0

Lab 12 — Ansible Troubleshooting

Mục tiêu: Sau Lab này, người học không chỉ biết viết Playbook mà còn có thể đọc lỗi, debug, tìm root cause và khắc phục deployment failure trong môi trường thực tế.

Đây là Lab rất quan trọng trong roadmap từ Beginner → Senior.

Ở các Lab trước, chúng ta chủ yếu học:

Viết Ansible
     ↓
Chạy Ansible
     ↓
Server được cấu hình

Nhưng production thực tế thường là:

Viết Playbook
     ↓
Run
     ↓
❌ FAILED
     ↓
Debug
     ↓
Find Root Cause
     ↓
Fix
     ↓
Run lại
     ↓
✅ SUCCESS

Senior DevOps/Infrastructure Engineer không phải người không gặp lỗi, mà là người có khả năng tìm lỗi nhanh và xác định đúng nguyên nhân.


1. Bối cảnh

Giả sử chúng ta có hệ thống:

                    Ansible Controller
                           │
                           │ SSH
                           ▼
                  ┌─────────────────┐
                  │ Production      │
                  │ Server           │
                  │                 │
                  │ Docker           │
                  │ PostgreSQL       │
                  │ Todo API        │
                  └─────────────────┘

Playbook:

ansible-playbook site.yml

Có thể gặp:

SSH connection failed
Permission denied
Package not found
Service failed
Template error
Variable undefined
Docker error
Port already in use
File permission denied
Handler không chạy
Task chạy nhưng application vẫn chết

Mục tiêu của Lab:

Học một quy trình troubleshooting có hệ thống, thay vì sửa lỗi bằng cách thử ngẫu nhiên.


2. Mục tiêu Lab

Sau Lab này, người học có thể:

  • Đọc Ansible error.
  • Phân biệt UNREACHABLEFAILED.
  • Sử dụng -v, -vv, -vvv, -vvvv.
  • Debug variables.
  • Kiểm tra Inventory.
  • Kiểm tra SSH.
  • Kiểm tra privilege escalation.
  • Debug undefined variable.
  • Debug Jinja2 Template.
  • Debug package installation.
  • Debug service.
  • Debug Docker.
  • Debug Handler.
  • Debug permissions.
  • Debug networking.
  • Debug application deployment.
  • Sử dụng check mode.
  • Sử dụng diff mode.
  • Kiểm tra Playbook trước khi chạy.
  • Debug từng host.
  • Debug từng task.
  • Xây dựng troubleshooting workflow.
  • Biết cách tìm root cause thay vì chỉ xử lý symptom.

3. Nguyên tắc quan trọng nhất

Khi Playbook fail:

Đừng sửa ngay. Hãy đọc lỗi trước.

Ví dụ:

fatal: [server01]: FAILED!

Không có nghĩa:

Ansible bị lỗi

Mà có thể là:

Ansible
   │
   ▼
Task
   │
   ▼
Command
   │
   ▼
Operating System
   │
   ▼
Application

Lỗi có thể nằm ở bất kỳ layer nào.


4. Troubleshooting theo Layer

Một cách tư duy rất tốt:

Layer 1
Ansible Controller
       │
       ▼
Layer 2
Inventory
       │
       ▼
Layer 3
SSH
       │
       ▼
Layer 4
Privilege
       │
       ▼
Layer 5
OS / Package
       │
       ▼
Layer 6
Service
       │
       ▼
Layer 7
Docker
       │
       ▼
Layer 8
Application
       │
       ▼
Layer 9
Network

Không nên nhảy thẳng đến Layer 8 khi chưa biết Layer 3 có hoạt động hay không.


5. Bước 1 — Kiểm tra Syntax

Trước tiên:

ansible-playbook site.yml --syntax-check

Nếu đúng:

playbook: site.yml

Nếu sai YAML:

ERROR! We were unable to read either as JSON nor YAML

6. YAML Error

Ví dụ:

tasks:
  - name: Install nginx
    ansible.builtin.apt:
      name: nginx
      state: present
     update_cache: true

Indentation sai.

Chạy:

ansible-playbook site.yml --syntax-check

Có thể nhận:

mapping values are not allowed here

Cách xử lý

Không đoán.

Kiểm tra:

line number
column
task name

Sau đó kiểm tra indentation.


7. Bước 2 — Kiểm tra Inventory

Chạy:

ansible-inventory -i inventory/hosts.ini --graph

Ví dụ:

@all:
  |--@application:
  |  |--server01
  |--@database:
  |  |--server02

Nếu Inventory sai:

Playbook
   ↓
Wrong Host
   ↓
Everything fails

8. Xem toàn bộ Inventory

ansible-inventory \
  -i inventory/hosts.ini \
  --list

Output có thể rất dài.

Dùng:

ansible-inventory \
  -i inventory/hosts.ini \
  --list \
  | jq

nếu máy có jq.


9. Test Connectivity

Đây là một trong những command quan trọng nhất:

ansible all \
  -i inventory/hosts.ini \
  -m ansible.builtin.ping

Expected:

server01 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

Nếu:

server01 | UNREACHABLE!

thì chưa cần debug Playbook.

Hãy debug SSH trước.


10. UNREACHABLE vs FAILED

Đây là distinction rất quan trọng.

UNREACHABLE

Ansible
   │
   X
   │
Server

Ansible không kết nối được server.

Ví dụ:

SSH timeout
Connection refused
Permission denied
Host not found

FAILED

Ansible
   │
   ▼
Server
   │
   ▼
Task
   │
   X

Đã kết nối được nhưng task fail.


11. Debug SSH

Nếu:

ansible all -m ping

fail:

Permission denied (publickey)

thử SSH trực tiếp:

ssh deploy@server01

Nếu SSH cũng fail:

Vấn đề không nằm ở Ansible.


12. Kiểm tra SSH Verbose

ssh -vvv deploy@server01

Đây là command cực kỳ hữu ích.

Bạn có thể thấy:

Offering public key
Authenticating
Server refused key

Từ đó xác định:

SSH key
User
Permission
sshd

13. Kiểm tra Ansible SSH

Chạy:

ansible server01 \
  -i inventory/hosts.ini \
  -m ping \
  -vvv

-vvv giúp nhìn thấy nhiều thông tin hơn.


14. Verbosity Levels

Normal

ansible-playbook site.yml

-v

ansible-playbook site.yml -v

-vv

ansible-playbook site.yml -vv

-vvv

ansible-playbook site.yml -vvv

-vvvv

ansible-playbook site.yml -vvvv

Thông thường:

Normal → -v → -vv → -vvv

là đủ.

-vvvv thường dùng khi cần debug sâu connection/SSH.


15. Bước 3 — Kiểm tra User

Trong Inventory:

[application]
server01 ansible_user=deploy

Nhưng server có thể không có:

deploy

Test:

ssh deploy@server01

Hoặc:

ansible server01 \
  -m command \
  -a "whoami"

Expected:

deploy

16. Debug become

Ví dụ task:

- name: Install Docker
  become: true
  ansible.builtin.apt:
    name: docker.io
    state: present

Nếu:

Missing sudo password

hoặc:

deploy is not in the sudoers file

thì vấn đề là privilege escalation.


17. Test sudo

SSH vào server:

ssh deploy@server01

Sau đó:

sudo whoami

Expected:

root

Nếu không:

sudo configuration

cần được kiểm tra.


18. Debug Variable

Một lỗi rất phổ biến:

'database_host' is undefined

Ví dụ:

- name: Show database host
  ansible.builtin.debug:
    var: database_host

Nếu variable tồn tại:

database_host: "postgres"

Nếu không:

VARIABLE IS NOT DEFINED

19. Debug nhiều Variables

Có thể:

- name: Debug application config
  ansible.builtin.debug:
    msg:
      - "Environment: {{ app_environment }}"
      - "Port: {{ application_port }}"
      - "Host: {{ application_host }}"

Không làm điều này với secret.

Không:

- debug:
    var: postgres_password

20. Debug Variable Type

Đôi khi variable tồn tại nhưng sai kiểu.

Ví dụ:

application_port: "8080"

thay vì:

application_port: 8080

Debug:

- name: Debug variable type
  ansible.builtin.debug:
    msg:
      - "value={{ application_port }}"
      - "type={{ application_port | type_debug }}"

Output:

value=8080
type=str

hoặc:

type=int

Đây là kỹ thuật rất hữu ích khi debug Jinja2.


21. Bước 4 — Kiểm tra Facts

Chạy:

ansible server01 \
  -m ansible.builtin.setup

Có rất nhiều information:

ansible_hostname
ansible_distribution
ansible_os_family
ansible_memtotal_mb
ansible_processor_vcpus
ansible_default_ipv4

22. Debug OS

- name: Show OS
  ansible.builtin.debug:
    msg:
      - "OS: {{ ansible_distribution }}"
      - "Version: {{ ansible_distribution_version }}"
      - "Architecture: {{ ansible_architecture }}"

Ví dụ:

OS: Ubuntu
Version: 24.04
Architecture: aarch64

23. Một lỗi thực tế

Bạn viết:

ansible.builtin.apt:
  name: nginx

Nhưng target server là:

CentOS

Task fail.

Root cause:

Wrong package manager

Cần thiết kế:

Debian / Ubuntu
      ↓
apt

RHEL / CentOS
      ↓
dnf

24. Bước 5 — Debug Package

Ví dụ:

- name: Install nginx
  ansible.builtin.apt:
    name: nginx
    state: present

Nếu fail:

Unable to locate package nginx

Không nên ngay lập tức đổi package.

Kiểm tra:

apt update

hoặc:

apt-cache policy nginx

25. Debug bằng Ad-Hoc

Đây là lúc kiến thức Lab 3 — Ad-Hoc Commands trở nên rất hữu ích.

Ví dụ:

ansible server01 \
  -m command \
  -a "uname -a"
ansible server01 \
  -m command \
  -a "df -h"
ansible server01 \
  -m command \
  -a "free -m"
ansible server01 \
  -m command \
  -a "docker ps"

Ansible Ad-Hoc trở thành một công cụ troubleshooting.


26. Bước 6 — Debug Service

Ví dụ:

- name: Start nginx
  ansible.builtin.service:
    name: nginx
    state: started

Task có thể báo:

Could not start service nginx

Không dừng ở đây.

SSH vào server:

systemctl status nginx

27. Đọc Systemd Logs

journalctl -u nginx

Hoặc:

journalctl -u nginx -n 100

Theo dõi realtime:

journalctl -u nginx -f

Đây mới có thể chứa root cause.

Ví dụ:

bind() failed: Address already in use

28. Port Already in Use

Nếu:

nginx failed to start

kiểm tra:

ss -lntp

hoặc:

sudo lsof -i :80

Có thể phát hiện:

docker-proxy

đang chiếm port 80.

Root cause:

Port conflict

không phải:

Ansible bug

29. Bước 7 — Debug Template

Một lỗi rất phổ biến:

template error

Ví dụ:

server {
    listen {{ application_port }};
    server_name {{ application_domain }};
}

nhưng:

application_domain

không tồn tại.

Ansible báo:

' application_domain ' is undefined

30. Validate Template

Có thể chạy:

ansible-playbook site.yml --check

Nếu template có lỗi, thường sẽ phát hiện trước khi thay đổi hệ thống.


31. Kiểm tra Rendered File

Có thể tạo task tạm thời:

- name: Show rendered config
  ansible.builtin.command:
    cmd: cat /etc/nginx/conf.d/todo.conf

Nhưng production không nên để những task debug này tồn tại lâu dài.


32. Sử dụng --diff

Chạy:

ansible-playbook site.yml --check --diff

Đây là command rất hữu ích.

Ansible có thể cho biết:

- old configuration
+ new configuration

Giúp xác định:

Ansible đang định thay đổi cái gì?


33. --check

ansible-playbook site.yml --check

Đây là check mode.

Ansible cố gắng mô phỏng thay đổi mà không thực hiện đầy đủ thay đổi.

Ví dụ:

Task
 ↓
Check
 ↓
Would change

Rất hữu ích trước production deployment.


34. Nhưng --check không phải hoàn hảo

Một số module hoặc command:

ansible.builtin.command

không thể mô phỏng đầy đủ.

Ngoài ra:

Application runtime
External API
Database state

có thể không được kiểm tra hoàn toàn.

Do đó:

--check là một lớp kiểm tra, không phải guarantee deployment sẽ thành công.


35. Bước 8 — Debug Docker

Ví dụ:

- name: Start application
  community.docker.docker_compose_v2:
    project_src: /opt/todo
    state: present

Task fail.

Không chỉ xem Ansible.

Kiểm tra:

docker compose ps

Sau đó:

docker compose logs

36. Debug từng Container

docker ps -a

Ví dụ:

todo-api     Exited (1)
postgres     Up
nginx        Up

Sau đó:

docker logs todo-api

Root cause có thể:

DATABASE_URL invalid
Connection refused
Missing environment variable
Port conflict
Migration failed

37. Debug Environment

Kiểm tra:

docker inspect todo-api

Nhưng phải cẩn thận:

docker inspect có thể hiển thị secret.

Không copy output có password vào ticket, Slack, GitHub hoặc log.


38. Debug Network

Nếu application không connect database:

Todo API
   │
   X
   │
PostgreSQL

Kiểm tra:

docker network ls

Sau đó:

docker network inspect <network>

Kiểm tra:

Container
Network
IP
Aliases

39. Debug DNS trong Docker

Từ container:

docker exec todo-api getent hosts postgres

Nếu:

postgres

resolve được:

172.x.x.x postgres

thì DNS hoạt động.

Nếu không:

Network / service name

cần được kiểm tra.


40. Debug Database Connection

Ví dụ:

docker exec todo-api \
  sh -c 'nc -zv postgres 5432'

Nếu thành công:

Connection succeeded

Nếu fail:

Connection refused

cần kiểm tra PostgreSQL.


41. Debug Application

Một Playbook có thể:

SUCCESS

nhưng application:

❌ 500 Internal Server Error

Đây là một distinction rất quan trọng.

Ansible SUCCESS
        ≠
Application HEALTHY

42. Health Check

Sau deployment:

- name: Check application health
  ansible.builtin.uri:
    url: "http://localhost:8080/health"
    status_code: 200

Nếu:

200

→ deployment có vẻ healthy.

Nếu:

500

→ Ansible nên fail.

Đây là tư duy deployment verification.


43. Bước 9 — Debug Handler

Ví dụ:

- name: Update nginx config
  ansible.builtin.template:
    src: nginx.conf.j2
    dest: /etc/nginx/nginx.conf
  notify: Restart nginx

Handler:

handlers:

  - name: Restart nginx
    ansible.builtin.service:
      name: nginx
      state: restarted

Nếu config thay đổi:

Task changed
   ↓
notify
   ↓
handler

44. Nếu Handler không chạy

Kiểm tra:

1. Task có changed không?

Nếu:

ok

thì handler không chạy.

Nếu:

changed

thì handler được notify.

2. Tên Handler có đúng không?

notify: Restart nginx

phải match:

- name: Restart nginx

45. Handler chỉ chạy cuối Play

Thông thường:

Task 1
Task 2
Task 3
Task 4
     ↓
Handlers

Không phải:

Task 2
 ↓
Handler
 ↓
Task 3

Nếu cần handler chạy ngay:

- meta: flush_handlers

Nhưng không nên lạm dụng.


46. Bước 10 — Debug Permission

Một lỗi rất phổ biến:

Permission denied

Ví dụ:

ansible.builtin.template:
  src: app.conf.j2
  dest: /opt/todo/app.conf

Nếu user không có quyền:

Permission denied

Kiểm tra:

ls -ld /opt/todo

và:

ls -l /opt/todo

47. Kiểm tra User

whoami
id
groups

Ví dụ:

deploy

không thuộc:

docker

thì:

docker ps

có thể fail.


48. Docker Permission

Nếu:

permission denied while trying to connect to Docker daemon

kiểm tra:

groups

Có:

docker

không?

Nếu không:

sudo usermod -aG docker deploy

Sau đó user cần đăng nhập session mới để group membership có hiệu lực.


49. Bước 11 — Debug Disk

Deployment có thể fail vì:

No space left on device

Kiểm tra:

df -h

và:

df -i

Đây là một lỗi production rất thực tế.


50. Debug Memory

free -m

Hoặc:

docker stats

Có thể application chết vì:

OOMKilled

51. Debug CPU

top

hoặc:

htop

Docker:

docker stats

Nếu deployment rất chậm:

CPU
Memory
Disk I/O
Network

đều cần được xem xét.


52. Bước 12 — Debug bằng --limit

Nếu Inventory có:

server01
server02
server03
server04

không cần chạy toàn bộ.

ansible-playbook site.yml \
  --limit server01

Chỉ debug:

server01

53. Debug một Group

ansible-playbook site.yml \
  --limit application

Rất hữu ích trong production.

Ví dụ:

100 servers

không nên test bằng:

ansible-playbook site.yml

ngay lập tức.


54. Debug một Task

Dùng tags:

- name: Install Docker
  tags:
    - docker

Chạy:

ansible-playbook site.yml \
  --tags docker

Chỉ test phần Docker.


55. Skip Task

ansible-playbook site.yml \
  --skip-tags docker

Có thể dùng khi muốn cô lập vấn đề.


56. Step-by-Step Execution

Ansible hỗ trợ:

ansible-playbook site.yml --step

Ansible sẽ hỏi trước task.

Ví dụ:

Perform task: Install Docker? (N)o/(y)es/(c)ontinue

Rất hữu ích khi học và debug.

Không nên dùng thường xuyên trong automation production.


57. assert

Một kỹ thuật rất tốt để fail sớm:

- name: Validate configuration
  ansible.builtin.assert:
    that:
      - application_port is defined
      - application_domain is defined
      - app_environment is defined
    fail_msg: "Required application variables are missing"

Thay vì:

Deploy
 ↓
Template fail
 ↓
Debug khó

ta có:

Validate
 ↓
Fail immediately
 ↓
Clear error

58. Validate Port

- name: Validate application port
  ansible.builtin.assert:
    that:
      - application_port | int > 0
      - application_port | int < 65536
    fail_msg: "Invalid application_port"

59. Validate Environment

- name: Validate environment
  ansible.builtin.assert:
    that:
      - app_environment in ['dev', 'staging', 'production']

Nếu:

app_environment=prod

thì fail.

Điều này giúp tránh typo.


60. Debug với register

Ví dụ:

- name: Check Docker version
  ansible.builtin.command:
    cmd: docker --version
  register: docker_version
  changed_when: false

Sau đó:

- name: Show Docker version
  ansible.builtin.debug:
    var: docker_version.stdout

Output:

Docker version 28.x

61. Hiểu register

Command
   │
   ▼
register
   │
   ▼
Variable
   │
   ├── stdout
   ├── stderr
   ├── rc
   └── changed

Ví dụ:

docker_version.rc
docker_version.stdout
docker_version.stderr

62. failed_when

Có thể custom điều kiện fail:

- name: Check application
  ansible.builtin.command:
    cmd: curl -fs http://localhost:8080/health
  register: health
  failed_when: health.rc != 0

63. changed_when

Một command chỉ để kiểm tra:

- name: Check Docker version
  ansible.builtin.command:
    cmd: docker --version
  changed_when: false

Nếu không:

changed

có thể làm Playbook report sai.


64. Debug Command Failure

Ví dụ:

- name: Run migration
  ansible.builtin.command:
    cmd: ./migration.sh
  register: migration

Sau đó:

- name: Show migration output
  ansible.builtin.debug:
    msg:
      - "RC: {{ migration.rc }}"
      - "STDOUT: {{ migration.stdout }}"
      - "STDERR: {{ migration.stderr }}"

Không dùng cách này nếu output có secret.


65. Root Cause vs Symptom

Đây là phần quan trọng nhất của Lab.

Ví dụ:

Ansible:
FAILED - nginx failed to start

Đây chỉ là:

Symptom

Tiếp tục:

systemctl status nginx

thấy:

Address already in use

Đây mới là:

Root Cause

Tiếp:

ss -lntp

thấy:

Docker container chiếm port 80

Root cause cuối:

Port 80 conflict between nginx and Docker

66. Troubleshooting Tree

Khi Playbook fail:

                Playbook FAILED
                       │
              ┌────────┴────────┐
              │                 │
         UNREACHABLE          FAILED
              │                 │
              ▼                 ▼
             SSH             Task
              │                 │
        ┌─────┴─────┐      ┌────┴────┐
        │           │      │         │
      User        Key    Variable  Command
        │           │      │         │
      sudo       network  template  service

67. Troubleshooting Workflow

Hãy hình thành thói quen:

1. Read Error
      ↓
2. Identify Layer
      ↓
3. Reproduce
      ↓
4. Isolate
      ↓
5. Inspect
      ↓
6. Find Root Cause
      ↓
7. Fix
      ↓
8. Re-run
      ↓
9. Verify

68. Không nên làm như thế này

Playbook fail
    ↓
Sửa random
    ↓
Run
    ↓
Fail
    ↓
Sửa random
    ↓
Run
    ↓
Fail

Đây là:

Trial-and-error troubleshooting

Không scale được.


69. Nên làm như thế này

Failure
   ↓
Read exact error
   ↓
Classify
   ↓
Reproduce outside Ansible
   ↓
Inspect system
   ↓
Root Cause
   ↓
Minimal Fix
   ↓
Verify

Ví dụ:

nginx failed
   ↓
systemctl status nginx
   ↓
Address already in use
   ↓
ss -lntp
   ↓
Docker owns :80
   ↓
Port conflict
   ↓
Change port architecture

70. Lab Challenge 1 — SSH Failure

Cố tình cấu hình sai:

server01 ansible_user=wronguser

Chạy:

ansible server01 -m ping

Kỳ vọng:

UNREACHABLE

Nhiệm vụ:

  1. Đọc lỗi.
  2. SSH trực tiếp.
  3. Kiểm tra user.
  4. Sửa Inventory.
  5. Test lại.

71. Lab Challenge 2 — Wrong SSH Key

Cấu hình sai:

ansible_ssh_private_key_file=wrong-key

Chạy:

ansible server01 -m ping

Debug:

ansible server01 -m ping -vvv

Sau đó:

ssh -vvv deploy@server01

Mục tiêu:

Phân biệt vấn đề Ansible và vấn đề SSH.


72. Lab Challenge 3 — Undefined Variable

Xóa:

application_port: 8080

Sau đó chạy:

ansible-playbook site.yml

Expected:

'application_port' is undefined

Fix bằng:

assert

để error rõ ràng hơn.


73. Lab Challenge 4 — Template Error

Cố tình viết:

server_name {{ application_domain }};

nhưng không khai báo:

application_domain

Chạy:

ansible-playbook site.yml

Debug:

ansible-playbook site.yml -vv

Sau đó bổ sung variable.


74. Lab Challenge 5 — Permission Error

Cố tình deploy:

/etc/myapp/config.yml

bằng user không có quyền.

Quan sát:

Permission denied

Sau đó xác định:

whoami
id
ls -ld /etc/myapp

và sửa bằng:

become: true

nếu phù hợp.


75. Lab Challenge 6 — Service Failure

Cố tình tạo nginx config sai.

Deploy:

ansible-playbook site.yml

Kỳ vọng:

nginx restart failed

Không sửa ngay.

Thực hiện:

systemctl status nginx
nginx -t
journalctl -u nginx -n 100

Tìm root cause.


76. Lab Challenge 7 — Docker Failure

Cố tình đổi:

DATABASE_HOST=wrong-host

Deploy application.

Sau đó:

docker compose ps
docker compose logs todo-api

Tìm:

Database connection failure

Sau đó kiểm tra:

docker network inspect

và sửa configuration.


77. Lab Challenge 8 — Port Conflict

Cho nginx sử dụng:

80

và Docker:

80

Deploy.

Kỳ vọng:

Address already in use

Tìm process:

ss -lntp

Xác định:

Who owns port 80?

Sau đó thiết kế lại port mapping.


78. Lab Challenge 9 — Disk Full

Giả lập:

disk gần đầy

Sau đó chạy deployment.

Kiểm tra:

df -h
df -i

Mục tiêu:

Phân biệt application failure với infrastructure capacity problem.


79. Lab Challenge 10 — Application Health Failure

Cho application start thành công nhưng:

GET /health

trả:

500

Ansible vẫn có thể báo:

changed

Nhiệm vụ:

Thêm:

ansible.builtin.uri

để deployment fail nếu application không healthy.


80. Lab Challenge 11 — Handler Failure

Tạo:

nginx.conf

sai.

Task:

template

notify:

Restart nginx

Theo dõi:

Task
 ↓
Changed
 ↓
Handler
 ↓
Restart
 ↓
Failed

Debug:

systemctl status nginx
journalctl -u nginx

81. Lab Challenge 12 — Production Incident

Đây là bài quan trọng nhất.

Giả sử:

02:00 AM

CI/CD chạy:

ansible-playbook production.yml

Output:

server01 SUCCESS
server02 SUCCESS
server03 FAILED
server04 SUCCESS

Application trên server03:

HTTP 500

Nhiệm vụ:

Tìm nguyên nhân.

Không được:

reinstall server
restart everything
delete Docker

Phải đi theo quy trình:

1. Identify affected server
2. Check Ansible error
3. SSH
4. Check service
5. Check logs
6. Check Docker
7. Check network
8. Check disk/memory
9. Identify root cause
10. Fix minimal component
11. Verify application

82. Production Incident Example

Giả sử Ansible báo:

TASK [Restart nginx]
fatal: [server03]: FAILED!

Đừng kết luận:

Ansible lỗi

Kiểm tra:

systemctl status nginx

Kết quả:

nginx.service failed

Tiếp:

nginx -t

Kết quả:

duplicate listen options for 0.0.0.0:80

Root cause:

Generated configuration duplicated listen directive

Không phải:

SSH
Ansible
systemd

83. Debug Checklist

Khi gặp lỗi, hãy đi theo checklist này:

[ ] 1. Read exact error
[ ] 2. Identify affected host
[ ] 3. Is it UNREACHABLE or FAILED?
[ ] 4. Test SSH
[ ] 5. Check user
[ ] 6. Check sudo/become
[ ] 7. Check variables
[ ] 8. Check facts
[ ] 9. Check template
[ ] 10. Check package
[ ] 11. Check service
[ ] 12. Check logs
[ ] 13. Check Docker
[ ] 14. Check network
[ ] 15. Check disk
[ ] 16. Check memory
[ ] 17. Check application
[ ] 18. Verify health

84. Bộ Command cần nhớ

Syntax

ansible-playbook site.yml --syntax-check

Inventory

ansible-inventory -i inventory/hosts.ini --graph

Connectivity

ansible all -m ping

Verbose

ansible-playbook site.yml -vvv

Check

ansible-playbook site.yml --check

Diff

ansible-playbook site.yml --check --diff

Limit

ansible-playbook site.yml --limit server01

Tags

ansible-playbook site.yml --tags docker

Facts

ansible server01 -m setup

85. Các command Linux cần kết hợp

Ansible troubleshooting không thể chỉ dùng Ansible.

Người học cần thành thạo:

ssh
systemctl
journalctl
ss
lsof
df
du
free
top
ps
docker
docker compose
curl
ping
getent
dig

Đây chính là lý do các Lab trước về Linux, SSH, Docker và Application Deployment rất quan trọng.


86. Tư duy Senior — Automation phải có khả năng tự kiểm tra

Playbook tốt không chỉ:

Install
Configure
Start

mà nên:

Validate
   ↓
Install
   ↓
Configure
   ↓
Restart
   ↓
Health Check
   ↓
Verify

Ví dụ:

- name: Validate nginx config
  ansible.builtin.command:
    cmd: nginx -t
  changed_when: false

- name: Restart nginx
  ansible.builtin.service:
    name: nginx
    state: restarted

- name: Verify nginx
  ansible.builtin.uri:
    url: http://localhost
    status_code: 200

87. Tư duy Senior — Fail Fast

Thay vì:

Deploy 20 tasks
      ↓
Task 20 fail

nên:

Validate configuration
       ↓
       ❌
Fail immediately

Ví dụ:

- name: Validate environment
  ansible.builtin.assert:
    that:
      - app_environment is defined
      - application_port is defined

88. Tư duy Senior — Minimize Blast Radius

Nếu production có:

100 servers

không nên:

ansible-playbook production.yml

và thay đổi cả 100 server ngay lập tức.

Có thể:

1 server
   ↓
verify
   ↓
5 servers
   ↓
verify
   ↓
20 servers
   ↓
verify
   ↓
100 servers

Đây là tư duy progressive rollout.


89. Tư duy Senior — Troubleshooting không phải chỉ là sửa lỗi

Một Senior sau khi fix phải hỏi:

Tại sao lỗi xảy ra?

và:

Tại sao hệ thống không phát hiện lỗi sớm hơn?

Ví dụ:

Nginx config sai
      ↓
Deployment failed

Junior:

Sửa config

Senior:

Sửa config
+
nginx -t trước restart
+
CI syntax validation
+
Ansible assert
+
health check
+
prevent regression

90. Sau Incident cần cải thiện Automation

Một incident tốt nên tạo ra:

Incident
   ↓
Root Cause Analysis
   ↓
Fix
   ↓
Automation Improvement
   ↓
Prevention

Ví dụ:

Database connection failed

Sau incident:

- name: Check database connectivity
  ...

được thêm vào deployment.

Lần sau:

Database unavailable
        ↓
Ansible detects
        ↓
Fail early

91. Bài tập tổng hợp cuối Lab

Xây dựng một Playbook:

production.yml

có pipeline:

                START
                  │
                  ▼
          Validate Variables
                  │
                  ▼
            Check SSH
                  │
                  ▼
          Install Dependencies
                  │
                  ▼
          Deploy Configuration
                  │
                  ▼
             Validate Config
                  │
                  ▼
            Restart Service
                  │
                  ▼
           Health Check
                  │
            ┌─────┴─────┐
            │           │
          PASS         FAIL
            │           │
            ▼           ▼
        SUCCESS      Debug

Yêu cầu:

  • assert.
  • register.
  • changed_when.
  • failed_when khi phù hợp.
  • no_log cho secret.
  • Có health check.
  • Có handler.
  • Có template.
  • Có Docker.
  • Có troubleshooting documentation.

92. Deliverable

Sau Lab 12, người học cần có:

ansible-lab-12/
│
├── ansible.cfg
├── production.yml
│
├── inventory/
│   └── hosts.ini
│
├── group_vars/
│   ├── all.yml
│   └── vault.yml
│
├── roles/
│   └── application/
│       ├── defaults/
│       ├── handlers/
│       ├── tasks/
│       └── templates/
│
└── TROUBLESHOOTING.md

Trong TROUBLESHOOTING.md cần ghi lại ít nhất:

1. SSH failure
2. Permission failure
3. Variable failure
4. Template failure
5. Service failure
6. Docker failure
7. Network failure
8. Health check failure
9. Disk failure
10. Memory failure

Mỗi issue phải có:

Symptom
   ↓
Error
   ↓
Investigation
   ↓
Root Cause
   ↓
Fix
   ↓
Prevention

93. Kết quả đạt được

Sau Lab 12, người học không còn chỉ có tư duy:

Ansible = chạy Playbook

mà bắt đầu có tư duy:

              Automation Engineer
                      │
          ┌───────────┴───────────┐
          │                       │
       Deploy                  Troubleshoot
          │                       │
          ▼                       ▼
      Automation             Root Cause
          │                       │
          └───────────┬───────────┘
                      ▼
               Reliable System

Đây là một mốc rất quan trọng trong roadmap Beginner → Senior.


94. Liên kết với các Lab trước

Toàn bộ kiến thức đến đây bắt đầu kết nối thành một hệ thống:

Lab 1
Ansible Fundamentals
        ↓
Lab 2
Inventory & SSH
        ↓
Lab 3
Ad-Hoc
        ↓
Lab 4
Playbook
        ↓
Lab 5
Variables & Facts
        ↓
Lab 6
Jinja2
        ↓
Lab 7
Handlers & Idempotency
        ↓
Lab 8
Roles
        ↓
Lab 9
Server Provisioning
        ↓
Lab 10
Application Deployment
        ↓
Lab 11
Secrets & Vault
        ↓
Lab 12
Troubleshooting

Lab 12 là điểm chuyển rất rõ từ "học Ansible" sang "vận hành hệ thống bằng Ansible".

Và từ đây, Lab 13 — Ansible với nhiều Environment (Dev / Staging / Production) nên tập trung vào một vấn đề production quan trọng hơn nữa: làm sao dùng cùng một automation codebase nhưng triển khai an toàn cho nhiều môi trường, tránh việc cấu hình của Production bị lẫn với Dev/Staging.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.