Ansible替换连接用户公钥时SSH连接中断问题解决方案
问题原因
原有实现出现SSH断连的核心原因是:先删除authorized_keys文件的操作制造了认证文件缺失的空窗期,SSH服务端在连接复用、会话合法性校验时检测到授权密钥文件不存在,会直接中断现有Ansible控制连接,导致后续任务无法执行。
提到的两种临时方案本质都没有解决「文件操作非原子、存在空窗期」的核心问题,还引入了额外的运维复杂度,完全不需要采用。
原生最优方案
Ansible官方提供了专门用于管理SSH授权密钥的内置模块ansible.posix.authorized_key,该模块采用临时文件写入+原子替换的逻辑,全程不会删除原authorized_keys文件,不存在认证空窗期,完全不会触发SSH断连,是这类场景的标准实现。
全量替换公钥实现(匹配原逻辑需求:清除旧公钥、仅保留新指定公钥)
配置exclusive: yes参数即可实现原逻辑中「删除旧文件、写入新公钥」的效果,无需单独执行删除操作:
- name: "{{ansibleuser_username}} : Configure SSH authorized public key" ansible.posix.authorized_key: user: "{{ansibleuser_username}}" key: "{{ansibleuser_public_key}}" exclusive: yes manage_dir: yes when: ansibleuser_public_key is defined
参数说明
user: 指定公钥所属的系统用户,模块会自动定位到对应用户主目录下的.ssh/authorized_keys路径;如果家目录为非标准路径,可额外添加path参数指定文件完整路径exclusive: yes: 全量覆盖文件内所有公钥,移除所有未在key参数中指定的公钥,完全匹配原有删除旧文件重建的需求manage_dir: yes: 模块自动检查并修正.ssh目录、authorized_keys文件的属主和权限,默认将文件权限设为0600、目录权限设为0700,符合SSH安全认证要求,无需手动配置owner/group/mode参数
通用文件模块替代方案
如果环境限制无法使用ansible.posix集合,也可使用copy模块实现原子写入,同样不会出现断连问题:
- name: "{{ansibleuser_username}} : Set authorized public key" copy: content: "{{ansibleuser_public_key}}\n" dest: "{{ansibleuser_home_dir}}/.ssh/authorized_keys" owner: "{{ansibleuser_username}}" group: "{{ansibleuser_username}}" mode: '0600' backup: yes when: ansibleuser_public_key is defined
注意:不建议使用
lineinfile模块做全量密钥替换,该模块按行匹配修改,无法保证全量覆盖的一致性,容易出现重复行、旧配置残留的问题。
内容的提问来源于stack exchange,提问作者David Koenig
相关产品推荐
相关产品推荐

