Site logo
Tác giả
  • avatar Nguyễn Đức Xinh
    Name
    Nguyễn Đức Xinh
    Twitter
Ngày xuất bản
Ngày xuất bản

Ansible Handlers và Notifications Part 2

Anti-Patterns Cần Tránh

❌ Anti-pattern 1: Handlers Với Side Effects Phức Tạp

# KHÔNG TỐT
handlers:
  - name: restart everything
    shell: |
      systemctl restart mysql
      systemctl restart php-fpm
      systemctl restart nginx
      redis-cli FLUSHALL
      rm -rf /tmp/*

Vấn đề: Khó debug, không idempotent, không thể selective run.

✅ Tốt hơn:

handlers:
  - name: restart mysql
    service: name=mysql state=restarted
  
  - name: restart php-fpm
    service: name=php-fpm state=restarted
  
  - name: restart nginx
    service: name=nginx state=restarted

❌ Anti-pattern 2: Handlers Phụ Thuộc Vào Biến Task

tasks:
  - name: Update config
    template:
      src: app.conf.j2
      dest: /etc/app/app.conf
    register: config_result
    notify: restart app

handlers:
  - name: restart app
    service:
      name: myapp
      state: restarted
    when: config_result.changed  # KHÔNG HOẠT ĐỘNG!

Vấn đề: Handler không thấy config_result.


Best Practices

1. Đặt Tên Handler Rõ Ràng

restart nginx, reload apache, flush redis cache
handler1, do stuff, fix things

2. Một Handler Một Nhiệm Vụ

Mỗi handler chỉ nên làm một việc duy nhất.

3. Sử Dụng Listen Cho Handler Groups

handlers:
  - name: stop app
    service: name=myapp state=stopped
    listen: "deploy app"
  
  - name: run migrations
    command: /opt/app/migrate.sh
    listen: "deploy app"
  
  - name: start app
    service: name=myapp state=started
    listen: "deploy app"

4. Document Dependencies

Thêm comments cho handlers có dependency:

handlers:
  # Must run before "start app"
  - name: update database schema
    command: /opt/app/migrate.sh
  
  # Depends on "update database schema"
  - name: start app
    service: name=myapp state=started

5. Test Handlers Riêng Biệt

# test-handlers.yml
---
- name: Test handlers
  hosts: localhost
  tasks:
    - name: Trigger all handlers
      command: /bin/true
      changed_when: true
      notify:
        - restart nginx
        - restart mysql
        - restart app
  
  handlers:
    # Import handlers từ role
    - import_tasks: roles/webserver/handlers/main.yml

Tổng Kết

Trong bài học này, bạn đã học:

  • ✅ Cách handlers thực sự hoạt động
  • ✅ Quản lý thứ tự thực thi handlers
  • ✅ Sử dụng listen để group handlers
  • meta: flush_handlers để chạy handlers ngay lập tức
  • ✅ Handlers trong roles
  • ✅ Graceful restart patterns
  • ✅ Best practices và anti-patterns

Bài Tập Thực Hành

Bài 1: Tạo role database với handlers để:

  • Stop MySQL
  • Backup database
  • Update configuration
  • Start MySQL
  • Verify database is running

Bài 2: Tạo playbook zero-downtime deployment với:

  • Remove server from load balancer
  • Deploy new code
  • Restart application
  • Health check
  • Add back to load balancer

Bài 3: Implement blue-green deployment pattern sử dụng handlers.

Resources