Vấn đề
Bạn vừa mới khởi tạo một loạt 10 server mới và sẵn sàng triển khai mã nguồn. Bạn chạy Ansible playbook, nhưng thay vì thấy các thanh 'success' màu xanh, bạn lại gặp một loạt văn bản màu đỏ. Kết nối bị từ chối ngay cả trước khi Ansible bắt đầu công việc của mình.
Đây không phải là do mạng bị hỏng hay server bị sập. Đây là một tính năng bảo mật cơ bản của SSH. Khi bạn kết nối với một máy tính lần đầu tiên, SSH sẽ kiểm tra fingerprint (dấu vân tay) duy nhất của nó so với file ~/.ssh/known_hosts cục bộ. Nếu host đó hoàn toàn mới, hoặc nếu bạn đã cài lại hệ điều hành và fingerprint thay đổi, SSH sẽ dừng lại và hỏi: "Bạn có chắc chắn muốn tiếp tục kết nối không?"
Ansible được thiết kế để tự động hóa, không phải để hội thoại. Vì nó chạy ở chế độ không tương tác (non-interactively), nó không thể tự gõ "yes" thay bạn. Nó chỉ đơn giản là bỏ cuộc và báo lỗi fatal.
Thông báo lỗi chính xác
fatal: [192.168.1.100]: UNREACHABLE! => {
"changed": false,
"msg": "Host key verification failed.",
"unreachable": true
}
Tại sao điều này xảy ra
Thông thường, bạn sẽ gặp phải vấn đề này trong một trong ba tình huống sau:
- **Khởi đầu mới:** Bạn đang kết nối với một VPS mới hoặc VM cục bộ lần đầu tiên.
- **Cài đặt lại:** Bạn đã xóa một server (như instance AWS EC2) và cài lại hệ điều hành mới. IP vẫn giữ nguyên, nhưng SSH key đã thay đổi.
- **Tái sử dụng IP:** Trong các môi trường cloud động, bạn có thể được cấp một địa chỉ IP trước đây từng thuộc về một server khác đã có trong `known_hosts` của bạn.
Các bước khắc phục
Cách 1: Vô hiệu hóa Host Key Checking (Cách nhanh nhất)
Nếu bạn đang làm việc trong một lab an toàn hoặc mạng nội bộ riêng tư, bạn có thể muốn bỏ qua hoàn toàn việc kiểm tra fingerprint. Đây thường là cách xử lý cho các runner CI/CD tạm thời nơi bảo mật được xử lý ở cấp độ mạng.
Để thực hiện việc này, hãy tạo hoặc chỉnh sửa file ansible.cfg trong thư mục dự án của bạn:
[defaults]
host_key_checking = False
Bạn cần một cách sửa lỗi một lần mà không cần chỉnh sửa file? Hãy thiết lập biến môi trường trước khi chạy lệnh:
export ANSIBLE_HOST_KEY_CHECKING=False
ansible-playbook site.yml
Cảnh báo: Việc này khiến bạn dễ bị tấn công Man-in-the-Middle (MITM). Chỉ sử dụng cách này nếu bạn hoàn toàn tin tưởng mạng của mình.
Cách 2: Sử dụng ssh-keyscan (Cách bảo mật)
Đối với môi trường production, hãy giữ nguyên tính năng xác minh và chỉ cần cung cấp cho Ansible các key cần thiết. Bạn có thể "quét trước" (pre-scan) các server và đưa fingerprint của chúng vào kho lưu trữ tin cậy cục bộ.
# Quét một server duy nhất
ssh-keyscan -H 192.168.1.100 >> ~/.ssh/known_hosts
# Quét toàn bộ danh sách IP từ một file
ssh-keyscan -H -f inventory_ips.txt >> ~/.ssh/known_hosts
Flag -H rất hữu ích ở đây. Nó sẽ hash các hostname để nếu ai đó xem file known_hosts của bạn, họ không thể dễ dàng ánh xạ toàn bộ hạ tầng của bạn.
Cách 3: Xóa các Key cũ
Nếu bạn thấy lỗi "Host key mismatch", điều đó có nghĩa là máy tính của bạn đang nhớ một key cũ cho IP đó. Bạn phải xóa bản ghi cũ trước khi có thể lưu bản ghi mới. Sử dụng ssh-keygen để nhắm mục tiêu vào địa chỉ IP cụ thể:
ssh-keygen -f "~/.ssh/known_hosts" -R "192.168.1.100"
Sau khi key cũ đã bị xóa, hãy sử dụng lệnh ssh-keyscan từ Cách 2 để lấy key mới.
Cách 4: Ghi đè cấu hình trong Inventory
Đôi khi bạn chỉ muốn vô hiệu hóa việc kiểm tra cho một nhóm server cụ thể. Bạn có thể truyền các đối số SSH trực tiếp vào bên trong file inventory của mình (ví dụ: hosts.ini).
[dev_servers]
192.168.1.100 ansible_ssh_extra_args='-o StrictHostKeyChecking=no'
Xác minh
Hãy đảm bảo rằng nó hoạt động. Chạy module ping của Ansible đối với host của bạn. Nếu bạn thấy pong, việc bắt tay đã thành công và bạn đã sẵn sàng để tự động hóa.
ansible all -m ping -i inventory.ini
Kết quả mong đợi:
192.168.1.100 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
Mẹo chuyên nghiệp cho Production
- **Giới hạn phạm vi cấu hình:** Tránh thiết lập `host_key_checking = False` trong file toàn cục `/etc/ansible/ansible.cfg`. Hãy giữ nó ở mức cục bộ trong dự án của bạn để hạn chế rủi ro bảo mật.
- **Tự động hóa Pipeline:** Trong GitLab CI hoặc GitHub Actions, hãy thêm `ssh-keyscan` vào `before_script` của bạn. Điều này cho phép pipeline kết nối với hạ tầng mới mà không cần can thiệp thủ công.
- **Bastion Hosts:** Nếu bạn đang sử dụng Jump host, hãy nhớ rằng việc kiểm tra key diễn ra trên máy điều khiển cục bộ của bạn. Nếu bạn sử dụng `ProxyCommand`, bạn có thể cần quản lý key cho cả gateway và đích đến cuối cùng.

