Khắc phục nhanh TL;DR
Lỗi fatal: [host]: UNREACHABLE! trong Ansible gần như luôn chỉ ra rằng nút điều khiển Ansible của bạn không thể thiết lập kết nối SSH với máy chủ đích. Bắt đầu bằng cách kiểm tra kết nối mạng cơ bản bằng ping, sau đó thử kết nối SSH thủ công từ nút điều khiển của bạn đến máy chủ gặp sự cố:
ping <your_target_host_ip_or_hostname>
ssh <your_ssh_user>@<your_target_host_ip_or_hostname>
Nếu một trong hai điều này thất bại, bạn đã tìm thấy điểm bắt đầu của mình: các vấn đề về mạng, tường lửa hoặc máy chủ SSH. Nếu SSH hoạt động thủ công, vấn đề có thể nằm ở cấu hình SSH của Ansible.
Nguyên nhân sâu xa chi tiết
Khi Ansible báo cáo fatal: [host]: UNREACHABLE!, điều đó có nghĩa là cơ chế giao tiếp cơ bản mà Ansible sử dụng (thường là SSH) không thể kết nối với máy chủ được quản lý. Ansible cần có khả năng đăng nhập vào máy đích để thực thi các mô-đun và lệnh. Lỗi này là một triệu chứng cấp cao của một vấn đề kết nối cấp thấp hơn. Không phải Ansible không thể chạy một tác vụ, mà là nó thậm chí không thể giao tiếp với máy chủ ngay từ đầu. Các lý do phổ biến cho điều này bao gồm:
- Sự cố mạng: Nút điều khiển không thể truy cập địa chỉ IP hoặc tên máy chủ của nút được quản lý.
- Hạn chế tường lửa: Tường lửa (trên nút điều khiển, nút được quản lý hoặc ở giữa) đang chặn kết nối SSH (cổng 22 theo mặc định).
- Sự cố SSH Daemon: Máy chủ SSH (
sshd) trên nút được quản lý không chạy, bị cấu hình sai hoặc bị quá tải. - Thông tin đăng nhập/Xác thực không chính xác: Ansible đang cố gắng xác thực bằng tên người dùng, mật khẩu hoặc khóa SSH không chính xác, dẫn đến việc từ chối kết nối.
- Sự cố xác minh khóa máy chủ: SSH không thể xác minh khóa máy chủ của nút được quản lý, thường là do khóa đã thay đổi hoặc kết nối lần đầu.
- Không khớp Inventory: Tên máy chủ hoặc địa chỉ IP trong tệp inventory của Ansible của bạn không chính xác.
Các phương pháp khắc phục
1. Xác minh kết nối mạng
Đầu tiên, hãy đảm bảo nút điều khiển Ansible của bạn thực sự có thể giao tiếp với máy chủ đích ở cấp độ mạng cơ bản.
Cách khắc phục:
-
Ping máy chủ:
ping <your_target_host_ip_or_hostname>
Nếu `ping` thất bại, có một vấn đề về định tuyến mạng cơ bản. Hãy kiểm tra địa chỉ IP của máy chủ, cáp mạng, cài đặt bộ định tuyến hoặc nhóm bảo mật đám mây.
-
**Kiểm tra khả năng truy cập cổng SSH:** Sử dụng `telnet` hoặc `nc` (netcat) để xem cổng 22 (cổng SSH mặc định) có mở và đang lắng nghe hay không.
```bash
telnet <your_target_host_ip_or_hostname> 22
Bạn sẽ thấy một cái gì đó như SSH-2.0-OpenSSH_.... Nếu nó bị treo hoặc kết nối ngay lập tức rồi ngắt kết nối, cổng có thể bị chặn hoặc máy chủ SSH không phản hồi.
Ngoài ra, sử dụng `nc`:
```bash
nc -vz <your_target_host_ip_or_hostname> 22
Tìm kiếm đầu ra như `Connection to <host> 22 port [tcp/ssh] succeeded!`.
#### Xác minh:
Sau khi giải quyết mọi vấn đề về mạng, hãy chạy lại playbook Ansible của bạn hoặc một mô-đun ping đơn giản:
```bash
ansible <your_inventory_group> -m ping
2. Kiểm tra SSH Daemon trên Managed Host
Máy chủ SSH (sshd) trên máy đích của bạn phải đang chạy và được cấu hình chính xác để chấp nhận các kết nối.
Cách khắc phục:
Đăng nhập vào máy chủ được quản lý (nếu có thể, có thể qua console hoặc một phiên SSH đang hoạt động khác) và kiểm tra trạng thái của SSH daemon.
-
Kiểm tra trạng thái dịch vụ SSH:
sudo systemctl status sshd
Nếu nó không chạy, hãy khởi động nó:
```bash
sudo systemctl start sshd
sudo systemctl enable sshd # Để đảm bảo nó khởi động khi boot
-
Xem lại nhật ký SSH daemon: Kiểm tra nhật ký hệ thống để tìm các lỗi liên quan đến SSH.
sudo journalctl -u sshd -e
Hoặc đối với các hệ thống cũ hơn
sudo tail -f /var/log/auth.log sudo tail -f /var/log/secure # RedHat/CentOS
Tìm kiếm các thông báo chỉ ra lý do tại sao các kết nối có thể bị lỗi (ví dụ: lỗi xác thực, sự cố cấu hình).
-
**Kiểm tra `/etc/ssh/sshd_config`:** Đảm bảo `Port 22` (hoặc cổng SSH tùy chỉnh của bạn) không bị comment và `PasswordAuthentication yes` hoặc `PubkeyAuthentication yes` được đặt như mong đợi cho phương pháp xác thực của bạn.
#### Xác minh:
Thử kết nối SSH thủ công từ nút điều khiển:
```bash
ssh <your_ssh_user>@<your_target_host_ip_or_hostname>
Sau khi thành công, hãy thử lại mô-đun ping của Ansible.
3. Giải quyết chặn tường lửa
Tường lửa là nguyên nhân phổ biến gây ra các vấn đề kết nối. Hãy kiểm tra tường lửa trên cả nút điều khiển Ansible và nút được quản lý.
Cách khắc phục:
-
Trên máy chủ được quản lý:
UFW (Ubuntu/Debian): ```bash sudo ufw status verbose sudo ufw allow OpenSSH # hoặc sudo ufw allow 22/tcp sudo ufw enable
- **firewalld (CentOS/RHEL):**
```bash
sudo firewall-cmd --list-all
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload
- **iptables (Linux chung):** Điều này phức tạp hơn, nhưng bạn có thể cần kiểm tra các quy tắc chặn cổng 22. Kiểm tra nhanh các quy tắc hiện có:
```bash
sudo iptables -L -n | grep 22
Bạn có thể cần thêm một quy tắc để cho phép các kết nối SSH đến:
```bash
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Hãy nhớ lưu các quy tắc iptables để chúng tồn tại sau mỗi lần khởi động lại.
-
Trên nút điều khiển: Mặc dù ít phổ biến hơn đối với các kết nối đi, hãy đảm bảo không có quy tắc tường lửa cục bộ nào ngăn nút điều khiển Ansible của bạn khởi tạo các kết nối SSH.
-
Nhóm bảo mật/ACL mạng của nhà cung cấp dịch vụ đám mây: Nếu máy chủ của bạn nằm trong môi trường đám mây (AWS, Azure, GCP), hãy xác minh rằng các nhóm bảo mật hoặc ACL mạng của chúng cho phép lưu lượng truy cập đến trên cổng 22 từ địa chỉ IP của nút điều khiển của bạn.
Xác minh:
Sau khi điều chỉnh các quy tắc tường lửa, hãy thử lại telnet hoặc nc tới cổng 22, sau đó tiến hành mô-đun ping của Ansible:
ansible <your_inventory_group> -m ping
4. Sửa thông tin đăng nhập và xác thực SSH
Ansible dựa vào SSH để xác thực. Nếu Ansible có thể kết nối nhưng không xác thực được, bạn sẽ gặp lỗi không thể truy cập này.
Cách khắc phục:
-
Kiểm tra SSH thủ công: Đầu tiên, hãy đảm bảo bạn có thể SSH thủ công vào máy chủ bằng cách sử dụng chính xác người dùng, khóa hoặc mật khẩu mà Ansible sẽ sử dụng.
ssh <ansible_user>@<your_target_host_ip_or_hostname> -i /path/to/your/private_key
Nếu điều này thất bại, trước tiên hãy giải quyết vấn đề SSH thủ công. Các vấn đề phổ biến bao gồm:
Sai tên người dùng.
- Quyền của tệp khóa riêng tư (phải là `0600` hoặc `0400`): `chmod 600 /path/to/your/private_key`.
- Khóa công khai tương ứng không có trong `~/.ssh/authorized_keys` trên máy chủ được quản lý.
- Mật khẩu không chính xác (nếu sử dụng xác thực bằng mật khẩu).
-
**Ansible Inventory và Cấu hình:** Xác minh tệp inventory của bạn (ví dụ: `/etc/ansible/hosts` hoặc một tệp dành riêng cho dự án) và `ansible.cfg` để biết các tham số SSH chính xác:
**`ansible_host`:** Địa chỉ IP hoặc tên máy chủ của máy đích.
- **`ansible_user`:** Tên người dùng Ansible nên sử dụng để kết nối.
- **`ansible_port`:** Nếu SSH không ở cổng 22.
- **`ansible_private_key_file`:** Đường dẫn đến khóa riêng tư SSH.
- **`ansible_ssh_pass` / `ansible_password`:** Mật khẩu SSH (thường không được khuyến nghị, hãy sử dụng khóa SSH hoặc Ansible Vault).
- **`ansible_ssh_common_args`:** Đối với các đối số SSH tùy chỉnh, ví dụ: `-o StrictHostKeyChecking=no` (sử dụng thận trọng, chỉ dành cho thiết lập ban đầu hoặc môi trường đã biết).
Ví dụ về mục nhập inventory:
```ini
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deployuser ansible_private_key_file=/home/user/.ssh/id_rsa
-
SSH Agent: Nếu bạn sử dụng SSH agent, hãy đảm bảo các khóa của bạn được thêm vào:
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
-
**Xác minh khóa máy chủ:** Nếu bạn thấy cảnh báo về xác minh khóa máy chủ, bạn có thể cần thêm máy chủ vào tệp `known_hosts` của mình. Bạn có thể kết nối thủ công trước:
```bash
ssh <ansible_user>@<your_target_host_ip_or_hostname>
và chấp nhận khóa, hoặc, đối với môi trường tạm thời hoặc được kiểm soát, hãy sử dụng:
```ini
[defaults] host_key_checking = False
trong `ansible.cfg` hoặc đặt `ansible_ssh_common_args='-o StrictHostKeyChecking=no'` trong inventory của bạn (một lần nữa, hãy thận trọng).
#### Xác minh:
Sau khi điều chỉnh chi tiết xác thực, hãy thử lại lệnh Ansible của bạn:
```bash
ansible <your_inventory_group> -m ping
5. Đường dẫn trình thông dịch Python không chính xác
Mặc dù ít phổ biến hơn đối với lỗi UNREACHABLE! (thường xảy ra trước khi bất kỳ mã Python nào chạy), nếu kết nối của bạn thành công trong thời gian ngắn và sau đó bị lỗi với các lỗi lạ, điều đó có thể liên quan đến việc Ansible không tìm thấy trình thông dịch Python trên máy chủ được quản lý.
Cách khắc phục:
Chỉ định đường dẫn trình thông dịch Python chính xác trong inventory hoặc ansible.cfg của bạn:
[webservers:vars]
ansible_python_interpreter=/usr/bin/python3
Hoặc toàn cục trong ansible.cfg:
[defaults]
interpreter_python = auto_silent # Ansible sẽ cố gắng tự động phát hiện. Hoặc chỉ định đường dẫn: /usr/bin/python3
Xác minh:
Chạy một lệnh Ansible đơn giản yêu cầu trình thông dịch Python:
ansible <your_inventory_group> -m setup

