如何从目标主机获取Ansible控制节点的IP地址?
隔离网络中Ansible控制节点文件分发:无需硬编码IP的实现方案
场景与问题
在无公网的隔离网络中,使用Ansible控制节点(示例IP:192.168.0.5)管理多台目标主机(示例IP:192.168.0.10/11/12),需要让目标主机通过HTTP/HTTPS从控制节点下载文件,但存在以下限制:
- 控制节点通过DHCP获取IP,地址不固定;
- 控制节点有多块网卡,
ansible_all_ipv4_addresses包含目标主机无法访问的IP,无法直接通过控制节点的facts确定可用地址; - 不想通过循环尝试IP的方式测试可用性,希望直接获取目标主机能访问的控制节点IP。
为什么选择HTTP/HTTPS下载而非直接传输
部分目标主机为Windows系统,win_copy模块基于WinRM传输大文件速度极慢,Ansible文档明确提示:
由于win_copy通过WinRM运行,并非高效的传输机制。若传输大文件,建议将其托管在Web服务上,改用ansible.windows.win_get_url模块。
解决方案:从目标主机侧获取控制节点的连接源IP
核心思路:目标主机与控制节点已通过WinRM/SSH建立了管理连接,从目标主机视角查看该连接的远程IP(即控制节点的源IP),这个IP就是目标主机能直接访问的控制节点地址。
实现步骤与Playbook示例
以下是跨Linux/Windows目标主机的通用实现:
- name: 从控制节点分发文件至目标主机(自动获取控制节点IP) hosts: all gather_facts: yes vars: target_file: "large_data.iso" # 要分发的文件(需放在控制节点执行Playbook的目录) web_port: 8000 # 临时Web服务端口 tasks: # 1. 在控制节点启动临时HTTP服务(后台运行) - name: 启动临时HTTP服务器 delegate_to: localhost command: python3 -m http.server {{ web_port }} --bind 0.0.0.0 async: 3600 # 后台运行1小时 poll: 0 changed_when: false when: ansible_connection != 'local' # 2. 针对Linux目标主机获取控制节点IP - name: 获取控制节点源IP(Linux) shell: | ss -tunap | grep "{{ ansible_port }}" | grep ESTAB | awk '{print $5}' | cut -d: -f1 | head -n1 register: ctrl_ip_linux when: ansible_os_family in ['Debian', 'RedHat'] # 3. 针对Windows目标主机获取控制节点IP - name: 获取控制节点源IP(Windows) win_shell: | Get-NetTCPConnection -LocalPort {{ ansible_port }} -State Established | Select-Object -ExpandProperty RemoteAddress register: ctrl_ip_windows when: ansible_os_family == 'Windows' # 4. 统一设置控制节点IP变量 - name: 定义controller_source_ip变量 set_fact: controller_source_ip: "{{ ctrl_ip_linux.stdout if ansible_os_family != 'Windows' else ctrl_ip_windows.stdout_lines[0] }}" # 5. Linux目标主机下载文件 - name: 下载文件到Linux主机 get_url: url: "http://{{ controller_source_ip }}:{{ web_port }}/{{ target_file }}" dest: "/tmp/{{ target_file }}" when: ansible_os_family in ['Debian', 'RedHat'] # 6. Windows目标主机下载文件 - name: 下载文件到Windows主机 win_get_url: url: "http://{{ controller_source_ip }}:{{ web_port }}/{{ target_file }}" dest: "C:\\Temp\\{{ target_file }}" when: ansible_os_family == 'Windows' # 7. 停止控制节点的临时HTTP服务 - name: 停止临时HTTP服务器 delegate_to: localhost command: pkill -f "python3 -m http.server {{ web_port }}" changed_when: false when: ansible_connection != 'local'
关键说明
- 临时Web服务:使用Python内置的HTTP服务器,无需额外安装;若控制节点已有常驻Web服务,可跳过启动/停止步骤,直接使用对应端口。
- 连接端口匹配:
ansible_port变量会自动获取当前Ansible连接使用的端口(SSH默认22,WinRM默认5985/5986),确保准确匹配当前管理连接。 - 跨平台兼容:分别针对Linux和Windows系统执行不同的命令获取IP,保证兼容性。
内容的提问来源于stack exchange,提问作者gratz
相关产品推荐
相关产品推荐

