Lỗi gặp phải
fatal: [remote-host]: FAILED! => {"changed": false, "cmd": "/usr/bin/git clone ...", "msg": "Host key verification failed.\r\nfatal: Could not read from remote repository."}
Lỗi này xuất hiện khi module git của Ansible cố clone qua SSH (git@github.com:... hoặc ssh://...) nhưng host key của máy chủ từ xa chưa có trong ~/.ssh/known_hosts. Cụ thể, Ansible kiểm tra người dùng đang chạy task trên máy đích — không phải trên control node của bạn.
SSH chặn kết nối đến các host chưa được xác nhận. Ansible chạy không tương tác, nên không có lời nhắc để chấp nhận key — nó đơn giản là thất bại hoàn toàn.
Nguyên nhân
Hầu hết mọi người đều nghĩ vấn đề nằm ở Ansible control node. Thực ra không phải vậy. Quá trình kiểm tra known_hosts xảy ra trên máy chủ từ xa — máy đang được cấu hình. Máy chủ đó chưa từng SSH đến Git server của bạn trước đây, nên không có bản ghi nào về host key.
Bốn tình huống thường gây ra lỗi này:
- Provisioning máy chủ mới — đây là lần clone đầu tiên nó thực hiện
- Chuyển từ URL clone HTTPS sang SSH
- IP hoặc key của Git server đã thay đổi (GitHub đã thay thế RSA key vào tháng 3 năm 2023)
- Chạy task với tư cách người dùng khác như
deploy, người chưa cóknown_hosts
Cách xử lý 1: Điền trước known_hosts bằng ssh-keyscan (Khuyến nghị)
Thêm một task trước task git để scan và đăng ký host key:
- name: Add GitHub to known_hosts
ansible.builtin.known_hosts:
name: github.com
key: "{{ lookup('pipe', 'ssh-keyscan github.com') }}"
state: present
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:yourorg/yourrepo.git
dest: /opt/app
version: main
Với GitLab hoặc máy chủ riêng, thay github.com bằng host của bạn:
- name: Add GitLab to known_hosts
ansible.builtin.known_hosts:
name: gitlab.example.com
key: "{{ lookup('pipe', 'ssh-keyscan gitlab.example.com') }}"
path: /home/deploy/.ssh/known_hosts
state: present
Tham số path rất dễ bị bỏ qua. Nếu bỏ qua, Ansible mặc định dùng /etc/ssh/ssh_known_hosts. Nhưng nếu task git chạy với tư cách deploy, SSH client của người dùng đó sẽ kiểm tra /home/deploy/.ssh/known_hosts thay vào đó. Luôn đặt path rõ ràng để khớp với người dùng đang thực hiện clone.
Cách xử lý 2: Dùng accept_hostkey (Nhanh nhưng đã bị loại bỏ)
Các phiên bản Ansible cũ hơn có tham số accept_hostkey trực tiếp trên module git:
- name: Clone repository
ansible.builtin.git:
repo: git@github.com:yourorg/yourrepo.git
dest: /opt/app
version: main
accept_hostkey: yes # deprecated in Ansible 2.12+
Ansible đã loại bỏ tham số này từ phiên bản 2.12. Nếu bạn đang thấy cảnh báo [DEPRECATION WARNING]: The 'accept_hostkey' argument is deprecated, hãy chuyển sang Cách xử lý 1 ngay — tham số này sẽ ngừng hoạt động hoàn toàn trong các phiên bản tương lai.
Cách xử lý 3: Cố định thủ công Host Key
Chạy ssh-keyscan trong lúc thực thi task sẽ thực hiện một lần gọi mạng trực tiếp. Nếu bạn muốn pin một key cụ thể — hoặc môi trường của bạn chặn SSH ra ngoài qua cổng 22 — hãy lấy key một lần từ control node:
# On your control node:
ssh-keyscan github.com 2>/dev/null
Sao chép kết quả và nhúng trực tiếp vào playbook của bạn:
- name: Add GitHub host key
ansible.builtin.known_hosts:
name: github.com
key: "github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GkZH"
state: present
GitHub công bố fingerprint chính thức trên trang tài liệu SSH key fingerprints của họ — hãy xác minh key ở đó trước khi pin vào môi trường production.
Cách xử lý 4: Cấu hình SSH trên máy chủ từ xa (Giải pháp cuối cùng)
Khi bạn kiểm soát được máy chủ từ xa và cần giải phóng nhanh, bạn có thể tắt kiểm tra host key nghiêm ngặt qua cấu hình SSH:
- name: Disable StrictHostKeyChecking for git server
ansible.builtin.blockinfile:
path: /home/deploy/.ssh/config
create: yes
mode: '0600'
owner: deploy
block: |
Host github.com
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Chỉ áp dụng cách này cho mạng nội bộ hoặc môi trường CI cô lập. StrictHostKeyChecking no sẽ chấp nhận bất kỳ host key nào một cách âm thầm — kể cả key từ kẻ tấn công MITM. Không dùng cách này trong môi trường production.
Kiểm tra sau khi xử lý
SSH vào máy chủ từ xa và xác nhận key đã được đăng ký:
# Check system-wide known_hosts
grep github.com /etc/ssh/ssh_known_hosts
# Or check user-level
grep github.com ~/.ssh/known_hosts
# Test the SSH connection directly
ssh -T git@github.com
# Expected: Hi username! You've successfully authenticated...
Chạy lại playbook của bạn. Task git sẽ thực thi thành công mà không còn lỗi host key.
Lưu ý thêm
- Sai đường dẫn known_hosts: Đường dẫn rất quan trọng. Task chạy với tư cách root cần key trong
/root/.ssh/known_hostshoặc/etc/ssh/ssh_known_hosts. Task chạy với tư cáchdeploycần key trong/home/deploy/.ssh/known_hosts. Luôn chỉ địnhpathrõ ràng trong taskknown_hosts— đừng để Ansible tự đoán. - GitHub thay thế RSA key năm 2023: GitHub đã thay thế RSA host key vào tháng 3 năm 2023. Các RSA key được cố định trước thời điểm đó sẽ thất bại. Hãy chuyển sang ED25519 key — key này chưa thay đổi và bảo mật hơn.
- Nhiều Git server: Tập hợp tất cả các task
known_hostsvào một role dùng chung hoặc khốipre_tasks. Mọi host đều được chuẩn bị trước khi bất kỳ lệnhgit clonenào chạy. - CI/CD pipelines: Nếu GitHub Actions hoặc GitLab CI chạy các playbook Ansible của bạn, runner cũng gặp vấn đề tương tự. Thêm bước
ssh-keyscanvào phần cài đặt pipeline trước khi gọi Ansible. - Máy chủ riêng dùng cổng không chuẩn: Dùng
ssh-keyscan -p 2222 git.example.comvà đặtname: "[git.example.com]:2222"trong taskknown_hosts— ký hiệu ngoặc vuông là bắt buộc.

