ตัวแปรใน Ansible ช่วยให้ playbook เดียวทำงานต่างกันในแต่ละ server ได้ ไม่ว่าจะเป็น port, path, หรือค่า config ที่แตกต่างกันระหว่าง production กับ staging การเข้าใจวิธีกำหนด host_vars และ group_vars อย่างถูกต้องช่วยให้ playbook อ่านง่าย maintain ได้ดี และขยายระบบได้โดยไม่ต้องแก้ logic หลัก
บทความนี้อธิบายการใช้งาน host_vars และ group_vars ทั้งแบบ inline ในไฟล์ inventory และแบบแยกโฟลเดอร์ พร้อมลำดับความสำคัญของตัวแปรที่ต้องเข้าใจก่อนออกแบบโครงสร้างโปรเจกต์
ประเภทของ Variables
ตัวแปรใน Ansible แบ่งตามขอบเขตการใช้งานได้ 2 ระดับหลัก ได้แก่ host variables ที่ใช้เฉพาะกับ server เครื่องนั้น และ group variables ที่ใช้กับทุก server ในกลุ่มนั้น การเลือกระดับที่ถูกต้องช่วยลดการซ้ำซ้อนและทำให้ config อ่านเข้าใจง่ายขึ้น
Inline Variables ใน Inventory File
วิธีที่ง่ายที่สุดคือกำหนด variable ตรงใน inventory file ตามหลัง hostname ในรูปแบบ key=value
# inventory.ini
[webservers]
web1.example.com http_port=80 max_connections=200
web2.example.com http_port=8080 max_connections=100
[dbservers]
db1.example.com db_port=5432
# group variables สำหรับทุก host ใน webservers
[webservers:vars]
app_user=www-data
document_root=/var/www/html
# variables สำหรับทุก host ในระบบ
[all:vars]
ntp_server=time.google.com
ansible_user=ubuntu
วิธีนี้เหมาะสำหรับโปรเจกต์เล็กที่มี host ไม่มาก เพราะทุกอย่างอยู่ในไฟล์เดียว แต่เมื่อ inventory ขยายใหญ่ขึ้น การแยกออกมาเป็นโฟลเดอร์แยกจะ maintain ได้ง่ายกว่า
โครงสร้างโฟลเดอร์ host_vars และ group_vars
วิธีมาตรฐานที่แนะนำสำหรับโปรเจกต์ขนาดกลางขึ้นไปคือสร้างโฟลเดอร์ host_vars/ และ group_vars/ ในโฟลเดอร์โปรเจกต์ โดยระบบจะค้นหาไฟล์ใน path เหล่านี้อัตโนมัติ
project/
├── inventory.ini
├── group_vars/
│ ├── all.yml # ตัวแปรสำหรับทุก host
│ ├── webservers.yml # ตัวแปรสำหรับ group webservers
│ └── dbservers.yml # ตัวแปรสำหรับ group dbservers
├── host_vars/
│ ├── web1.example.com.yml # ตัวแปรเฉพาะของ web1
│ └── db1.example.com.yml # ตัวแปรเฉพาะของ db1
└── site.yml
ตัวอย่างไฟล์ group_vars
แต่ละไฟล์ใน group_vars/ ใช้รูปแบบ YAML ธรรมดา โดยชื่อไฟล์ต้องตรงกับชื่อ group ใน inventory
# group_vars/all.yml — ใช้กับทุก host
ntp_server: time.google.com
timezone: Asia/Bangkok
ansible_user: ubuntu
# group_vars/webservers.yml — ใช้เฉพาะ webservers group
http_port: 80
document_root: /var/www/html
app_user: www-data
worker_processes: auto
# group_vars/dbservers.yml — ใช้เฉพาะ dbservers group
db_port: 5432
db_max_connections: 100
backup_dir: /var/backups/postgres
ตัวอย่างไฟล์ host_vars
ไฟล์ใน host_vars/ ชื่อต้องตรงกับ hostname หรือ alias ที่กำหนดใน inventory
# host_vars/web1.example.com.yml
http_port: 80
server_alias: www.example.com
ssl_enabled: true
# host_vars/web2.example.com.yml
http_port: 8080
server_alias: staging.example.com
ssl_enabled: false
แยกโฟลเดอร์ย่อยสำหรับ Group ที่ซับซ้อน
สำหรับ group ที่มีตัวแปรจำนวนมาก สามารถสร้างโฟลเดอร์ย่อยแทนไฟล์เดียว ระบบจะอ่านไฟล์ทุกไฟล์ใน path นั้นอัตโนมัติ
group_vars/
└── webservers/
├── main.yml # ค่าพื้นฐาน
├── ssl.yml # ค่า SSL
└── firewall.yml # ค่า firewall rules
วิธีนี้ทำให้แบ่ง config ตามหัวข้อได้ชัดเจนขึ้น และแต่ละไฟล์มีขนาดเล็กลง ง่ายต่อการ review และ merge ใน version control
ลำดับความสำคัญของ Variables (Precedence)
เมื่อตัวแปรเดียวกันถูกกำหนดในหลายที่ ระบบจะใช้ค่าจากแหล่งที่มีความสำคัญสูงกว่า ลำดับจากต่ำไปสูง (ค่าที่กำหนดทีหลังชนะ) มีดังนี้
- group_vars/all — ความสำคัญต่ำสุด ใช้สำหรับ default ของทั้งระบบ
- group_vars/[groupname] — ใช้กับ host ในกลุ่มนั้น
- host_vars/[hostname] — ใช้เฉพาะ host นั้น override ค่า group ได้
- vars ใน play/task — กำหนดใน playbook โดยตรง
- extra_vars (-e) — ส่งผ่าน command line ความสำคัญสูงสุด override ทุกอย่าง
# ตัวอย่าง: http_port ถูกกำหนดในหลายที่
# group_vars/all.yml → http_port: 80 (default)
# group_vars/webservers.yml → http_port: 443 (override all)
# host_vars/web2.yml → http_port: 8080 (override group)
# ผลลัพธ์: web2 จะใช้ port 8080, web อื่นในกลุ่มใช้ 443
ใช้ Variables ใน Playbook
ตัวแปรที่กำหนดใน host_vars หรือ group_vars พร้อมใช้งานใน playbook ผ่าน Jinja2 template syntax โดยอัตโนมัติ
# site.yml
- name: Configure web server
hosts: webservers
tasks:
- name: Set nginx port
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
vars:
listen_port: "{{ http_port }}"
- name: Create document root
file:
path: "{{ document_root }}"
state: directory
owner: "{{ app_user }}"
ตรวจสอบ Variables ที่ Host รับ
ใช้คำสั่งนี้เพื่อดูตัวแปรทั้งหมดที่ host แต่ละเครื่องจะได้รับ รวมถึง source ที่มาของแต่ละค่า
# ดู variables ทั้งหมดของ host
ansible-inventory -i inventory.ini --host web1.example.com
# รัน debug module เพื่อดู variables จาก playbook
ansible webservers -m debug -a "var=http_port" -i inventory.ini
สรุป
host_vars และ group_vars เป็นกลไกหลักในการจัดการ configuration ที่แตกต่างกันในแต่ละ server โดยไม่ต้องแก้ playbook หลัก การใช้โฟลเดอร์แยกแทน inline variables ทำให้โปรเจกต์ scale ได้ดีกว่าในระยะยาว สิ่งสำคัญคือต้องเข้าใจลำดับ precedence เพื่อออกแบบโครงสร้างตัวแปรได้ถูกต้องตั้งแต่ต้น

