Playbook là thành phần cốt lõi trong Ansible. Nó là cách phổ biến nhất để miêu tả quá trình làm việc tự động một cách dễ dàng và có tổ chức. Ansible Playbook là một tệp YAML chứa các chỉ dẫn (các nhiệm vụ cần thực hiện) cho Ansible. Playbook bao gồm nhiều “play” – mỗi play là một tập hợp các nhiệm vụ cần thực hiện trên một nhóm máy chủ cụ thể.
Sơ lược về YAML
YAML – YAML Ain’t Markup Language, là ngôn ngữ tuần tự hóa dữ liệu (Data Serialization Language), giúp con người dễ đọc hiểu, tương tự như JSON và XML. Nó sử dụng định dạng thụt đầu dòng (giống Python) để xác định cấu trúc.
Thường được sử dụng cho các file cấu hình (configuration files) nhưng cũng có thể được sử dụng cho những mục đích khác như lưu các file log, giao tiếp liên tiến trình (interprocess communication), trao đổi chéo dữ liệu, toàn vẹn đối tượng (object persistence) hoặc gỡ rối 1 cấu trúc dữ liệu phức tạp.
Tệp thường bắt đầu với ---. Các chú thích, comment sẽ được bắt đầu bằng #.
Có 3 kiểu để biểu diễn giá trị trong YAML:
Key Value Pair (Cặp khoá – giá trị)
– Cú pháp đơn giản nhất.
– Trong YAML, khóa và giá trị được phân tách bằng dấu hai chấm (:), luôn phải có khoảng trắng theo sau dấu hai chấm.
– Các phần tử trong mảng sẽ được thể hiện bởi dấu gạch ngang (-).
– Cần có khoảng trắng trước mỗi mục.
– Số lượng khoảng trắng cần bằng nhau trước các phần tử của một mảng.
Ví dụ:
tasks: - install httpd - start httpd
Dictionary (Từ điển)
– Cấu trúc lồng nhau với nhiều cấp độ.
– Sử dụng thụt lề để thể hiện quan hệ cha-con.
→ Tùy theo mục đích sử dụng để chọn kiểu biểu diễn file YAML sao cho phù hợp.
Cấu trúc một playbook
Một Playbook trong Ansible thường được chia thành 3 phần cơ bản:
Phần đầu (Metadata)
Khai báo các groups servers cần thực hiện cũng như các biến, facts, phân quyền sudo,…
Một vài thông số điển hình như sau:
gather_facts: Lựa chọn thu thập thông tin hệ thống từ các host.
hosts: Chỉ định nhóm hoặc máy chủ mục tiêu trong inventory.
vars hoặc vars_files: Khai báo biến toàn cục hoặc từ file bên ngoài.
become: Xác định quyền sudo nếu cần.
Phần thân (Tasks)
Phần này chứa danh sách các tasks (tác vụ) mà Ansible sẽ thực thi. Đây là phần chính của Playbook và được tổ chức dưới dạng danh sách các module và tham số.
Mỗi task sẽ bao gồm tên, module và các tham số cần thiết.
Có thể sử dụng điều kiện (when), vòng lặp (with_items), hoặc xử lý lỗi (ignore_errors).
Phần cuối (Handlers) (Không bắt buộc)
Được sử dụng khi một hoặc nhiều tasks thay đổi trạng thái. Chúng thường được dùng để khởi động lại dịch vụ, cập nhật file log hoặc thực thi các tác vụ cần thiết khác sau khi task được thực hiện.
Handlers chỉ được gọi khi task có trạng thái changed.
Handlers được khai báo trong một mục riêng với tên giống như callback.
Playbook minh hoạ
Dưới đây mình sẽ minh hoạ một playbook đơn giản thực hiện cài đặt, triển khai cấu hình Apache và upload website tĩnh trên 2 remote servers sử dụng Ubuntu 24.
---- hosts: all become: yes gather_facts: no vars: http_port: 1808 vars_prompt: - name: yours_name prompt: Type yours name?
hosts: all: áp dụng Playbook cho tất cả các máy chủ trong danh sách inventory.
become: yes: chạy các lệnh với quyền sudo.
gather_facts: no: Nếu không cần thu thập thông tin của remote servers, hay không cần sử dụng các biến mặc định, bạn thiết lập No để ansible playbook bỏ qua phần này, giúp tiết kiệm thời gian thực thi.
vars: khai báo biến.
http_port: Định nghĩa port Apache sẽ sử dụng là port 1808. Biến này nằm trong file port.j2 được khai báo bên dưới. Mục đích khi cần thay đổi port Apache cho các servers, ta chỉ cần thay đổi giá trị của biến trong playbook.
vars_prompt: yêu cầu người dùng nhập giá trị đầu vào khi chạy Playbook.
yours_name: Biến này nằm trong file index.j2.
Phần thân:
Sử dụng module apt để đảm bảo Apache được cài đặt trên hệ thống:
- name: Ensure that Apache is installed apt: name: apache2 state: present
Khởi động Apache và bật tự động chạy service khi máy chủ khởi động:
- name: Start Apache service service: name: apache2 state: started enabled: yes
→ Module template dùng để tạo file cấu hình động bằng cách sử dụng các biến. Nó sử dụng Jinja2 để render file từ một template .j2 và lưu vào máy remote.
Mình sẽ sử dụng module này để triển khai file cấu hình port Apache từ đường dẫn /root/templates/ports.j2 (trên control server) sang /etc/apache2/ports.conf (trên remote servers). Nếu file ports.conf đã tồn tại và không thay đổi, Ansible sẽ không ghi đè.
backup: yes: tạo bản sao lưu nếu có sự thay đổi so với file gốc trước đó trên remote servers.
notify: Kích hoạt handler để khởi động lại Apache nếu có sự thay đổi.
Triển khai file website:
- name: Copy site files template: src: /root/templates/index.j2 dest: /var/www/html/index.html
→ Copy file giao diện website (index.j2) vào thư mục web /var/www/html/index.html.
Phần cuối
Nếu cấu hình Apache bị thay đổi, handler sẽ được gọi để khởi động lại Apache.
→ Khi chạy lệnh, Ansible yêu cầu nhập giá trị đầu vào Type yours name?. Ở đây mình sẽ nhập Linux Unity. Giá trị này ứng với biến yours_name trong file index.j2 trước đó.
Chú ý ở task [Deploy configuration file], chỉ có sự thay đổi cấu hình trên máy chủ web2. Vì vậy mà handler Restart Apache cũng chỉ được gọi trên máy chủ này.
Bước 4: Kiểm tra
Truy cập địa chỉ IP của 2 remote servers kèm port 1808. Lúc này sẽ hiển thị giao diện website với giá trị input Linux Unity đã truyền vào trước đó.
SSH vào máy chủ web2 và di chuyển đến đường dẫn /etc/apache2. File ports.conf có thay đổi nên đã được backup với tên khác (file ports.conf.731055.2025-02-03@17:17:32~).
Role trong Ansible
Role không phải là playbook. Role là một bộ khung (framework) để chia nhỏ playbook thành nhiều files khác nhau. Mỗi role là một thành phần độc lập, bao gồm nhiều variables, tasks, files, templates, và modules bên dưới.
Việc tổ chức playbook theo role cũng giúp người dùng dễ chia sẻ và tái sử dụng lại playbook với người khác. Đặc biệt trong môi trường doanh nghiệp khi có từ vài trăm tới vài ngàn playbook thì role chính là cách quản lý các playbook này.
Một role sẽ có 7 folder với các chức năng khác nhau. Mỗi một thư mục cần phải chứa 1 file main.yml. Trong đó thì tasks thường là folder quan trọng nhất, dùng để chứa những playbook.
tasks: Viết các bước setup cụ thể cho role. Viết như 1 playbook bình thường.
handlers: Dùng để trigger một số thao tác như reload/restart/start stop service khi thực hiện một task nào đó trong playbook bằng lệnh notify.
defaults: Định nghĩa các giá trị default của variables được sử dụng trong roles. Nếu variables không được định nghĩa trong thư mục vars, các giá trị default này sẽ được gọi.
vars: Chứa thông tin các biến dùng trong role, biến trong vars sẽ override biến trong default.
templates: Chứa các file template theo Jinja format đuôi *.j2 (có thể là file config, file system, …).
meta: Chứa các thông tin về metadata của role, thường chỉ dùng khi publish role lên Ansible Galaxy – nơi mọi người upload và chia sẻ các role mình viết.
Ảnh minh hoạ cây thư mục tổ chức role trong Ansible:
Xem các ví dụ về role cũng như toàn bộ kiến thức về Ansible cơ bản mà mình đã thực hành tại đây!
Kết luận
Như vậy là đã hoàn thành Playbook, cung cấp cái nhìn tổng quan về việc tự động hóa quản lý hệ thống một cách đơn giản và hiệu quả. Khi đã nắm vững Playbook sẽ giúp bạn tiết kiệm thời gian, giảm thiểu lỗi và nâng cao hiệu suất làm việc.