Best Practices: Cấu Trúc Dự Án và Thiết Kế
Bạn đã học mọi mảnh ghép. Bài này gom chúng thành best practices — cách tổ chức và viết Ansible để dự án dễ bảo trì, an toàn, và làm việc nhóm tốt. Đây là khác biệt giữa "playbook chạy được" và "codebase Ansible chuyên nghiệp".
Cấu trúc dự án
Một dự án Ansible nghiêm túc nên có cấu trúc rõ ràng, tách môi trường:
project/
├── ansible.cfg # cấu hình
├── requirements.yml # collection/role phụ thuộc (Bài 9)
├── inventories/
│ ├── production/
│ │ ├── hosts.yml # inventory prod
│ │ └── group_vars/ # biến RIÊNG prod
│ └── staging/
│ ├── hosts.yml
│ └── group_vars/ # biến riêng staging
├── roles/
│ ├── common/ # role nền dùng chung
│ └── webserver/ # role theo chức năng
├── playbooks/
│ └── site.yml # playbook gọi các role
└── group_vars/ host_vars/ # biến chung mọi môi trường
Hai nguyên tắc quan trọng:
- Tách môi trường bằng inventory riêng (
inventories/production/,inventories/staging/), mỗi cái cógroup_vars/riêng. Cùng playbook + role, chạy với inventory khác → môi trường khác. Tránh trộn biến prod/staging. - Playbook mỏng, role dày:
site.ymlchỉ gọi role; logic nằm trong role (Bài 8). Playbook trở thành "bản nhạc" điều phối, dễ đọc.
Thiết kế role tốt
Role là đơn vị tái dùng — thiết kế tốt thì dùng lại được khắp nơi:
- Một role một trách nhiệm: role
nginxlo nginx, rolepostgreslo postgres. Đừng nhồi mọi thứ vào một role. - Tham số hóa qua
defaults/: mọi thứ có thể tùy biến (port, version, đường dẫn) đặt làm biến trongdefaults/main.yml(ưu tiên thấp, dễ ghi đè — Bài 6). Role không nên hard-code. - Idempotent tuyệt đối (Bài 5): mọi task phải an toàn chạy lại.
meta/main.ymlđầy đủ: khai báogalaxy_info(author, license, platform hỗ trợ). Nhớ Bài 14 — molecule/galaxy bắt buộc điều này.- Kèm
READMEvàmolecule/: tài liệu cách dùng + test (Bài 14).
Quy ước đặt tên
Đặt tên nhất quán giúp đọc và gỡ lỗi:
- Đặt
name:cho MỌI task và play — log mới rõ ràng (nhớ PLAY RECAP/task name ở Bài 4). Task không tên hiện ra dạng module khó hiểu. - Dùng FQCN (Bài 9):
ansible.builtin.copythay vìcopy. Rõ ràng, tránh trùng, vàansible-lintkhuyến nghị. - Tiền tố biến của role: biến của role
webservernên đặtwebserver_port,webserver_user... thay vìport,user. Tránh đụng biến giữa các role (biến Ansible là global trong một play). - snake_case cho tên biến.
Bảo mật
Tổng hợp từ các bài:
- Bí mật qua Vault (Bài 10) hoặc secret manager (lookup — Bài 12). Không bao giờ để mật khẩu trần trong playbook/Git.
becomeđúng mức: chỉ nâng quyền task cần root, không bậtbecomecả play nếu không cần (series Linux Bài 12).- Module thay vì command/shell (Bài 5): an toàn và idempotent hơn.
- Không log secret: thêm
no_log: truecho task xử lý dữ liệu nhạy cảm để Ansible không in giá trị ra log.
ansible-lint: tự động bắt lỗi
Đừng dựa vào trí nhớ để giữ best practice — dùng ansible-lint kiểm tra tự động:
ansible-lint site.yml
Chạy trên playbook site.yml (Bài 4) cho kết quả thật:
# Rule Violation Summary
1 risky-file-permissions profile:safety
risky-file-permissions: File permissions unset or incorrect.
site.yml:17 Task/Handler: Triển khai trang index
Failed: 1 failure(s) ... Rating: 2/5 star
ansible-lint phát hiện task copy ở dòng 17 không đặt mode: — rủi ro vì quyền file phụ thuộc umask, không tường minh (nhớ series Linux Bài 7). Cách sửa: thêm mode: "0644":
- name: Triển khai trang index
ansible.builtin.copy:
content: "..."
dest: /usr/share/nginx/html/index.html
mode: "0644" # ← tường minh, lint hết phàn nàn
ansible-lint có nhiều rule và profile (min, basic, safety, production...) với độ nghiêm khác nhau. Exit code khác 0 khi có vi phạm — nên đưa vào CI (cùng molecule — Bài 14) để chặn code không đạt chuẩn trước khi merge:
# .github/workflows/lint.yml (ý tưởng)
- run: ansible-lint
- run: molecule test
Vài quy ước khác đáng theo
- Pin phiên bản trong
requirements.yml(Bài 9): collection/role pin version để build tái lập. --check --difftrước khi áp prod (Bài 5, 13): luôn dry-run.- Tags cho playbook dài (Bài 13): chạy chọn lọc.
- Đừng dùng
ignore_errorsbừa: che lỗi thật. Dùngfailed_when/block-rescue(Bài 7) có chủ đích. - Giữ playbook khai báo, không mệnh lệnh: mô tả trạng thái (
state:), tránh chuỗicommandthủ tục.
🧹 Dọn dẹp
Cấu trúc dự án mẫu ở repo nghiadaulau/ansible-series, thư mục 15-best-practices.
Tổng kết
Best practices: cấu trúc dự án rõ ràng (tách môi trường bằng inventory riêng, playbook mỏng gọi role dày); thiết kế role một-trách-nhiệm, tham số hóa qua defaults/, idempotent, có meta/README/molecule; đặt tên nhất quán (mọi task có name, dùng FQCN, tiền tố biến theo role); bảo mật qua Vault/secret manager, become tối thiểu, no_log; và ansible-lint tự động bắt lỗi (như risky-file-permissions thiếu mode) — đưa vào CI cùng molecule. Đây là chuẩn của codebase Ansible chuyên nghiệp.
Bài cuối (16) ghép tất cả thành một dự án hoàn chỉnh — deploy một ứng dụng thật bằng role, áp best practices — rồi dọn dẹp EC2 và tổng kết series.