Ansible Synchronize模块执行证书复制任务时卡住求助
嘿,我来帮你搞定这个同步任务卡住的麻烦!先理清楚你的场景:你想从tower.example.com服务器,把/home/foo/certificates/*/{fullchain.cer,*.key}这些证书文件复制到staging:web:tower:!tower.example.com这组节点上,但用Ansible 2.5执行且开了verbose模式后任务直接卡住了。你的Playbook片段大概是这样的:
- hosts: staging:web:tower:!tower.example.com gather_facts: yes become: yes become_user: foo tasks: - name: synchronize the certificates folder synchronize: src: "/home/foo/certificates/" dest: "{{ certifica..."
结合Ansible 2.5的特性和synchronize模块的工作逻辑,我整理了几个大概率能解决问题的方向:
1. 先搞对synchronize的同步方向和委托节点
默认情况下,synchronize是从你的Ansible控制节点把文件推送到目标节点,但你要的是从tower.example.com这个远程源节点,同步到其他远程节点——这时候必须调整模块的mode和delegate_to参数,不然任务会因为搞不清同步发起方而卡住。
如果是要从tower.example.com推送到其他节点,修正后的任务应该是这样:
- name: 从tower同步证书到目标节点 synchronize: src: "/home/foo/certificates/" dest: "/home/foo/certificates/" # 替换成你实际的目标路径 mode: push delegate_to: tower.example.com
这里的delegate_to是让任务在tower.example.com上执行,由它作为发起端把文件推送到其他节点;mode: push明确是源到目标的推送动作。
2. 修正通配符的使用方式
你要同步的是特定文件fullchain.cer和*.key,直接在src里用/*/{fullchain.cer,*.key}这种通配符可能会被Ansible或者rsync解析出错,建议用rsync_opts来精准过滤文件,避免同步冗余内容,也能解决通配符导致的卡住问题:
- name: 同步指定的证书文件 synchronize: src: "/home/foo/certificates/" dest: "/home/foo/certificates/" mode: push rsync_opts: - "--include=*/" # 先包含所有子目录 - "--include=fullchain.cer" # 包含需要的证书文件 - "--include=*.key" # 包含所有key文件 - "--exclude=*" # 排除其他所有文件 delegate_to: tower.example.com
3. 避开Ansible 2.5的已知bug
Ansible 2.5是比较老的版本了,synchronize模块在处理远程到远程的同步时,可能存在SSH连接复用或者委托节点处理的bug。你可以试试这两个办法:
- 优化SSH连接配置:在你的
ansible.cfg里添加以下配置,开启SSH连接复用,减少连接建立的开销:[ssh_connection] control_path = %(directory)s/%%h-%%p-%%r control_master = auto control_persist = 60s - 绕过
synchronize模块,直接调用rsync命令:如果模块本身有问题,用command模块直接执行rsync会更可靠: - name: 用rsync命令直接同步证书
command: rsync -avz --include='/' --include='fullchain.cer' --include='.key' --exclude='*' foo@tower.example.com:/home/foo/certificates/ /home/foo/certificates/
become_user: foo
4. 手动验证rsync和SSH连通性
任务卡住大概率是底层的rsync或SSH出了问题,你可以先在目标节点上手动执行rsync命令测试:
rsync -avz --include='*/' --include='fullchain.cer' --include='*.key' --exclude='*' foo@tower.example.com:/home/foo/certificates/ /home/foo/certificates/
如果手动执行也卡住,那问题就出在tower.example.com和目标节点之间的SSH信任关系(比如foo用户的密钥没在目标节点授权),或者网络问题;如果手动执行正常,那就是Ansible模块的问题,直接用上面的command模块方案就行。
内容的提问来源于stack exchange,提问作者sf_tristanb

