Ansible Delegate To – Thực thi Task trên Host Cụ Thể

Trong Ansible, mặc định các task được chạy trên các host đã khai báo trong inventory. Tuy nhiên, đôi khi bạn muốn một task cụ thể chạy trên một host khác thay vì host hiện tại.

Đó là lúc bạn dùng delegate_to.

  • delegate_to không phải là một module riêng biệt.
  • Đây là một directive (chỉ thị), cho phép bạn “chỉ định” host cụ thể để thực thi task.

Xem thêm:

Ansible Local Action – Thực thi tác vụ trên Controller

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

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

1. Ansible Delegate To là gì?

Trong Ansible, delegate_to là một directive (chỉ thị), cho phép bạn chỉ định một host cụ thể để chạy một task, thay vì chạy trên host mặc định trong inventory.

Nói đơn giản:

  • Bình thường, mỗi task trong playbook sẽ chạy trên từng host trong danh sách hosts.
  • Nhưng với delegate_to, bạn có thể buộc task đó chạy ở một host khác (có thể là localhost hoặc một host trong inventory).

2. Khi nào dùng delegate_to?

Một số tình huống thực tế:

  • Chạy lệnh backup database chỉ trên máy DB, không phải trên toàn bộ cluster.
  • Ghi log hoặc thu thập thông tin từ nhiều host, nhưng lưu kết quả vào một host tập trung.
  • Tạo chứng chỉ trên một máy duy nhất rồi phân phối cho các máy còn lại.

3. Cú pháp cơ bản

- name: Task chạy trên host khác
  command: echo "Hello from {{ inventory_hostname }}"
  delegate_to: target_host
  • delegate_to: target_host → xác định rõ task sẽ chạy trên host nào.
  • target_host có thể là:
    • Tên host trong inventory (db, loadbalancer, web1, …).
    • Hoặc địa chỉ IP trực tiếp (192.168.1.10).
    • Đặc biệt: localhost → chạy trên Ansible controller.

4. Ví dụ

Giả sử ta có 2 host trong inventory:

  • web1 (ứng dụng).
  • db1 (database).

Mục tiêu:

  1. Tạo file log tạm trên tất cả host.
  2. Ghi hostname của mỗi host vào file log, nhưng file log chỉ được lưu tại một máy duy nhất (ví dụ db1).

Playbook:

---
- name: Demo Delegate To
  hosts: all
  become: yes
  vars:
    log_path: /tmp/connection.log

  tasks:
    - name: Ensure log file exists
      shell: "test -f {{ log_path }} || touch {{ log_path }}"
      args:
        warn: false

    - name: Write host info into log file (delegated)
      shell: "echo '{{ inventory_hostname }} - {{ ansible_hostname }}' >> {{ log_path }}"
      delegate_to: db1

5. Giải thích từng bước

Task 1: Tạo file log

shell: "test -f {{ log_path }} || touch {{ log_path }}"
  • Kiểm tra file /tmp/connection.log.
  • Nếu chưa có thì tạo mới.
  • Chạy trên từng host trong inventory.

Task 2: Ghi thông tin vào log (delegated)

delegate_to: db1
  • Dù playbook chạy trên tất cả host, nhưng task này chỉ chạy tại db1.
  • Mỗi lần lặp qua một host khác (web1, db1, …), nội dung log vẫn được ghi vào cùng một file trên db1.
  • Ví dụ kết quả file /tmp/connection.log trên db1:
web1 - web1-hostname
db1 - db1-hostname

6. So sánh delegate_tolocal_action

Tiêu chí local_action delegate_to
Cú pháp Viết ngắn gọn: local_action: <module> Viết đầy đủ: delegate_to: localhost
Ngữ nghĩa Dễ hiểu, chuyên biệt: task này luôn chạy ở controller Linh hoạt: task có thể chạy ở bất kỳ host nào (kể cả controller nếu chỉ định localhost)
Tính tương thích cũ Xuất hiện từ Ansible rất sớm, nhiều ví dụ/lab cũ vẫn dùng Bổ sung sau này, thống nhất hơn với triết lý “delegate cho host cụ thể”
Đọc code Khi thấy local_action, người đọc biết ngay là chạy trên controller Khi thấy delegate_to, người đọc phải nhìn giá trị (localhost hay host khác)

delegate_to là một công cụ cực kỳ hữu ích để linh hoạt điều khiển nơi task được chạy. Trong môi trường production, nó giúp giảm trùng lặp, tối ưu hóa tài nguyên và dễ dàng quản lý hạ tầng phức tạp.

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

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

tags trong Ansible

Ansible Vault – Bài 11

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