Mô tả lỗi
Playbook của bạn đã có become: true. SSH kết nối bình thường. Rồi dòng này xuất hiện trên terminal:
fatal: [host]: FAILED! => {"msg": "Missing sudo password"}
Play dừng hẳn. Ansible đã kết nối tới host, xác thực qua SSH xong, rồi bị chặn — sudo yêu cầu mật khẩu nhưng Ansible không có gì để cung cấp.
Lưu ý: đây không phải lỗi kết nối. SSH đang hoạt động tốt. Remote user tồn tại. Vấn đề cụ thể là tài khoản này cần mật khẩu để leo thang lên root, và Ansible không biết mật khẩu đó là gì.
Nguyên nhân
Khi một task chạy với become: true, Ansible gọi sudo (hoặc bất kỳ become_method nào bạn đã cấu hình) trên remote host. Nếu user đó không thuộc nhóm sudoers NOPASSWD, sudo sẽ hỏi mật khẩu.
Ansible có thể cung cấp mật khẩu — nhưng chỉ khi bạn cho nó biết mật khẩu là gì. Nếu không có ansible_become_pass, Ansible truyền chuỗi rỗng. Sudo từ chối. Lỗi phát sinh.
Bạn thường gặp lỗi này trong các tình huống sau:
- Thêm host mới mà remote user có sudo thông thường, không phải passwordless
- Hardening bảo mật đã xóa
NOPASSWDkhỏi sudoers trên các host hiện tại - Playbook chạy tốt ở local nhưng fail trong CI — không có mật khẩu được truyền qua pipeline
- Deploy với service account yêu cầu mật khẩu sudo
Sửa nhanh: Nhập mật khẩu tại runtime
Cần giải quyết ngay? Yêu cầu Ansible hỏi mật khẩu become trước khi chạy:
ansible-playbook site.yml -i inventory --ask-become-pass
Bạn sẽ được hỏi một lần, và mật khẩu đó áp dụng cho tất cả host trong lần chạy. Phù hợp cho thực thi một lần hoặc kiểm thử tương tác. Dạng rút gọn là -K:
ansible-playbook site.yml -i inventory -K
Kiểm tra kết quả: Chạy thử nhanh với inventory của bạn:
ansible all -i inventory -m command -a "whoami" --become -K
Kết quả mong đợi: root cho mỗi host. Nếu thấy vậy, leo thang đặc quyền đang hoạt động đúng.
Sửa vĩnh viễn 1: Đặt become_pass trong Inventory
Với lab cá nhân hoặc môi trường không phải production, bạn có thể khai báo mật khẩu become trực tiếp trong inventory. Cấu hình theo từng host trong inventory/hosts.ini:
[webservers]
192.168.1.10 ansible_user=deploy ansible_become_pass=matkhaucuaban
192.168.1.11 ansible_user=deploy ansible_become_pass=matkhaucuaban
Hoặc đặt là biến nhóm trong inventory/group_vars/webservers.yml:
ansible_user: deploy
ansible_become_pass: matkhaucuaban
Quy tắc bắt buộc: không commit mật khẩu plaintext lên Git. Cách này chỉ chấp nhận được với thông tin xác thực tạm thời trong môi trường dev local. Bất cứ thứ gì liên quan đến server thật cần dùng Vault — xem Cách 2 bên dưới.
Sửa vĩnh viễn 2: Mã hóa bằng Ansible Vault
Với môi trường production, đây là cách làm đúng đắn. Mã hóa mật khẩu become bằng Ansible Vault để có thể lưu vào version control mà không lộ bí mật.
Bước 1: Tạo file vars được mã hóa
ansible-vault create group_vars/webservers/vault.yml
Thêm mật khẩu vào trong file:
vault_become_pass: "MatKhauSudoCuaBan"
Bước 2: Tham chiếu trong file vars thông thường
Trong group_vars/webservers/vars.yml:
ansible_become_pass: "{{ vault_become_pass }}"
Bước 3: Chạy với vault password
# Nhập mật khẩu lúc chạy (dùng tương tác)
ansible-playbook site.yml -i inventory --ask-vault-pass
# Dùng file mật khẩu (pipeline CI/CD)
ansible-playbook site.yml -i inventory --vault-password-file ~/.vault_pass
Kiểm tra cấu hình:
ansible-vault view group_vars/webservers/vault.yml
Nhập vault password khi được hỏi. Bạn sẽ thấy nội dung đã giải mã. Nếu thấy được, mọi thứ đã được kết nối đúng.
Sửa vĩnh viễn 3: Sudo không mật khẩu (khi chính sách cho phép)
Một số team cấp cho service account của Ansible quyền sudo không mật khẩu trên các host được quản lý. Cách này loại bỏ hoàn toàn vấn đề mật khẩu — không cần lưu thông tin xác thực, không cần nhập mật khẩu, không cần entry trong Vault.
Trên remote host, chỉnh sửa sudoers an toàn bằng visudo:
sudo visudo -f /etc/sudoers.d/ansible
Cấp quyền đầy đủ cho user deploy:
deploy ALL=(ALL) NOPASSWD: ALL
Hoặc giới hạn ở các lệnh cụ thể nếu chính sách bảo mật yêu cầu:
deploy ALL=(ALL) NOPASSWD: /usr/bin/apt, /usr/bin/systemctl
Sau khi cấu hình xong, xóa ansible_become_pass khỏi vars và kiểm tra:
ansible all -i inventory -m command -a "whoami" --become
Kết quả phải là root — không hỏi mật khẩu, không có lỗi.
Kiểm tra cấu hình become
Không chắc become được đặt ở đâu trong stack playbook của bạn? Bắt đầu từ đây:
# Tìm tất cả tham chiếu become
grep -r "become" site.yml roles/
# Kiểm tra become_method đang dùng
ansible-config dump | grep BECOME
Một playbook tối giản có become:
---
- hosts: webservers
become: true
become_method: sudo # mặc định — có thể bỏ qua
tasks:
- name: Cài đặt nginx
apt:
name: nginx
state: present
Mẹo hay
Với mật khẩu của service account Ansible, đừng dùng mật khẩu dễ nhớ. Hãy tạo mật khẩu ngẫu nhiên 32 ký tự — loại bạn sẽ không bao giờ gõ tay. Password Generator trên ToolCraft chạy hoàn toàn trên trình duyệt, không gửi dữ liệu lên server nào, nên an toàn để tạo thông tin xác thực cho service. Lưu kết quả vào Ansible Vault là xong.
Đang quản lý quyền file trong các playbook có dùng become? Unix Permissions Calculator trên cùng trang đó giúp bạn tính giá trị chmod đúng mà không cần thử đi thử lại.
Tóm tắt
- Chạy một lần: dùng
-Khoặc--ask-become-pass - Team/production: mã hóa
ansible_become_passbằng Ansible Vault - Service account: cấu hình
NOPASSWDtrong sudoers cho Ansible user - Không bao giờ commit mật khẩu plaintext lên version control

