Nguyên nhân gây ra lỗi này
Bạn chạy một Ansible playbook nhắm vào Windows host và nhận được thông báo:
fatal: [win_host]: UNREACHABLE! => {"msg": "ssl: HTTPSConnectionPool(host='192.168.1.10', port=5986): Max retries exceeded with url: /wsman"}
Kết nối chưa kịp thiết lập đã thất bại. Thường có ba nguyên nhân: cổng chưa mở, SSL handshake bị lỗi, hoặc Ansible không tin tưởng certificate. Xác định trường hợp phù hợp với bạn và thực hiện theo các bước bên dưới.
Nguyên nhân gốc rễ
- WinRM HTTPS listener chưa được cấu hình trên Windows host
- Cổng 5986 bị chặn bởi Windows Firewall hoặc firewall mạng phía trước
- Self-signed certificate không được Ansible tin tưởng (thiếu
validate_certs: false) - Gói
pywinrmchưa cài hoặc phiên bản quá cũ trên Ansible controller - Sai
ansible_winrm_transporthoặc các biến kết nối trong inventory
Cách sửa nhanh: tắt xác thực certificate để kiểm tra
Hầu hết môi trường lab nội bộ và staging đều dùng self-signed certificate. Mặc định, Ansible sẽ từ chối các kết nối như vậy. Thêm các dòng sau vào inventory hoặc group_vars để bỏ qua xác thực certificate trong lúc chẩn đoán:
[windows:vars]
ansible_user=Administrator
ansible_password=YourPassword
ansible_connection=winrm
ansible_winrm_scheme=https
ansible_port=5986
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
Sau đó chạy thử kiểm tra kết nối nhanh:
ansible win_host -m win_ping
Nếu thành công, SSL certificate chính là thủ phạm — không có gì khác. Hãy bỏ qua và đến phần sửa vĩnh viễn bên dưới.
Bước 1: Kiểm tra xem WinRM có đang chạy không
Kết nối RDP hoặc console vào máy Windows và chạy các lệnh sau trong PowerShell:
Get-Service WinRM
winrm enumerate winrm/config/listener
Bạn cần thấy một listener hiển thị Transport=HTTPS trên cổng 5986. Nếu kết quả chỉ thấy HTTP trên cổng 5985, tức là HTTPS listener chưa được thiết lập.
Khởi tạo WinRM HTTPS với self-signed cert chỉ trong một bước:
# Run on the Windows host as Administrator
$cert = New-SelfSignedCertificate -DnsName "$(hostname)" -CertStoreLocation Cert:\LocalMachine\My
$thumbprint = $cert.Thumbprint
New-WSManInstance -ResourceURI winrm/config/listener `
-SelectorSet @{Address="*"; Transport="HTTPS"} `
-ValueSet @{CertificateThumbprint=$thumbprint}
# Prefer the Ansible-maintained setup script instead:
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file
Script của Ansible xử lý việc tạo cert, thiết lập listener và cấu hình firewall chỉ trong một lần — rất đáng dùng nếu bạn cần cài đặt cho nhiều host.
Bước 2: Mở cổng 5986 trong Windows Firewall
New-NetFirewallRule -DisplayName "Ansible WinRM HTTPS" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 5986 `
-Action Allow
Đang chạy trên AWS, Azure, hoặc GCP? Đừng quên security group hoặc NSG — các quy tắc Windows Firewall sẽ vô nghĩa nếu tầng cloud đang chặn lưu lượng ở cấp VPC.
Từ Ansible controller, kiểm tra xem cổng 5986 có thực sự kết nối được không:
nc -zv 192.168.1.10 5986
# or
curl -k https://192.168.1.10:5986/wsman
Chỉ cần curl trả về HTTP 401 hoặc 500 là cổng đã mở và WinRM đang hoạt động. Nếu bị từ chối kết nối hoặc timeout thì firewall vẫn đang chặn.
Bước 3: Cài pywinrm trên Ansible controller
Không có pywinrm thì không thể kết nối WinRM — Ansible cần gói này để giao tiếp theo giao thức này:
pip install pywinrm
pip install pywinrm[kerberos] # domain environments using Kerberos
pip install pywinrm[credssp] # if using CredSSP auth
Xác nhận đã cài và kiểm tra phiên bản (cần từ 0.4.x trở lên):
pip show pywinrm
Sửa vĩnh viễn: tin tưởng certificate của Windows host
Đưa server_cert_validation=ignore lên môi trường production là một ý tưởng tồi. Nó mở ra nguy cơ tấn công man-in-the-middle vào hệ thống tự động hóa của bạn. Cách sửa thực sự là xuất certificate của Windows host và thêm vào kho tin tưởng trên Ansible controller.
Trên Windows host, xuất certificate:
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match "$(hostname)"}
Export-Certificate -Cert $cert -FilePath C:\winrm_cert.cer -Type CERT
Sao chép winrm_cert.cer sang Ansible controller (qua scp, SMB share, hay bất kỳ cách nào bạn có), rồi chuyển đổi và cài đặt:
# Convert .cer (DER format) to PEM
openssl x509 -inform DER -in winrm_cert.cer -out winrm_cert.pem
# Ubuntu/Debian
cp winrm_cert.pem /usr/local/share/ca-certificates/winrm_cert.crt
update-ca-certificates
# RHEL/CentOS
cp winrm_cert.pem /etc/pki/ca-trust/source/anchors/
update-ca-trust extract
Sau đó cập nhật inventory để xác thực đúng cách:
[windows:vars]
ansible_winrm_server_cert_validation=validate
ansible_winrm_ca_trust_path=/path/to/winrm_cert.pem
Tham khảo: inventory hoàn chỉnh
Đây là inventory đầy đủ hoạt động với NTLM qua HTTPS — hãy sao chép và chỉnh sửa theo nhu cầu:
[windows]
win_host ansible_host=192.168.1.10
[windows:vars]
ansible_user=Administrator
ansible_password=YourSecurePassword
ansible_connection=winrm
ansible_winrm_scheme=https
ansible_port=5986
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
Host đã tham gia domain với Active Directory? Chuyển sang Kerberos — bảo mật hơn và xử lý token delegation đúng cách:
ansible_winrm_transport=kerberos
ansible_user=user@DOMAIN.COM
Kiểm tra sau khi sửa
Bắt đầu với win_ping — bài kiểm tra kết nối ít tốn tài nguyên nhất mà Ansible có cho Windows:
ansible win_host -m win_ping
Kết quả mong đợi:
win_host | SUCCESS => {
"changed": false,
"ping": "pong"
}
Sau khi ping thành công, chạy một lệnh thực tế để xác nhận toàn bộ hệ thống hoạt động đầu cuối:
ansible win_host -m win_shell -a "Get-ComputerInfo | Select-Object WindowsProductName"
Vẫn thấy lỗi SSL sau tất cả những bước trên? Tăng mức độ chi tiết lên bốn và lọc trace của quá trình handshake:
ansible win_host -m win_ping -vvvv 2>&1 | grep -i ssl
Kết quả handshake sẽ cho bạn biết chính xác nơi thất bại — CN của certificate không khớp, cert hết hạn, CA không được tin tưởng, v.v.

