Hướng dẫn sử dụng Block, Rescue và Always trong Ansible Playbook

Trong quá trình tự động hoá với Ansible, đôi khi chúng ta cần xử lý lỗi hoặc gom nhóm nhiều tác vụ (task) lại với nhau để dễ quản lý. Các khối block, rescuealways sẽ giúp chúng ta thực hiện điều này.

Xem thêm:

Hướng dẫn sử dụng Error Handling trong Ansible Playbook

Hướng dẫn tạo Cron Job tự động dọn dẹp log bằng Ansible

1. Khái niệm cơ bản

Block

  • Block cho phép gom nhiều task thành một nhóm logic.
  • Thay vì lặp lại cùng một cấu hình (ví dụ: become: yes), ta có thể khai báo ở block để áp dụng cho toàn bộ task bên trong.
  • Có thể gắn điều kiện, ignore_errors hoặc bất kỳ thuộc tính chung nào cho cả nhóm task.

Nói ngắn gọn: Block = “gói nhiều task lại” + “áp dụng chung điều kiện/thuộc tính”.

Rescue

  • Được dùng khi block bị lỗi.
  • Thường dùng để thực hiện cleanup (thu dọn, khôi phục) sau khi block thất bại.
  • Chỉ chạy khi có lỗi trong block.

Always

  • Luôn chạy dù block thành công hay thất bại.
  • Dùng cho những việc “bắt buộc phải thực hiện”, ví dụ như gửi thông báo, log, hoặc reset trạng thái.

2. Cấu trúc tổng quát

tasks:
  - block:
      - name: Task 1
        command: echo "Running task 1"

      - name: Task 2
        command: echo "Running task 2"
    rescue:
      - name: Cleanup nếu block fail
        command: echo "Rescue running"
    always:
      - name: Luôn luôn chạy
        command: echo "Always running"
  • block: chứa danh sách các task chính.
  • rescue: chỉ chạy khi có task trong block bị lỗi.
  • always: chạy trong mọi trường hợp.

3. Ví dụ

3.1 Gom nhóm task với Block

- name: Demo Ansible Block
  hosts: all
  tasks:
    - block:
        - name: Liệt kê thư mục /root
          command: ls /root

        - name: Liệt kê thư mục /etc
          command: ls /etc

        - name: Liệt kê thư mục /tmp
          command: ls /tmp
      become: yes
      ignore_errors: yes

Giải thích:

  • become: yes: áp dụng cho toàn bộ 3 task.
  • ignore_errors: yes: nếu 1 task lỗi thì không làm playbook dừng lại.

3.2 Sử dụng Rescue để cleanup khi lỗi

- name: Demo Block + Rescue
  hosts: all
  tasks:
    - block:
        - name: Cố tình fail (thư mục không tồn tại)
          command: ls /not_exist_dir

        - name: Liệt kê /tmp
          command: ls /tmp
      rescue:
        - name: Cleanup sau khi block fail
          command: echo "Thực hiện dọn dẹp do lỗi"

Kết quả:

  • Task ls /not_exist_dir sẽ fail.
  • Rescue sẽ chạy và in ra "Thực hiện dọn dẹp do lỗi".

3.3 Kết hợp Always

- name: Demo Block + Rescue + Always
  hosts: all
  tasks:
    - block:
        - name: Thực thi task hợp lệ
          command: ls /tmp
      rescue:
        - name: Cleanup nếu lỗi
          command: echo "Rescue chạy"
      always:
        - name: Gửi thông báo
          command: echo "Always chạy dù thành công hay thất bại"

Kết quả:

  • Vì task trong block chạy thành công → Rescue không chạy.
  • Always vẫn chạy để in thông báo.

3.4. Ví dụ tổng quát

---
- name: Error Handling in Ansible Playbook
  hosts: app
  become: true
  become_user: root

  vars:
    anonymous_enable: yes
    local_enable: yes
    write_enable: yes
    anon_upload_enable: yes

  tasks:
    - block:
        - name: Install vsftpd
          apt: 
            name: vsftpd
            state: present

        - name: Take backup of existing config
          copy:
            src: /etc/vsftpd.conf
            dest: /etc/vsftpd.conf.bkp
            remote_src: yes

        - name: Use Jinja2 template to configure vsftpd
          template:
            src: vsftpd.j2
            dest: /etc/vsftpd.conf
        
        - name: View Custom Jinja Template values
          command: "cat /etc/vsftpd.conf"
          register: jinja_out
        - debug: var=jinja_out

      rescue:
        - name: Recovery block
          debug:
            msg: "Something failed, restoring vsftpd.conf from backup"
            
        - name: Restore vsftpd configuration from backup
          copy:
            src: /etc/vsftpd.conf.bkp
            dest: /etc/vsftpd.conf
            remote_src: yes

        - name: View vsftpd.conf values
          command: "cat /etc/vsftpd.conf"
          register: conf_out
        - debug: var=conf_out

      always:
        - name: Restarting vsftpd
          service:
            name: vsftpd
            state: restarted

        

vsftpd.j2:

anonymous_enable={{ anonymous_enable }}
local_enable={{ local_enable }}
write_enable={{ write_enable }}
anon_upload_enable={{ anon_upload_enable }}
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
pam_service_name=vsftpd
userlist_enable=YES
# MY IP Address={{ ansible_facts['default_ipv4']['address'] }}

4. Khi nào dùng Block/Rescue/Always?

  • Block: gom nhiều task, dễ quản lý, áp dụng điều kiện chung.
  • Rescue: xử lý khi task trong block thất bại (rollback, cleanup).
  • Always: thực hiện việc phải làm mọi lúc (log, thông báo, reset).

Tóm lại, sử dụng block, rescuealways trong Ansible giúp bạn:

  • Viết playbook gọn gàng, dễ bảo trì.
  • Kiểm soát lỗi tốt hơn thay vì dừng ngay khi gặp lỗi.
  • Đảm bảo những tác vụ quan trọng luôn được thực hiện.

Cảm ơn bạn đã tham khảo ansible tutorial trên ttnguyen.net

Bài viết cùng chủ đề:

tags trong Ansible

Ansible Vault – Bài 11

Ansible Role – Bài 10

Nguyễn Tiến Trường

Mình viết về những điều nhỏ nhặt trong cuộc sống, Viết về câu chuyện những ngày không có em