Chuyện gì đang xảy ra
Bạn chạy một playbook hoặc ansible -m ping và nhận được thông báo này:
fatal: [192.168.1.10]: UNREACHABLE! => {
"changed": false,
"msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic)",
"unreachable": true
}
Ansible đã gửi SSH key của mình. Máy chủ từ chối. Không có gì được thực thi.
Lưu ý rằng đây không phải là lỗi timeout — máy chủ từ xa vẫn đang hoạt động, nó chỉ từ chối key. Trong khoảng 90% trường hợp, nguyên nhân là một trong bốn thứ: sai đường dẫn key, key không có trong authorized_keys, sai remote user, hoặc quyền truy cập file bị lỗi trên key hoặc thư mục .ssh.
Quy trình debug
Bước 1: Kiểm tra SSH thủ công trước
Tạm gác Ansible sang một bên và kiểm tra kết nối SSH trực tiếp:
ssh -i /path/to/private_key ansible_user@192.168.1.10
Nếu lệnh này cũng thất bại, vấn đề nằm ở SSH chứ không phải Ansible. Hãy sửa SSH trước và Ansible sẽ tự hoạt động được.
Vẫn bí? Thêm -v để xem chính xác xác thực bị lỗi ở đâu:
ssh -v -i /path/to/private_key ansible_user@192.168.1.10
Tìm trong output những dòng như sau:
debug1: Offering public key: /path/to/private_key
debug1: Authentications that can continue: publickey
Permission denied (publickey).
Bước 2: Chạy Ansible với output chi tiết
ansible all -m ping -vvv
-vvv in ra chính xác lệnh SSH mà Ansible tạo ra nội bộ. Bạn sẽ thấy nó đang tải key nào, kết nối với user nào, và đang dùng port nào.
Bước 3: Kiểm tra inventory của bạn
cat inventory.ini
Xác nhận rằng các biến này đã được thiết lập:
[webservers]
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_rsa
Nguyên nhân phổ biến và cách khắc phục
Nguyên nhân 1: Sai hoặc thiếu đường dẫn private key
Ansible không thể tìm thấy — hoặc không thể đọc — private key mà bạn đã chỉ định.
Khắc phục: Xác nhận key tồn tại và có quyền sở hữu đúng:
ls -la ~/.ssh/id_rsa
# Should show: -rw------- 1 youruser youruser
Sau đó thiết lập đường dẫn trong ansible.cfg:
# ansible.cfg
[defaults]
private_key_file = ~/.ssh/id_rsa
Hoặc theo từng host trong inventory:
192.168.1.10 ansible_user=ubuntu ansible_ssh_private_key_file=/home/youruser/.ssh/deploy_key
Nguyên nhân 2: Public key không có trong authorized_keys trên máy chủ từ xa
Public key của bạn đơn giản là không có ở đó. Máy chủ từ xa không biết bạn là ai.
Khắc phục: Đẩy key lên bằng một lệnh duy nhất:
ssh-copy-id -i ~/.ssh/id_rsa.pub ansible_user@192.168.1.10
Chưa có quyền truy cập bằng mật khẩu? Thêm thủ công trên máy từ xa:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "your-public-key-content" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
Nguyên nhân 3: Quyền file sai trên key hoặc thư mục .ssh
SSH âm thầm loại bỏ các key có quyền truy cập quá rộng. Nó sẽ không thông báo "bị bỏ qua do quyền truy cập" — mà chỉ nói "permission denied" rồi tiếp tục. Rất khó chịu.
Khắc phục: Giới hạn quyền truy cập trên control node:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
Làm tương tự trên máy từ xa:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Nếu bạn hay nhầm lẫn giữa 600 và 644, Unix Permissions Calculator tại ToolCraft cho phép bạn click vào các bit quyền và nhận ngay giá trị số chính xác.
Nguyên nhân 4: Sai remote user
Mặc định Ansible kết nối bằng tên người dùng local của bạn. Trên máy chủ Ubuntu mới thì user đó là ubuntu, trên Amazon Linux là ec2-user, trên CentOS là centos — tên người dùng local của bạn gần như chắc chắn không phải bất kỳ cái nào trong số đó.
Khắc phục: Thiết lập user một cách tường minh. Chọn cấp độ phù hợp với bạn:
# In inventory
192.168.1.10 ansible_user=ubuntu
# Or in ansible.cfg
[defaults]
remote_user = ubuntu
# Or per-play in the playbook
- hosts: webservers
remote_user: ubuntu
Nguyên nhân 5: SELinux hoặc StrictModes chặn key
Trên RHEL/CentOS, SELinux có thể ngăn SSH đọc authorized_keys ngay cả khi quyền file trông có vẻ đúng. Nhãn bị sai, không phải các bit mode.
Khắc phục: Khôi phục SELinux context:
restorecon -Rv ~/.ssh
Cũng kiểm tra /etc/ssh/sshd_config trên máy từ xa xem có StrictModes yes không — cài đặt đó áp dụng kiểm tra quyền truy cập cho ~/.ssh và mọi thứ bên trong.
Nguyên nhân 6: SSH agent chưa được tải hoặc có key sai
Khi bạn không chỉ định file key, Ansible lấy bất kỳ key nào hiện đang có trong SSH agent của bạn. Nếu bạn đã tải personal key nhưng máy chủ lại mong đợi deploy key, xác thực sẽ thất bại — và lỗi trông y hệt nhau.
Khắc phục: Xem những gì đang thực sự được tải:
ssh-add -l
Tải đúng key:
ssh-add ~/.ssh/deploy_key
Hoặc yêu cầu Ansible bỏ qua agent hoàn toàn và dùng một key cụ thể:
[ssh_connection]
ssh_args = -o ForwardAgent=no
Ví dụ hoàn chỉnh
Đây là thiết lập tối giản từ đầu đến khi có kết nối Ansible hoạt động:
# 1. Generate a new ed25519 key pair
ssh-keygen -t ed25519 -f ~/.ssh/ansible_key -N ""
# 2. Push the public key to the remote host
ssh-copy-id -i ~/.ssh/ansible_key.pub ubuntu@192.168.1.10
# 3. Verify raw SSH works before involving Ansible
ssh -i ~/.ssh/ansible_key ubuntu@192.168.1.10 exit
echo "Exit code: $?" # Must be 0
# 4. Write the inventory
cat > inventory.ini {
"changed": false,
"ping": "pong"
}
Đang quản lý nhiều máy chủ? Kiểm tra tất cả cùng lúc với lệnh gọn hơn:
ansible all -i inventory.ini -m ping --one-line
Bài học rút ra
- Kiểm tra SSH trước khi động vào Ansible.
ssh -v -i key user@hostcho bạn biết mọi thứ trong 3 giây. Nếu lệnh đó thất bại, Ansible không có cơ hội nào. - Quyền truy cập thất bại trong im lặng. SSH loại bỏ các key có quyền sai mà không thông báo gì hữu ích. Luôn chạy
chmod 600trên private key vàchmod 700trên thư mục.ssh— cả trên control node lẫn máy từ xa. - Khai báo tường minh trong inventory. Khai báo
ansible_uservàansible_ssh_private_key_filecho mọi nhóm host. Dựa vào giá trị mặc định là cách lỗi này xuất hiện ba tháng sau khi ai đó chạy Ansible từ máy khác. - Dùng ed25519 cho key mới. Ngắn hơn, nhanh hơn, và không có vấn đề tương thích so với RSA-1024 hay RSA-2048.

