- Tác giả

- Name
- Nguyễn Đức Xinh
- Ngày xuất bản
- Ngày xuất bản
Ansible Playbooks Phần 2: Tasks, Variables và Handlers
Phần 2 của series Ansible Playbooks tập trung vào các thành phần quan trọng: Tasks, Variables và Handlers.
Phần 2: Tasks, Variables và Handlers:
- Tasks và cách tổ chức tasks
- Variables: khai báo, sử dụng, precedence
- Variables từ external files
- Register để lưu output
- Handlers và notifications
- Ví dụ deploy với variables và handlers
Tasks
Là từng bước Ansible sẽ thực thi. Mỗi task gọi một module và truyền parameters.
Cấu trúc task cơ bản
- name: Cài nginx
apt:
name: nginx
state: present
become: yes
Task với nhiều parameters
- name: Copy nginx config
copy:
src: files/nginx.conf
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
backup: yes
become: yes
notify: restart nginx
Multiple tasks trong một play
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
become: yes
- name: Install packages
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- git
- vim
become: yes
- name: Start nginx service
service:
name: nginx
state: started
enabled: yes
become: yes
Task organization best practices
Dictionary format vs Inline
# BAD - Inline format khó đọc
- name: Install nginx
apt: name=nginx state=present update_cache=yes
# GOOD - Dictionary format dễ đọc
- name: Install nginx
apt:
name: nginx
state: present
update_cache: yes
Descriptive names
# BAD - Không rõ ràng
- apt:
name: nginx
# GOOD - Mô tả chi tiết
- name: Install nginx web server for production environment
apt:
name: nginx
state: present
Variables (Biến)
Biến giúp tái sử dụng giá trị và customize behavior.
Khai báo trong Playbook
- name: Deploy application
hosts: web
become: yes
vars:
package_name: nginx
http_port: 80
server_name: example.com
app_user: www-data
tasks:
- name: Install {{ package_name }}
apt:
name: "{{ package_name }}"
state: present
Sử dụng biến
tasks:
- name: Install {{ package_name }}
apt:
name: "{{ package_name }}"
state: present
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
vars:
port: "{{ http_port }}"
domain: "{{ server_name }}"
Variables từ file external
- name: Deploy application
hosts: web
vars_files:
- vars/common.yml
- vars/{{ env }}.yml # dev.yml, staging.yml, prod.yml
tasks:
# ... tasks using variables
vars/common.yml:
app_name: myapp
app_port: 8080
log_level: info
timezone: Asia/Ho_Chi_Minh
vars/prod.yml:
env: production
debug: false
workers: 8
max_connections: 1000
vars/dev.yml:
env: development
debug: true
workers: 2
max_connections: 100
Variable types
String variables
vars:
app_name: "myapp"
server_name: example.com
Numeric variables
vars:
http_port: 80
max_workers: 4
Boolean variables
vars:
enable_ssl: true
debug_mode: false
List variables
vars:
packages:
- nginx
- git
- vim
allowed_ips:
- "192.168.1.0/24"
- "10.0.0.0/8"
Dictionary variables
vars:
database:
host: localhost
port: 5432
name: myapp_db
user: dbuser
nginx:
port: 80
workers: 4
keepalive_timeout: 65
Variable precedence (thứ tự ưu tiên)
Ansible có 22 levels of variable precedence, một số quan trọng:
- Extra vars (
-etrong command line) - Cao nhất - Task vars (trong task)
- Block vars (trong block)
- Play vars (trong play)
- Play vars_files
- Host vars (
host_vars/hostname.yml) - Group vars (
group_vars/groupname.yml) - Inventory vars (trong inventory file)
- Role defaults - Thấp nhất
# Extra vars override mọi thứ khác
ansible-playbook site.yml -e "env=production http_port=8080"
# Multiple extra vars
ansible-playbook site.yml -e "env=production" -e "debug=false"
# Extra vars từ file
ansible-playbook site.yml -e "@vars/override.yml"
Using variables in templates
Template file: nginx.conf.j2
server {
listen {{ http_port }};
server_name {{ server_name }};
root {{ document_root }};
access_log {{ log_dir }}/access.log;
error_log {{ log_dir }}/error.log;
location / {
try_files $uri $uri/ =404;
}
}
Playbook:
- name: Configure nginx
template:
src: templates/nginx.conf.j2
dest: /etc/nginx/sites-available/default
vars:
http_port: 80
server_name: example.com
document_root: /var/www/html
log_dir: /var/log/nginx
Register - Lưu output của task
- name: Check nginx version
command: nginx -v
register: nginx_version
ignore_errors: yes
- name: Display nginx version
debug:
var: nginx_version.stderr
- name: Check if config file exists
stat:
path: /etc/nginx/nginx.conf
register: config_file
- name: Backup config if exists
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/nginx.conf.backup
remote_src: yes
when: config_file.stat.exists
- name: Run application
shell: /opt/app/start.sh
register: app_start
- name: Show app output
debug:
msg: |
Return code: {{ app_start.rc }}
Stdout: {{ app_start.stdout }}
Stderr: {{ app_start.stderr }}
Register output fields
| Field | Mô tả |
|---|---|
stdout |
Output standard |
stderr |
Error output |
rc |
Return code (0 = success) |
changed |
Task có thay đổi không |
failed |
Task có fail không |
skipped |
Task có bị skip không |
Handlers
Handlers là special tasks chỉ chạy khi được notify và chỉ chạy một lần dù được notify nhiều lần.
Khi nào dùng Handlers?
- Restart service khi config thay đổi
- Reload configuration
- Clear cache
- Rebuild indexes
- Bất kỳ tác vụ nào cần chạy sau khi có thay đổi
Cú pháp cơ bản
tasks:
- name: Copy nginx config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Copy php config
copy:
src: php.ini
dest: /etc/php/8.1/fpm/php.ini
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Lưu ý: Handler restart nginx chỉ chạy một lần dù được notify 2 lần.
Multiple handlers
tasks:
- name: Update nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify:
- reload nginx
- clear cache
- send notification
handlers:
- name: reload nginx
service:
name: nginx
state: reloaded
- name: clear cache
shell: rm -rf /var/cache/nginx/*
args:
warn: false
- name: send notification
debug:
msg: "Nginx configuration has been updated and reloaded"
Handlers với listen
Nhiều handlers cùng listen một keyword:
tasks:
- name: Update nginx config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart web services
- name: Update php-fpm config
copy:
src: php-fpm.conf
dest: /etc/php/8.1/fpm/php-fpm.conf
notify: restart web services
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
listen: restart web services
- name: restart php-fpm
service:
name: php8.1-fpm
state: restarted
listen: restart web services
Handler execution order
Handlers chạy:
- Sau khi tất cả tasks hoàn thành
- Theo thứ tự định nghĩa trong handlers section
- Chỉ một lần dù được notify nhiều lần
tasks:
- name: Task 1
copy:
src: file1
dest: /tmp/file1
notify: handler 1
- name: Task 2
copy:
src: file2
dest: /tmp/file2
notify: handler 2
- name: Task 3
copy:
src: file3
dest: /tmp/file3
notify: handler 1 # Handler 1 vẫn chỉ chạy 1 lần
handlers:
- name: handler 1
debug:
msg: "Handler 1 executed"
- name: handler 2
debug:
msg: "Handler 2 executed"
# Execution order:
# 1. Task 1, Task 2, Task 3 chạy
# 2. Handler 1 chạy (chỉ 1 lần)
# 3. Handler 2 chạy
Force handlers với meta
tasks:
- name: Update config
template:
src: app.conf.j2
dest: /etc/app/app.conf
notify: restart app
- name: Force handlers to run now
meta: flush_handlers
- name: Check app is running
uri:
url: http://localhost:8080/health
status_code: 200
💡 Key Takeaways
- Tasks là building blocks của Playbooks
- Variables giúp tái sử dụng và customize behavior
- Variable precedence: Extra vars > Play vars > Group vars > Inventory vars > Role defaults
- Register lưu output của tasks để sử dụng cho tasks sau
- Handlers chỉ chạy khi được notify và chỉ chạy một lần
- Handlers chạy sau khi tất cả tasks hoàn thành
🎯 Thực hành
- Viết playbook sử dụng variables từ external file
- Sử dụng register để lưu output và hiển thị kết quả
- Tạo handlers cho restart multiple services
- Deploy một ứng dụng với variables và handlers
