เรียนรู้ Ansible ตั้งแต่แนวคิด Agentless, Inventory, Ad-hoc Command และ Playbook ไปจนถึงการติดตั้ง NGINX และ Docker บน Ubuntu Server แบบอัตโนมัติ

#Ansible คืออะไร?

Ansible คือเครื่องมือ Open Source สำหรับงาน IT Automation, Configuration Management, Application Deployment และ Infrastructure Automation ช่วยให้ผู้ดูแลระบบและ DevOps Engineer สามารถจัดการ Server จำนวนมากจากเครื่องควบคุมเพียงเครื่องเดียว

จุดเด่นสำคัญของ Ansible คือแนวทาง Agentless โดยเครื่อง Linux ปลายทางไม่จำเป็นต้องติดตั้ง Ansible Agent เพิ่มเติม การเชื่อมต่อโดยทั่วไปใช้ SSH และกำหนดสถานะที่ต้องการผ่านไฟล์ Playbook ซึ่งเขียนด้วย YAML

แนวคิดโดยย่อ:

                 Ansible Control Node
                 +------------------+
                 |     Ansible      |
                 |   Playbook YAML  |
                 +--------+---------+
                          |
                         SSH
              +-----------+-----------+
              |           |           |
              v           v           v
          Server 01   Server 02   Server 03
           Ubuntu      Ubuntu      Ubuntu

#สิ่งที่ Ansible เหมาะสำหรับ

Ansible สามารถนำมาใช้กับงานหลายประเภท เช่น

  • ติดตั้ง Package และ Software
  • กำหนดค่า Web Server และ Application Server
  • สร้าง User และกำหนด Permission
  • จัดการไฟล์ Configuration
  • Deploy Application
  • เตรียม Server สำหรับ Docker และ Kubernetes
  • ทำงานร่วมกับ CI/CD Pipeline
  • จัดการ Server จำนวนมากด้วย Configuration ชุดเดียว
  • ทำ Infrastructure as Code (IaC)

#Workshop: เริ่มต้นใช้งาน Ansible

#เป้าหมาย

เมื่อจบ Workshop นี้ เราจะสามารถ

  1. ติดตั้ง Ansible บน Control Node
  2. เชื่อมต่อ Managed Node ผ่าน SSH
  3. สร้าง Inventory
  4. ใช้ Ansible Ad-hoc Command
  5. เขียน Ansible Playbook
  6. ติดตั้ง NGINX อัตโนมัติ
  7. ติดตั้ง Docker อัตโนมัติ
  8. ตรวจสอบว่า Playbook ทำงานแบบ Idempotent

#Architecture ที่ใช้

ตัวอย่างนี้ใช้ Server 3 เครื่อง

Server หน้าที่ IP ตัวอย่าง


ansible-control Control Node 192.168.1.10 web01 Managed Node 192.168.1.11 web02 Managed Node 192.168.1.12

เปลี่ยน IP address และชื่อผู้ใช้ให้ตรงกับระบบจริงของคุณ

ระบบปฏิบัติการตัวอย่าง: Ubuntu Server


#1. เตรียม Control Node

อัปเดต Package Index

sudo apt update

ติดตั้ง Ansible

sudo apt install ansible -y

ตรวจสอบเวอร์ชัน

ansible --version

หากติดตั้งสำเร็จจะเห็นข้อมูล Ansible Core, Python และตำแหน่ง Configuration File


#2. เตรียม SSH Key

Ansible จำเป็นต้องสามารถเข้าสู่ Managed Node ผ่าน SSH ได้

สร้าง SSH Key บน Control Node

ssh-keygen -t ed25519

กด Enter เพื่อใช้ค่ามาตรฐานตามขั้นตอน

จากนั้นส่ง Public Key ไปยัง Server ปลายทาง

ssh-copy-id ubuntu@192.168.1.11
ssh-copy-id ubuntu@192.168.1.12

ทดสอบ

ssh ubuntu@192.168.1.11

หากเข้าสู่ Server ได้โดยใช้ key authentication ก็พร้อมใช้งาน Ansible


#3. สร้าง Project

สร้าง Directory

mkdir ansible-workshop
cd ansible-workshop

โครงสร้างเริ่มต้น

ansible-workshop/
├── inventory.ini
├── ansible.cfg
├── ping.yml
├── nginx.yml
└── docker.yml

#4. สร้าง Inventory

สร้างไฟล์ inventory.ini

[webservers]
web01 ansible_host=192.168.1.11
web02 ansible_host=192.168.1.12

[webservers:vars]
ansible_user=ubuntu

Inventory ใช้ระบุว่า Ansible ต้องจัดการ Host ใดบ้าง และสามารถจัดกลุ่ม Host ตามบทบาทได้

ตรวจสอบ Inventory

ansible-inventory -i inventory.ini --graph

#5. สร้าง ansible.cfg

สร้างไฟล์ ansible.cfg

[defaults]
inventory = inventory.ini
host_key_checking = False

จากนั้นไม่จำเป็นต้องใส่ -i inventory.ini ในทุกคำสั่งเมื่อทำงานจาก Project นี้

host_key_checking = False สะดวกสำหรับ Lab แต่ใน Production ควรจัดการ SSH host keys อย่างเหมาะสมแทนการปิดการตรวจสอบโดยไม่จำเป็น


#6. ทดสอบการเชื่อมต่อ

ใช้ Ping Module

ansible all -m ping

ผลลัพธ์ที่คาดหวัง

web01 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

web02 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

ping ของ Ansible ไม่ใช่ ICMP ping แต่เป็นการทดสอบว่า Ansible สามารถเชื่อมต่อและเรียกใช้ module บนเครื่องปลายทางได้


#7. ทดลอง Ad-hoc Commands

ดู Hostname

ansible all -m command -a "hostname"

ดูพื้นที่ Disk

ansible all -m command -a "df -h"

ดู Memory

ansible all -m command -a "free -h"

ตรวจสอบ Uptime

ansible all -m command -a "uptime"

Ad-hoc Command เหมาะกับงานสั้น ๆ แต่ถ้าต้องการขั้นตอนที่ทำซ้ำได้และเก็บใน Version Control ควรใช้ Playbook


#8. Playbook แรก

สร้างไฟล์ ping.yml

---
- name: Test Ansible connection
  hosts: all

  tasks:
    - name: Ping managed nodes
      ansible.builtin.ping:

รัน

ansible-playbook ping.yml

ส่วนประกอบสำคัญคือ

  • name ชื่อ Play
  • hosts กลุ่มเครื่องเป้าหมาย
  • tasks รายการงาน
  • ansible.builtin.ping Module ที่ต้องการเรียกใช้

#9. Workshop: ติดตั้ง NGINX

สร้าง nginx.yml

---
- name: Install and configure NGINX
  hosts: webservers
  become: true

  tasks:
    - name: Update APT cache
      ansible.builtin.apt:
        update_cache: true
        cache_valid_time: 3600

    - name: Install NGINX
      ansible.builtin.apt:
        name: nginx
        state: present

    - name: Ensure NGINX is running
      ansible.builtin.service:
        name: nginx
        state: started
        enabled: true

ตรวจ Syntax

ansible-playbook nginx.yml --syntax-check

ทดลองดูสิ่งที่จะเปลี่ยน

ansible-playbook nginx.yml --check

รันจริง

ansible-playbook nginx.yml

ตรวจสอบสถานะ

ansible webservers -b -m command -a "systemctl is-active nginx"

จาก Browser สามารถทดลองเข้า

http://192.168.1.11
http://192.168.1.12

#10. Deploy หน้า Web ด้วย Ansible

สร้างไฟล์ index.html

<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <title>Ansible Workshop</title>
</head>
<body>
    <h1>Hello from Ansible</h1>
    <p>This server is configured automatically.</p>
</body>
</html>

เพิ่ม Task ลงใน nginx.yml

    - name: Deploy web page
      ansible.builtin.copy:
        src: index.html
        dest: /var/www/html/index.html
        owner: root
        group: root
        mode: "0644"

รันอีกครั้ง

ansible-playbook nginx.yml

หน้าเดียวกันจะถูก Deploy ไปยัง Web Server ทุกเครื่องในกลุ่ม webservers


#11. Workshop: ติดตั้ง Docker

สำหรับ Ubuntu รุ่นปัจจุบัน ควรติดตั้ง Docker จาก repository ทางการของ Docker แทนการพึ่ง package docker.io หากต้องการ Docker Engine รุ่นที่ Docker รองรับโดยตรง

สร้าง docker.yml

---
- name: Install Docker Engine
  hosts: webservers
  become: true

  tasks:
    - name: Install prerequisites
      ansible.builtin.apt:
        name:
          - ca-certificates
          - curl
        state: present
        update_cache: true

    - name: Create APT keyrings directory
      ansible.builtin.file:
        path: /etc/apt/keyrings
        state: directory
        mode: "0755"

    - name: Download Docker signing key
      ansible.builtin.get_url:
        url: https://download.docker.com/linux/ubuntu/gpg
        dest: /etc/apt/keyrings/docker.asc
        mode: "0644"

    - name: Add Docker repository
      ansible.builtin.apt_repository:
        repo: >-
          deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.asc]
          https://download.docker.com/linux/ubuntu
          {{ ansible_distribution_release }} stable
        filename: docker
        state: present

    - name: Install Docker packages
      ansible.builtin.apt:
        name:
          - docker-ce
          - docker-ce-cli
          - containerd.io
          - docker-buildx-plugin
          - docker-compose-plugin
        state: present
        update_cache: true

    - name: Ensure Docker is running
      ansible.builtin.service:
        name: docker
        state: started
        enabled: true

หาก Managed Nodes ไม่ใช่ amd64 ให้ปรับ architecture ใน repository ให้ตรงกับเครื่องจริง หรือพัฒนา Role ให้ตรวจ architecture อัตโนมัติ

รัน

ansible-playbook docker.yml

ตรวจสอบ

ansible webservers -b -m command -a "docker --version"

และ

ansible webservers -b -m command -a "docker compose version"

#12. ทำความเข้าใจ Idempotency

แนวคิดสำคัญของ Ansible คือ Idempotency กล่าวคือ เมื่อระบบอยู่ในสถานะที่ต้องการแล้ว การรัน Playbook ซ้ำไม่ควรสร้างการเปลี่ยนแปลงโดยไม่จำเป็น

ลองรัน

ansible-playbook nginx.yml

สองครั้ง

ครั้งแรกอาจพบ

changed=3

แต่เมื่อรันซ้ำโดยไม่มีการแก้ Configuration ควรเห็น Task จำนวนมากเป็น

changed=0

นี่เป็นข้อแตกต่างสำคัญระหว่างการเขียน Automation แบบ declarative ด้วย Module ของ Ansible กับการนำ Shell Script มารันซ้ำโดยไม่ตรวจสอบสถานะ


#13. Variables

สร้าง variables.yml

---
- name: Install packages using variables
  hosts: webservers
  become: true

  vars:
    web_package: nginx

  tasks:
    - name: Install web server
      ansible.builtin.apt:
        name: "{{ web_package }}"
        state: present
        update_cache: true

Ansible ใช้ Jinja expression เช่น

{{ web_package }}

เพื่ออ้างอิง Variable


#14. Handler

Handler เหมาะกับงานที่ควรเกิดขึ้นเมื่อ Configuration มีการเปลี่ยนแปลงเท่านั้น

---
- name: Configure NGINX
  hosts: webservers
  become: true

  tasks:
    - name: Copy NGINX configuration
      ansible.builtin.copy:
        src: nginx.conf
        dest: /etc/nginx/nginx.conf
        mode: "0644"
      notify: Restart NGINX

  handlers:
    - name: Restart NGINX
      ansible.builtin.service:
        name: nginx
        state: restarted

หากไฟล์ไม่เปลี่ยน Handler ก็ไม่จำเป็นต้อง Restart Service


#15. โครงสร้าง Project ที่ใหญ่ขึ้น

เมื่อระบบเริ่มซับซ้อน ควรแยกส่วนประกอบ

ansible-project/
├── ansible.cfg
├── inventory/
│   ├── development.ini
│   └── production.ini
├── group_vars/
│   └── webservers.yml
├── playbooks/
│   ├── nginx.yml
│   └── docker.yml
└── roles/
    ├── nginx/
    │   ├── tasks/
    │   ├── handlers/
    │   ├── templates/
    │   └── defaults/
    └── docker/
        └── tasks/

Role ช่วยแบ่ง Automation ออกเป็น Component ที่นำกลับมาใช้ซ้ำและดูแลรักษาง่ายขึ้น


#16. Ansible กับ DevOps

Ansible สามารถเป็นส่วนหนึ่งของ Pipeline ได้ เช่น

Developer
   |
   v
Git Repository
   |
   v
CI/CD Pipeline
   |
   v
Ansible Playbook
   |
   +----------+----------+
   |          |          |
   v          v          v
Server 01  Server 02  Server 03

ตัวอย่าง Workflow คือ

Git Push
   ↓
Run Tests
   ↓
Build Artifact / Container
   ↓
Run Ansible
   ↓
Configure Server
   ↓
Deploy Application

จึงสามารถใช้ Ansible ร่วมกับ GitHub Actions, GitLab CI/CD หรือ Jenkins ได้


#17. คำสั่งที่ควรรู้

คำสั่ง การใช้งาน


ansible --version ตรวจสอบ Ansible ansible all -m ping ทดสอบ Connection ansible-inventory --graph แสดง Inventory ansible all -m command -a "uptime" รันคำสั่ง ansible-playbook site.yml รัน Playbook ansible-playbook site.yml --syntax-check ตรวจ Syntax ansible-playbook site.yml --check Check Mode ansible-playbook site.yml --list-tasks แสดง Tasks ansible-playbook site.yml --limit web01 จำกัด Host ansible-playbook site.yml -v เพิ่มรายละเอียด Output


#18. สิ่งที่ควรเรียนต่อ

หลังจากเข้าใจ Workshop นี้ หัวข้อที่ควรศึกษาต่อคือ

Inventory → Variables → Facts → Templates → Handlers → Roles → Ansible Vault → Collections → Dynamic Inventory → CI/CD Integration

โดยเฉพาะ Ansible Vault สำหรับจัดการข้อมูลลับ และ Roles สำหรับออกแบบ Automation ที่นำกลับมาใช้ซ้ำได้


#สรุป

Ansible ช่วยเปลี่ยนกระบวนการจาก

SSH → Login → Install → Configure → Restart
SSH → Login → Install → Configure → Restart
SSH → Login → Install → Configure → Restart

ให้กลายเป็น

ansible-playbook site.yml

แนวคิดสำคัญไม่ใช่เพียงการลดจำนวนคำสั่ง แต่คือการทำให้ Infrastructure และ Configuration สามารถนิยามเป็นโค้ด ทำซ้ำ ตรวจสอบ และเก็บ Version ได้

สำหรับผู้เริ่มต้น เส้นทางที่แนะนำคือเริ่มจาก Inventory และ Ad-hoc Commands แล้วจึงพัฒนาไปสู่ Playbook, Variables, Handlers และ Roles ก่อนนำไปเชื่อมต่อกับ CI/CD และ Cloud Infrastructure ในระบบจริง