เขียน Ansible Playbook ติดตั้ง Web Server บน Cloud VPS อัตโนมัติ

Ansible Playbook เป็นไฟล์ configuration ที่ช่วยให้คุณติดตั้ง Web Server เช่น Nginx หรือ Apache บน Cloud VPS อัตโนมัติ โดยไม่ต้องเข้า SSH และพิมพ์คำสั่งด้วยมือ ซึ่งทำให้กระบวนการ provisioning server เร็วและลดข้อผิดพลาดของมนุษย์ บทความนี้จะอธิบายวิธีการเขียน Ansible Playbook สำหรับติดตั้ง Nginx บน Cloud VPS ของ ผู้ให้บริการโฮสติ้ง

Ansible Playbook คืออะไร

Ansible Playbook เป็นไฟล์ YAML ที่กำหนดชุดของคำสั่ง (tasks) ที่ต้องทำงานบน remote servers โดยแต่ละ task จะเรียกใช้ Ansible modules เพื่อทำการต่างๆ เช่น การติดตั้ง packages, การแก้ไข configuration files, การ restart services เป็นต้น ด้วยการใช้ Playbook คุณสามารถ automate กระบวนการ provisioning server ได้อย่างมีประสิทธิภาพ

โครงสร้าง Ansible Playbook ที่เหมาะสำหรับ Web Server

Playbook ที่ดีจะมีโครงสร้างที่ชัดเจน ประกอบด้วยส่วนหลัก 3 ส่วน คือ 1) Variables – ตัวแปรที่ใช้ในไฟล์ 2) Tasks – รายการงานที่ต้องทำ 3) Handlers – รหัสที่ถูก trigger เมื่อมีการเปลี่ยนแปลง เช่นการ restart service เมื่อ configuration file มีการแก้ไข

---
- name: Install and configure Nginx on Cloud VPS
  hosts: webservers
  become: yes
  
  vars:
    nginx_port: 80
    nginx_user: www-data
    app_name: myapp
  
  tasks:
    - name: Update package manager
      apt:
        update_cache: yes
        cache_valid_time: 3600
    
    - name: Install Nginx
      apt:
        name: nginx
        state: present
    
    - name: Create Nginx configuration for application
      template:
        src: nginx.conf.j2
        dest: "/etc/nginx/sites-available/{{ app_name }}"
        backup: yes
      notify: restart nginx
    
    - name: Enable Nginx site
      file:
        src: "/etc/nginx/sites-available/{{ app_name }}"
        dest: "/etc/nginx/sites-enabled/{{ app_name }}"
        state: link
      notify: restart nginx
    
    - name: Remove default Nginx site
      file:
        path: /etc/nginx/sites-enabled/default
        state: absent
      notify: restart nginx
    
    - name: Ensure Nginx is running and enabled
      service:
        name: nginx
        state: started
        enabled: yes
  
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

Tasks, Handlers และ Variables

Tasks คือรายการของการกระทำที่ Ansible จะทำบน remote server ตามลำดับ Handlers เป็นงานพิเศษที่ trigger เฉพาะเมื่อมีการบอก notify ซึ่งเหมาะสำหรับการ restart services Variables ช่วยให้ Playbook สามารถนำกลับมาใช้ได้ (reusable) โดยการ define ค่าต่างๆ เพียงครั้งเดียว แล้วใช้งานได้หลายครั้ง

---
- name: Install Apache Web Server
  hosts: all
  become: yes
  
  vars:
    apache_port: 80
    apache_service: apache2
    doc_root: /var/www/html
  
  tasks:
    - name: Update package cache (Ubuntu)
      apt:
        update_cache: yes
      when: ansible_os_family == "Debian"
    
    - name: Install Apache
      apt:
        name: apache2
        state: present
    
    - name: Enable Apache modules
      apache2_module:
        name: "{{ item }}"
        state: present
      loop:
        - rewrite
        - proxy
        - ssl
      notify: restart apache
    
    - name: Create virtual host configuration
      template:
        src: vhost.conf.j2
        dest: "/etc/apache2/sites-available/{{ app_name }}.conf"
      notify: restart apache
    
    - name: Enable virtual host
      command: "a2ensite {{ app_name }}"
      notify: restart apache
  
  handlers:
    - name: restart apache
      service:
        name: "{{ apache_service }}"
        state: restarted
    
    - name: reload apache
      service:
        name: "{{ apache_service }}"
        state: reloaded

Jinja2 Templates สำหรับ Configuration Files

Jinja2 templates ช่วยให้คุณสร้าง configuration files ที่ dynamic โดยการใช้ variables และ loops ตัวอย่างเช่น การสร้าง Nginx configuration file ที่ต่างกันสำหรับ servers ต่างๆ โดยใช้ค่า variables ที่ define ไว้ใน Playbook

# nginx.conf.j2
server {
    listen {{ nginx_port }};
    server_name {{ server_name }};
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # SSL configuration
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/{{ server_name }}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/{{ server_name }}/privkey.pem;
}

# playbook.yml
- name: Configure Nginx with SSL
  hosts: webservers
  become: yes
  
  vars:
    nginx_port: 80
    server_name: example.com
  
  tasks:
    - name: Install certbot
      apt:
        name: certbot
        state: present
    
    - name: Deploy Nginx config from template
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/sites-available/default
      notify: restart nginx
  
  handlers:
    - name: restart nginx
      service:
        name: nginx
        state: restarted

Error Handling และ Conditional Tasks

Ansible Playbook มี capabilities ในการจัดการกับ errors และ conditional execution ของ tasks ด้วยคำสั่ง when, failed_when, changed_when และ handlers คุณสามารถทำให้ Playbook มีความ flexible และ robust มากขึ้น

---
- name: Web Server Setup with Error Handling
  hosts: all
  become: yes
  
  tasks:
    - name: Check if server is already configured
      stat:
        path: /etc/nginx/sites-available/configured
      register: nginx_configured
    
    - name: Install dependencies
      apt:
        name: "{{ item }}"
        state: present
      loop:
        - curl
        - wget
        - git
      when: not nginx_configured.stat.exists
    
    - name: Install Nginx
      apt:
        name: nginx
        state: present
      register: nginx_install
      when: not nginx_configured.stat.exists
    
    - name: Check Nginx status
      command: systemctl is-active nginx
      register: nginx_status
      changed_when: false
      failed_when: false
    
    - name: Start Nginx if not running
      service:
        name: nginx
        state: started
      when: nginx_status.rc != 0
    
    - name: Create marker file
      file:
        path: /etc/nginx/sites-available/configured
        state: touch
      when: nginx_install.changed
    
    - name: Verify installation
      assert:
        that:
          - nginx_install is succeeded or not nginx_configured.stat.exists
        fail_msg: "Nginx installation failed"
        success_msg: "Nginx installed successfully"

Running Playbooks บน Cloud VPS

การรัน Ansible Playbook บน Cloud VPS ของ ผู้ให้บริการโฮสติ้ง ทำได้ง่ายๆ โดยการ execute คำสั่ง ansible-playbook ที่ชี้ไปยัง playbook file และ inventory file ที่ระบุ servers ต่างๆ

# inventory.ini
[webservers]
web1.example.com ansible_user=ubuntu ansible_private_key_file=~/.ssh/id_rsa
web2.example.com ansible_user=ubuntu ansible_private_key_file=~/.ssh/id_rsa
web3.example.com ansible_user=ubuntu ansible_private_key_file=~/.ssh/id_rsa

[all:vars]
ansible_python_interpreter=/usr/bin/python3

# รัน playbook
ansible-playbook -i inventory.ini playbook.yml

# รัน playbook กับ verbose output
ansible-playbook -i inventory.ini playbook.yml -v

# รัน playbook เฉพาะ specific hosts
ansible-playbook -i inventory.ini playbook.yml --limit web1.example.com

# รัน playbook เฉพาะ specific tags
ansible-playbook -i inventory.ini playbook.yml --tags "install"

Best Practices สำหรับ Ansible Playbooks

1. ใช้ descriptive names สำหรับ tasks 2. เก็บ Playbooks ใน version control (Git) 3. ใช้ variables สำหรับค่าที่เปลี่ยนแปลง 4. ใช้ roles เพื่อ organize Playbooks ที่ซับซ้อน 5. ทำการ test Playbooks ก่อน deploy ไปยัง production 6. ใช้ handlers เพื่อ restart services เมื่อมีการเปลี่ยนแปลง

สรุป

Ansible Playbook เป็นเครื่องมือที่มีประสิทธิภาพสำหรับการ automate การติดตั้ง และตั้งค่า Web Server บน Cloud VPS โดยการใช้ Playbooks คุณสามารถ provision multiple servers ได้อย่างรวดเร็ว และลดความผิดพลาดของมนุษย์ Cloud VPS ของ ผู้ให้บริการโฮสติ้ง (https://de.co.th/cloud-vps) เป็น platform ที่เหมาะสำหรับการ host web servers ที่จัดการด้วย Ansible Playbooks