Infrastructure as Code: จัดการ Config Server ด้วย Git บน VPS

Infrastructure as Code (IaC) คืออะไร

Infrastructure as Code (IaC) เป็นการจัดการทรัพยากร Infrastructure (เซิร์ฟเวอร์ เครือข่าย หน่วยเก็บข้อมูล) ด้วยการเขียนโค้ด แทนการตั้งค่าด้วยมือผ่านหน้าควบคุม IaC ช่วยให้การจัดการโครงสร้างพื้นฐานเป็นเรื่องที่ทำซ้ำได้ ติดตามได้ และปรับปรุงได้อย่างสม่ำเสมอ โดยใช้เครื่องมือเช่น Terraform, Ansible, Docker Compose และ Kubernetes Manifests

ประโยชน์หลักของ IaC คือการควบคุมเวอร์ชัน (Version Control) ของการตั้งค่า Infrastructure ให้คุณสามารถ track การเปลี่ยนแปลง ทำให้ audit trail ชัดเจน และสามารถ rollback ได้เมื่อจำเป็น เมื่อใช้ ผู้ให้บริการโฮสติ้ง Cloud VPS คุณจะเห็นว่า IaC ช่วยลดข้อผิดพลาดของมนุษย์และเพิ่มความสม่ำเสมอของการ deploy

ปัญหาของการ Config Server ด้วยมือ

ก่อนที่จะนำ IaC มาใช้ การตั้งค่า Server มักทำด้วยมือผ่านคำสั่ง SSH หรือ CLI ซึ่งนำมาซึ่งปัญหาต่างๆ ดังนี้

  • Snowflake Server: Server ที่ถูกตั้งค่าด้วยมือมักมีลักษณะเฉพาะตัว ทำให้ยากที่จะสร้าง Server เหมือนเดิมอีกครั้ง
  • Human Error: การตั้งค่าด้วยมือเสี่ยงต่อความผิดพลาด เช่น พิมพ์ผิดคำสั่ง หรืออธิบายขั้นตอนไม่สมบูรณ์
  • ไม่มีการ Audit Trail: ไม่ทราบว่าใครเปลี่ยนแปลงอะไร และเมื่อไร
  • ยากต่อการ Scale: เมื่อต้องการสร้าง Server หลายตัว การทำด้วยมือจึงกลายเป็นการใช้เวลามากและซ้ำซาก

Git เป็น Version Control สำหรับ Infrastructure Config

Git ซึ่งเป็น Version Control System ที่นิยมใช้กับ Source Code ก็สามารถนำมาใช้กับ Infrastructure Configuration ได้เช่นกัน โดยการเก็บไฟล์ Configuration ต่างๆ เช่น nginx.conf, systemd services, firewall rules และ docker-compose.yml ลงในระบบ Version Control

ประโยชน์ของการใช้ Git กับ Infrastructure Config:

  • ดูประวัติการเปลี่ยนแปลงของแต่ละ Configuration ได้เต็มที่
  • สามารถ Rollback ไปยัง Configuration เดิมได้ง่าย
  • ทีมสามารถ Collaborate ผ่าน Pull Request และ Code Review
  • สร้าง CI/CD Pipeline เพื่อ Automate Deployment

โครงสร้างโฟลเดอร์สำหรับ Infrastructure Repository

การสร้าง Repository ที่มีโครงสร้างดีทำให้ง่ายต่อการจัดการ Configuration

infrastructure/
├── .gitignore
├── README.md
├── terraform/
│   ├── main.tf
│   ├── variables.tf
│   ├── outputs.tf
│   ├── production.tfvars
│   └── staging.tfvars
├── ansible/
│   ├── playbooks/
│   │   ├── site.yml
│   │   ├── web.yml
│   │   └── db.yml
│   ├── roles/
│   │   ├── nginx/
│   │   ├── docker/
│   │   └── monitoring/
│   └── inventory/
│       ├── production
│       └── staging
├── docker/
│   ├── web-server/
│   │   └── Dockerfile
│   └── docker-compose.yml
├── configs/
│   ├── nginx.conf
│   ├── systemd/
│   │   ├── app.service
│   │   └── app.timer
│   └── firewall/
│       └── ufw-rules.sh
└── ci-cd/
    └── .github/workflows/
        └── deploy.yml

ตัวอย่าง: เก็บ Nginx Config ใน Git และ Deploy

ตัวอย่างนี้แสดงวิธีการเก็บ nginx.conf ใน Git และ Deploy โดยใช้ Ansible

# configs/nginx.conf
server {
    listen 80;
    server_name api.de.co.th;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /health {
        access_log off;
        return 200 "OK";
    }
}

# ansible/playbooks/nginx.yml
---
- hosts: web_servers
  become: yes
  tasks:
    - name: Install Nginx
      apt:
        name: nginx
        state: present

    - name: Copy Nginx config from Git
      copy:
        src: ../configs/nginx.conf
        dest: /etc/nginx/sites-available/default
        owner: root
        group: root
        mode: 0644
      notify: restart nginx

    - name: Test Nginx configuration
      command: nginx -t
      register: nginx_test

    - name: Show test result
      debug:
        var: nginx_test.stderr_lines

  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

# Deploy
cd infrastructure
git pull origin main
ansible-playbook ansible/playbooks/nginx.yml -i ansible/inventory/production

Terraform เบื้องต้น: จัดการ Cloud Infrastructure ด้วย Code

Terraform เป็น Infrastructure as Code Tool ที่ช่วยให้คุณสามารถ Define Infrastructure ในรูปแบบ Configuration Files แล้ว Deploy ได้ง่ายๆ

# terraform/main.tf
provider "aws" {
  region = "ap-southeast-1"
}

resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  key_name      = "my-key"
  
  tags = {
    Name        = "de-web-server"
    Environment = "production"
    CreatedBy   = "Terraform"
  }
}

resource "aws_security_group" "allow_web" {
  name = "allow_web_traffic"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# Deploy
terraform init
terraform plan
terraform apply

# Destroy
terraform destroy

Ansible เบื้องต้น: Configure VPS ด้วย Playbook

หลังจากที่ Terraform สร้าง Infrastructure แล้ว Ansible ช่วยในการตั้งค่า (Configuration) ของแต่ละ Server

# ansible/playbooks/site.yml
---
- hosts: all
  become: yes
  roles:
    - common
    - security

- hosts: web_servers
  become: yes
  roles:
    - docker
    - nginx
    - app

- hosts: db_servers
  become: yes
  roles:
    - postgresql

# ansible/roles/common/tasks/main.yml
---
- name: Update and upgrade packages
  apt:
    update_cache: yes
    upgrade: dist

- name: Install essential tools
  apt:
    name:
      - curl
      - wget
      - git
      - tmux
      - htop
    state: present

- name: Set timezone
  timezone:
    name: Asia/Bangkok

# Run playbook
ansible-playbook ansible/playbooks/site.yml -i ansible/inventory/production

# Run with verbose output
ansible-playbook ansible/playbooks/site.yml -i ansible/inventory/production -v

GitOps: Git เป็น Single Source of Truth

GitOps คือแนวคิดที่ใช้ Git Repository เป็น Single Source of Truth สำหรับการตั้งค่า Infrastructure ทั้งหมด เมื่อมีการเปลี่ยนแปลงใน Git Repository Automated Pipeline จะตรวจเห็นและ Deploy โดยอัตโนมัติ

# .github/workflows/deploy.yml
name: Deploy Infrastructure
on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  terraform:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v2
      
      - name: Terraform Format Check
        run: terraform fmt -check
      
      - name: Terraform Plan
        run: terraform plan -no-color
      
      - name: Terraform Apply
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: terraform apply -auto-approve

  ansible:
    needs: terraform
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main' && github.event_name == 'push'
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Ansible
        run: |
          python -m pip install ansible
      
      - name: Run Playbooks
        run: |
          ansible-playbook ansible/playbooks/site.yml -i ansible/inventory/production

Best Practices: Secret Management และ .gitignore

เมื่อใช้ Git กับ Infrastructure Configuration ต้องระวังไม่ให้ Sensitive Data เช่น Passwords API Keys และ Certificates ถูก Commit ลง Repository

# .gitignore
# Terraform state files
terraform.tfstate
terraform.tfstate.*
.terraform/
.terraform.lock.hcl

# Sensitive files
.env
*.key
*.pem
*.crt
secrets/
.vault-pass

# Editor
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Ansible
ansible/*.retry

# Best practice: Use environment variables or secure vaults
export TF_VAR_db_password=$(aws secretsmanager get-secret-value \
  --secret-id prod/db/password \
  --query SecretString \
  --output text)

# Or use HashiCorp Vault
vault kv get secret/database/password
# 1. Clone repository
git clone https://github.com/dotenterprise/infrastructure.git
cd infrastructure

# 2. สร้าง feature branch
git checkout -b feature/upgrade-nginx-ssl

# 3. แก้ไข Configuration
vi configs/nginx.conf
vi ansible/playbooks/ssl.yml

# 4. Validate configuration
terraform fmt
terraform validate
ansible-playbook ansible/playbooks/ssl.yml --syntax-check

# 5. Commit และ push
git add .
git commit -m "Add SSL certificate for api.de.co.th"
git push origin feature/upgrade-nginx-ssl

# 6. สร้าง Pull Request สำหรับ Code Review
# ที่ GitHub หรือ GitLab

# 7. Merge เมื่อได้ Approval
git checkout main
git pull origin main
git merge feature/upgrade-nginx-ssl
git push origin main

# 8. CI/CD Pipeline จะ trigger โดยอัตโนมัติ
# GitHub Actions / GitLab CI จะ run:
#   - Terraform plan/apply
#   - Ansible playbooks

# 9. ตรวจสอบใน Production
ssh [email protected] "systemctl status nginx"
curl -I https://api.de.co.th

สรุป

Infrastructure as Code คือหลักการสำคัญของ Modern DevOps ที่ช่วยให้การจัดการ Infrastructure เป็นเรื่องที่เหมือนกับการจัดการ Source Code โดยใช้ Git เป็น Single Source of Truth ทีมของคุณสามารถ Collaborate ได้ดีขึ้น ลดความเสี่ยงของความผิดพลาด และเพิ่มความเร็วในการ Deploy ซอฟต์แวร์

เมื่อใช้ ผู้ให้บริการโฮสติ้ง Cloud VPS สามารถนำ IaC มาใช้ได้โดยง่าย เพราะ VPS นั้น Support Terraform Ansible และ Docker Compose ได้ทั้งหมด ให้คุณมี Infrastructure ที่ Scalable Reliable และ Maintainable