Sửa lỗi Ansible "Timeout (12s) waiting for privilege escalation prompt" với become

intermediate🔧 Ansible2026-03-21| Ansible 2.9+, Ubuntu/Debian/RHEL/CentOS, máy chủ từ xa sử dụng become với sudo/su

Error Message

Timeout (12s) waiting for privilege escalation prompt
#ansible#become#sudo#privilege-escalation#timeout

Lỗi Gặp Phải

Bạn chạy một playbook với become: true và Ansible cứ… treo. Mười hai giây sau:

fatal: [web01]: FAILED! => {
    "msg": "Timeout (12s) waiting for privilege escalation prompt: "
}

Hoặc dạng ngắn hơn:

Timeout (12s) waiting for privilege escalation prompt

Play dừng hẳn. SSH vẫn hoạt động bình thường. Không có task nào được chạy.

Điều Gì Đang Xảy Ra

become: true yêu cầu Ansible leo thang đặc quyền trên máy chủ từ xa — thường thông qua sudo. Khi sudo được cấu hình yêu cầu mật khẩu mà Ansible không cung cấp, nó cứ đứng chờ ở dấu nhắc mật khẩu cho đến khi hết 12 giây.

Có sáu nguyên nhân khác nhau có thể gây ra lỗi này. Cách sửa phụ thuộc vào nguyên nhân bạn đang gặp phải.

Nguyên Nhân Gốc Rễ (và Cách Sửa)

1. Không cung cấp mật khẩu become (phổ biến nhất)

Sudo của người dùng từ xa yêu cầu mật khẩu, nhưng Ansible không biết mật khẩu đó là gì.

Sửa nhanh — nhập mật khẩu khi chạy:

ansible-playbook site.yml -i inventory --ask-become-pass

Ansible hỏi một lần, sau đó dùng lại mật khẩu đó cho tất cả các host trong lần chạy.

Sửa tốt hơn — lưu vào group_vars:

# inventory/group_vars/all.yml
ansible_become_password: "your_sudo_password_here"

Đừng bao giờ commit mật khẩu dạng plaintext. Mã hóa file bằng Ansible Vault:

ansible-vault encrypt inventory/group_vars/all.yml

Sau đó chạy với:

ansible-playbook site.yml -i inventory --ask-vault-pass

2. Chưa cấu hình sudo không cần mật khẩu trên máy chủ từ xa

Với tự động hóa, bạn thường muốn sudo không cần mật khẩu. Thêm một file sudoers riêng trên mỗi máy chủ được quản lý — đừng sửa trực tiếp /etc/sudoers:

sudo visudo -f /etc/sudoers.d/ansible

Thêm dòng này, thay deploy bằng user Ansible thực tế của bạn:

deploy ALL=(ALL) NOPASSWD: ALL

Cần kiểm soát chặt hơn? Giới hạn chỉ cho các lệnh cụ thể:

deploy ALL=(ALL) NOPASSWD: /usr/bin/apt, /bin/systemctl

Kiểm tra thủ công trước khi động vào Ansible:

ssh deploy@web01 sudo whoami

Nếu lệnh đó in ra root mà không hỏi mật khẩu, Ansible cũng sẽ hoạt động được.

3. sudo yêu cầu TTY (requiretty trong sudoers)

Các phiên bản RHEL/CentOS cũ đi kèm với Defaults requiretty trong /etc/sudoers. Ansible mặc định không cấp phát TTY, nên sudo thẳng thừng từ chối.

Xác nhận đây có phải nguyên nhân không:

ssh deploy@web01 "sudo -n whoami" 2>&1

Bạn sẽ thấy: sudo: sorry, you must have a tty to run sudo. Đó chính là thủ phạm.

Cách A — tắt requiretty chỉ cho user Ansible:

Defaults:deploy !requiretty

Cách B — yêu cầu Ansible cấp phát pseudo-TTY:

# per-play
- hosts: all
  become: true
  vars:
    ansible_ssh_extra_args: '-tt'

Một ràng buộc quan trọng: -ttpipelining = true không thể dùng cùng nhau. Chọn một trong hai.

4. Bật pipelining nhưng vẫn cần mật khẩu become

pipelining = true tăng tốc độ thực thi playbook lên 30–50% với inventory lớn, nhưng nó chặn các dấu nhắc mật khẩu tương tác. Hai tính năng này về cơ bản không tương thích với nhau.

# ansible.cfg
[ssh_connection]
pipelining = true  # ← chặn mật khẩu become tương tác

Bạn có hai lựa chọn: tắt pipelining, hoặc cấu hình sudo không cần mật khẩu để Ansible không bao giờ cần hỏi. Lựa chọn thứ hai gần như luôn tốt hơn.

5. Sai become_method

Ansible mặc định dùng sudo. Nếu máy chủ dùng su, doas, hoặc pbrun, Ansible gửi sai lệnh leo thang — và dấu nhắc không bao giờ khớp với những gì nó mong đợi.

# playbook
- hosts: bsd_servers
  become: true
  become_method: doas   # khớp với cái máy chủ thực sự đang dùng

Hoặc đặt toàn cục:

[privilege_escalation]
become_method = su

6. Timeout quá ngắn với máy chủ chậm

Khi tải nặng — ví dụ máy chủ đang chạy ở 90% CPU, hoặc kết nối SSH xuyên lục địa — sudo có thể mất hơn 12 giây để phản hồi. Tăng timeout lên:

# ansible.cfg
[defaults]
timeout = 30

[privilege_escalation]
become_timeout = 30

Ghi đè theo từng play:

- hosts: all
  become: true
  vars:
    ansible_timeout: 30

Kiểm Tra

Sau khi sửa, lệnh một dòng này là cách kiểm tra nhanh nhất:

ansible web01 -i inventory -m command -a "whoami" --become

Kết quả mong đợi:

web01 | CHANGED | rc=0 >>
root

Vẫn bị timeout? Thêm -vvvv và grep để tìm chỗ bị treo:

ansible-playbook site.yml -i inventory --become -vvvv 2>&1 | grep -A5 "privilege"

Cấu Hình ansible.cfg Được Khuyến Nghị

Cấu hình này giúp tránh hầu hết các nguyên nhân trên. Kết hợp với sudo không cần mật khẩu trên máy chủ từ xa là xong:

[defaults]
timeout = 30
host_key_checking = false

[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false

[ssh_connection]
pipelining = true
# Tắt pipelining chỉ khi bạn cần mật khẩu become tương tác

Phòng Ngừa

  • Cấu hình sudo không cần mật khẩu cho tài khoản dịch vụ Ansible ngay khi khởi tạo máy chủ — làm sau sẽ mất công hơn nhiều.
  • Lưu mật khẩu become trong Ansible Vault. Thông tin đăng nhập dạng plaintext trong file inventory có xu hướng lọt vào git history.
  • Chạy ssh deploy@host sudo whoami thủ công trước khi thực thi playbook trên máy chủ mới. Phát hiện vấn đề sudo bên ngoài Ansible sẽ dễ debug hơn nhiều.
  • Nếu team dùng chung ansible.cfg, hãy thêm comment giải thích pipelining có đang bật hay không và tại sao — việc trộn lẫn pipelining với become dùng mật khẩu sẽ gây nhầm lẫn cho mọi người trong mỗi dự án không có tài liệu rõ ràng.

Related Error Notes