如何让Ansible在建立SSH隧道前跳过主机连接检查?
最优解决方案:将隧道创建任务转为本地执行,跳过初始远程连接检查
核心问题在于:默认情况下,哪怕是pre_tasks,Ansible也会先尝试与清单中的远程主机建立连接,这就导致了初始连接失败的问题。要解决这个问题,我们可以把隧道创建任务强制在本地执行,完全绕开远程主机的可达性检查,之后再动态修改主机的连接参数,让后续任务通过隧道正常访问VM。
具体实现步骤
- 关闭自动事实收集:避免Ansible在任务开始前触发远程连接
- 在本地执行隧道创建任务:用
delegate_to: localhost和connection: local让隧道命令在控制节点运行,不涉及远程主机连接 - 动态更新主机连接参数:将远程主机的
ansible_host改为127.0.0.1,ansible_port改为隧道映射的本地端口,让后续任务通过隧道连接 - 任务结束后清理隧道:在
post_tasks中关闭隧道,避免资源残留
完整剧本示例
--- - name: 通过Azure Bastion隧道配置VM hosts: all gather_facts: false vars: bastion_name: "your-bastion-resource-name" resource_group: "your-resource-group-name" # 可按主机自定义本地映射端口,比如用主机变量区分不同VM vm_local_port: "{{ 2200 + inventory_hostname | int }}" pre_tasks: - name: 启动Azure Bastion SSH隧道(后台运行) ansible.builtin.command: cmd: > az network bastion tunnel --name {{ bastion_name }} --resource-group {{ resource_group }} --target-resource-id {{ ansible_host }} --resource-port 22 --port {{ vm_local_port }} async: 3600 # 隧道后台存活时长,按需调整 poll: 0 register: tunnel_job delegate_to: localhost connection: local - name: 更新主机连接参数,切换为隧道访问 ansible.builtin.set_fact: ansible_host: "127.0.0.1" ansible_port: "{{ vm_local_port }}" delegate_to: localhost connection: local tasks: # 这里写你的实际配置任务,比如安装软件、修改配置等 - name: 更新系统包缓存 ansible.builtin.apt: update_cache: true become: true when: ansible_os_family == "Debian" - name: 安装常用工具 ansible.builtin.package: name: ["vim", "curl"] state: present become: true post_tasks: - name: 关闭Azure Bastion隧道 ansible.builtin.command: cmd: "kill {{ tunnel_job.ansible_job_id }}" delegate_to: localhost connection: local ignore_errors: true # 忽略可能的kill错误,比如隧道已自动关闭
关键说明
gather_facts: false:禁止Ansible在任务启动前自动收集远程主机信息,这一步会触发初始连接,必须关闭delegate_to: localhost+connection: local:强制任务在控制节点本地执行,完全跳过远程主机的可达性检查,这是解决初始连接失败的核心async: 3600+poll: 0:让隧道命令在后台运行,不会阻塞后续任务执行- 动态修改
ansible_host和ansible_port:让后续的配置任务通过本地隧道端口连接到远程VM,此时Ansible会正常识别主机状态,不会再出现不可达的错误提示
这种方案完全在Ansible内部完成隧道的创建与清理,不会出现执行摘要报错,也能正确识别主机的可达状态,比ignore_unreachable: true的方式更规范可靠。
内容的提问来源于stack exchange,提问作者user826955
相关产品推荐
相关产品推荐

