1. 问题现象:当Ansible伸出友谊的小手被拒绝时

深夜两点,你盯着屏幕上的红色报错信息陷入沉思:

fatal: [web-server]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true}

这个报错就像一扇紧闭的大门,而Ansible手里攥着错误的钥匙。别慌!让我们化身数字侦探,揪出SSH认证失败的元凶。


2. 排雷四部曲:从入门到入土的排查指南

2.1 第一步:确认物理连接可行性
$ ping web-server
PING web-server (192.168.1.100) 56(84) bytes of data.
64 bytes from web-server (192.168.1.100): icmp_seq=1 ttl=64 time=0.423 ms

# 检查SSH端口连通性(TCP协议)
$ nc -zv web-server 22
Connection to web-server 22 port [tcp/ssh] succeeded!

如果这两个测试失败,请检查:

  • 防火墙规则(特别是云主机的安全组)
  • 主机是否处于运行状态
  • 网络路由配置
2.2 第二步:直连测试SSH服务
# 使用与Ansible相同的用户身份手动连接
$ ssh -i ~/.ssh/ansible_key deploy@web-server
Last login: Wed Jul 12 02:34:56 2023 from 10.0.0.5
[deploy@web-server ~]$ 

如果手动连接成功但Ansible失败,说明问题出在Ansible配置而非SSH本身

2.3 第三步:Ansible的"坦白模式"
# 启用SSH调试模式(显示握手全过程)
$ ANSIBLE_SSH_ARGS="-vvvv" ansible all -m ping
...
debug3: send packet: type 50
debug2: we sent a publickey packet, wait for reply
debug3: receive packet: type 51
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password
debug2: we did not send a packet, disable method
debug1: No more authentication methods to try.
deploy@web-server: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).

这段输出就像SSH协议的实时字幕,注意观察:

  • 密钥文件是否被正确识别
  • 认证顺序是否符合预期
  • 服务端支持的认证方式

3. 七大经典翻车现场与求生指南

3.1 密钥权限:Linux的洁癖有多严重
# 错误示例:密钥权限过松
$ ls -l ~/.ssh/
-rw-rw-rw- 1 user user 1675 Jul 12 03:00 ansible_key

# 正确操作(仅限所有者读写)
$ chmod 600 ~/.ssh/ansible_key
$ chmod 700 ~/.ssh/

权限过高的密钥文件会被SSH直接拒绝,这是Linux的安全机制

3.2 配置文件捉迷藏
# ansible.cfg的正确打开方式
[defaults]
inventory = hosts
private_key_file = /home/deploy/.ssh/ansible_key  # 绝对路径更可靠
host_key_checking = False  # 首次连接跳过确认

[ssh_connection]
ssh_args = -o ControlMaster=auto 
           -o ControlPersist=60s
           -o ConnectTimeout=30
           -o ServerAliveInterval=60

常见坑点:

  • 相对路径陷阱(建议用绝对路径)
  • 多配置文件的优先级问题
  • 过短的超时设置导致偶发失败
3.3 用户身份的三重门禁
# playbook.yml中的用户设置陷阱
- hosts: web-server
  # 错误示例:同时指定用户和密钥
  remote_user: deploy
  vars:
    ansible_ssh_private_key_file: /wrong/path/key.pem
  tasks:
    - name: Test connection
      ping:

正确的用户映射应该这样处理:

# 在inventory中精准配置
[web-servers]
web-server ansible_host=192.168.1.100 
  ansible_user=deploy 
  ansible_ssh_private_key_file=/home/deploy/.ssh/ansible_key

4. 高级战场:那些藏在角落的魔鬼

4.1 sudo权限的隐形锁
# 当需要提权时的正确姿势
ansible_user: deploy
become: yes
become_method: sudo
become_user: root

# 对应需要在目标机配置的sudo权限
# visudo配置示例
deploy ALL=(ALL) NOPASSWD: ALL
4.2 SSH代理转发:钥匙不在身边怎么办
# ansible.cfg启用代理转发
[ssh_connection]
ssh_args = -o ForwardAgent=yes

使用场景:

  • 通过跳板机连接内网主机
  • 密钥只存储在本地工作站时

5. 技术栈全景分析(Ansible+OpenSSH)

5.1 应用场景矩阵
场景 解决方案 典型配置项
多环境密钥 目录分级存储 private_key_file按环境配置
混合云环境 Jump Host配置 ProxyCommand+ssh_args
大规模主机 连接池优化 pipelining=true
敏感数据管理 Ansible Vault加密 ansible-vault加密变量文件
5.2 技术优劣对比

优势:

  • 无代理架构降低维护成本
  • 基于SSH的天然安全性
  • 细粒度的连接控制参数

局限:

  • 大规模主机并发时性能瓶颈
  • 对Windows支持需要额外配置
  • 调试复杂网络拓扑较困难

6. 避坑法则:运维老司机的安全驾驶手册

  1. 密钥管理三原则

    • 生产环境禁用密码认证
    • 定期轮转密钥
    • 使用专用部署账户
  2. 连接优化四要素

    [ssh_connection]
    pipelining = True  # 减少SSH会话数
    control_path = %(directory)s/ansible-ssh-%%h-%%p-%%r  # 复用连接
    timeout = 30  # 合理超时设置
    
  3. 审计三板斧

    # 查看成功登录记录
    $ sudo grep "Accepted publickey" /var/log/auth.log
    
    # 查看失败尝试
    $ sudo grep "Failed publickey" /var/log/secure
    
    # 实时监控SSH连接
    $ watch -n 5 'ss -tnop | grep :22'
    

7. 总结:与SSH和解的艺术

当Ansible与SSH的"爱情故事"出现裂痕时,记住这个诊断口诀:

一测网络二看权,三查配置四验连
密钥权限莫要松,sudo配置别漏空
调试参数是法宝,日志分析见真章

掌握这些技巧后,你会发现SSH认证失败就像解谜游戏——每个错误提示都是通往解决方案的线索。保持耐心,善用工具,终将成为Ansible世界的"红娘",让每个节点都顺利牵手!