Roles คือวิธีจัดระเบียบ Playbook ขนาดใหญ่ให้เป็นหน่วยย่อยที่นำกลับมาใช้ใหม่ได้ แทนที่จะเขียน tasks ทั้งหมดในไฟล์เดียว Role แยกงานออกเป็นโครงสร้างไดเรกทอรีมาตรฐานที่ประกอบด้วย tasks, handlers, templates, files, vars และ defaults
บทความนี้อธิบายโครงสร้าง Role, วิธีสร้างและใช้งาน, การส่ง variables เข้า Role, และ pattern ที่ใช้บ่อยสำหรับ Role ที่ดูแลรักษาง่าย
โครงสร้างไดเรกทอรีของ Role
Role มีโครงสร้างไดเรกทอรีมาตรฐานที่กำหนดโดย Ansible ไฟล์ใน main.yml ของแต่ละไดเรกทอรีจะถูกโหลดโดยอัตโนมัติ
roles/
└── nginx/
├── tasks/
│ └── main.yml # tasks หลักของ Role
├── handlers/
│ └── main.yml # handlers เช่น reload service
├── templates/
│ └── nginx.conf.j2 # Jinja2 templates
├── files/
│ └── index.html # ไฟล์ static สำหรับ copy
├── vars/
│ └── main.yml # variables ที่ override ไม่ได้ (priority สูง)
├── defaults/
│ └── main.yml # default variables (priority ต่ำ — override ได้)
└── meta/
└── main.yml # metadata เช่น dependencies
ความต่างระหว่าง vars/main.yml และ defaults/main.yml: ค่าใน defaults มี priority ต่ำที่สุดและถูก override ได้จากทุกที่ ส่วน vars มี priority สูงกว่า ใช้สำหรับค่าที่ Role ต้องการบังคับ
สร้าง Role ด้วย ansible-galaxy
คำสั่ง ansible-galaxy role init สร้างโครงสร้างไดเรกทอรีครบถ้วนโดยอัตโนมัติ ไม่ต้องสร้างทีละไดเรกทอรีเอง
# สร้าง Role ใหม่ชื่อ nginx
ansible-galaxy role init roles/nginx
# โครงสร้างที่สร้างมาให้:
# roles/nginx/
# ├── defaults/main.yml
# ├── files/
# ├── handlers/main.yml
# ├── meta/main.yml
# ├── README.md
# ├── tasks/main.yml
# ├── templates/
# ├── tests/
# │ ├── inventory
# │ └── test.yml
# └── vars/main.yml
ตัวอย่าง Role: nginx
ตัวอย่าง Role สำหรับติดตั้งและ configure nginx ประกอบด้วยไฟล์หลัก 4 ไฟล์
# roles/nginx/defaults/main.yml
nginx_port: 80
nginx_worker_processes: "auto"
nginx_server_name: "localhost"
nginx_web_root: /var/www/html
nginx_enable_ssl: false
# roles/nginx/tasks/main.yml
---
- name: Install nginx
package:
name: nginx
state: present
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: nginx -t -c %s
notify: reload nginx
- name: Ensure web root exists
file:
path: "{{ nginx_web_root }}"
state: directory
owner: www-data
group: www-data
mode: '0755'
- name: Start and enable nginx
service:
name: nginx
state: started
enabled: yes
# roles/nginx/handlers/main.yml
---
- name: reload nginx
service:
name: nginx
state: reloaded
- name: restart nginx
service:
name: nginx
state: restarted
ใช้งาน Role ใน Playbook
เรียกใช้ Role ด้วย key roles: หรือ ansible.builtin.include_role ใน task
---
# site.yml — ใช้ Role แบบ static
- name: Configure web servers
hosts: webservers
become: true
roles:
- role: nginx
vars:
nginx_port: 8080
nginx_server_name: "app.example.com"
nginx_enable_ssl: true
- role: certbot # Role อื่นในลำดับถัดไป
---
# ใช้ include_role แบบ dynamic (ใช้ใน task)
- name: Conditionally include role
hosts: all
tasks:
- name: Install nginx on web servers
include_role:
name: nginx
vars:
nginx_port: "{{ app_port }}"
when: server_role == "web"
Role Dependencies
Role สามารถกำหนด dependencies กับ Role อื่นได้ใน meta/main.yml โดย Ansible จะรัน dependency Role ก่อนโดยอัตโนมัติ
# roles/wordpress/meta/main.yml
---
dependencies:
- role: nginx
vars:
nginx_port: 80
- role: mysql
vars:
mysql_db_name: wordpress
mysql_db_user: wp_user
- role: php
vars:
php_version: "8.1"
เมื่อรัน Role wordpress ระบบจะรัน nginx, mysql, และ php ก่อนโดยอัตโนมัติตามลำดับ dependencies ที่กำหนด
แยก tasks ออกเป็นหลายไฟล์
Role ที่ซับซ้อนควรแยก tasks ออกเป็นหลายไฟล์ตาม concern แล้วใช้ include_tasks หรือ import_tasks ใน main.yml
# roles/nginx/tasks/main.yml
---
- name: Install packages
import_tasks: install.yml
- name: Configure nginx
import_tasks: configure.yml
- name: Setup SSL (if enabled)
include_tasks: ssl.yml
when: nginx_enable_ssl | bool
- name: Configure virtual hosts
include_tasks: vhosts.yml
when: nginx_vhosts is defined
ความต่างระหว่าง import_tasks และ include_tasks: import_tasks โหลดแบบ static ตอน parse (conditions ทำงานทีละ task), ส่วน include_tasks โหลดแบบ dynamic ตอน runtime (condition ทำงานกับทั้งไฟล์)
ติดตั้ง Role จาก Galaxy
Ansible Galaxy คือ repository ของ Community Roles ที่นำมาใช้ได้ทันทีโดยไม่ต้องเขียนเอง
# ติดตั้ง Role จาก Galaxy
ansible-galaxy role install geerlingguy.nginx
ansible-galaxy role install geerlingguy.mysql
# ติดตั้งทุก Role จากไฟล์ requirements.yml
ansible-galaxy role install -r requirements.yml
# requirements.yml — กำหนด Roles ที่ต้องการ
---
roles:
- name: geerlingguy.nginx
version: "3.2.0"
- name: geerlingguy.mysql
version: "4.3.0"
- name: my_custom_role
src: https://github.com/myorg/ansible-role-custom.git
scm: git
version: main
สรุป
Roles เปลี่ยน Playbook จากสคริปต์ยาวเป็นโครงสร้างที่อ่านง่ายและนำกลับมาใช้ซ้ำได้ Pattern ที่ควรจำ: ใช้ defaults/main.yml เสมอสำหรับ variables ที่ต้องการให้ผู้ใช้ override ได้, แยก tasks ออกเป็นไฟล์ย่อยเมื่อ Role มีมากกว่า 20 tasks, และ pin version ของ Galaxy Roles ใน requirements.yml เพื่อความ reproducible
Role ที่ดีคือ Role ที่ทำงานเดียวได้ดี (single responsibility) มี defaults ที่สมเหตุสมผล และ document ตัวแปรทั้งหมดใน defaults/main.yml ด้วย comment อธิบาย

