主机名非静态时,跨组复用Ansible主机变量的问题
解决Ansible多Play切换主机后变量丢失的备份上传问题
你遇到的是Ansible的核心特性:变量与主机绑定,跨Play切换主机后,原主机的变量无法直接访问。针对批量处理Palo防火墙备份并上传到Azure Blob的需求,以下是几种可行的解决思路:
方案1:用add_host收集备份信息到临时组
在第一个Play中,将每台防火墙的备份文件路径、目标Blob路径等信息添加到一个临时主机组,第二个Play遍历这个组的信息完成批量上传。
修改第一个Play的任务:
- name: Pull configuration backups from Palo firewalls hosts: groupName gather_facts: no tasks: # 原有备份任务... - name: Saving configuration file... connection: local check_mode: no ansible.builtin.copy: content: "{{ configuration_string['content'] }}" dest: '/etc/ansible/backups/{{ inventory_hostname }}/{{ inventory_hostname }}_{{ current_date }}.txt' # 添加临时组收集备份信息 - name: Register backup details to temporary group ansible.builtin.add_host: name: "{{ inventory_hostname }}" groups: backup_hosts backup_src_path: '/etc/ansible/backups/{{ inventory_hostname }}/{{ inventory_hostname }}_{{ current_date }}.txt' blob_dest_path: '/{{ inventory_hostname }}/{{ inventory_hostname }}_{{ current_date }}.txt'
第二个Play遍历临时组的信息执行上传:
- name: Copy configuration from Ansible to Azure Blob... gather_facts: no pre_tasks: - include_vars: /etc/ansible/sftp_secrets.yml hosts: AzureBlobStorage tasks: - name: Copying files to Azure blob storage via SFTP... ansible.netcommon.net_put: src: "{{ hostvars[item].backup_src_path }}" protocol: sftp destination: "{{ hostvars[item].blob_dest_path }}" loop: "{{ groups['backup_hosts'] }}"
方案2:将备份信息存储到localhost的全局变量
在第一个Play中,把所有防火墙的备份信息收集到localhost的变量中,第二个Play直接读取这个变量循环上传。
修改第一个Play的任务:
- name: Pull configuration backups from Palo firewalls hosts: groupName gather_facts: no tasks: # 原有备份任务... - name: Saving configuration file... connection: local check_mode: no ansible.builtin.copy: content: "{{ configuration_string['content'] }}" dest: '/etc/ansible/backups/{{ inventory_hostname }}/{{ inventory_hostname }}_{{ current_date }}.txt' # 收集备份信息到localhost变量 - name: Collect backup info to localhost ansible.builtin.set_fact: backup_list: "{{ backup_list | default([]) + [ {'host': inventory_hostname, 'file': inventory_hostname ~ '_' ~ current_date} ] }}" delegate_to: localhost delegate_facts: true
第二个Play循环读取localhost的backup_list:
- name: Copy configuration from Ansible to Azure Blob... gather_facts: no pre_tasks: - include_vars: /etc/ansible/sftp_secrets.yml hosts: AzureBlobStorage tasks: - name: Copying files to Azure blob storage via SFTP... ansible.netcommon.net_put: src: "/etc/ansible/backups/{{ item.host }}/{{ item.file }}.txt" protocol: sftp destination: "/{{ item.host }}/{{ item.file }}.txt" loop: "{{ hostvars['localhost'].backup_list }}"
方案3:直接遍历备份目录(无需变量传递)
如果备份路径的命名规则固定(比如主机名作为子目录,文件名包含主机名和日期),可以直接在第二个Play中扫描备份目录,解析路径信息完成上传,无需传递变量。
修改第二个Play:
- name: Copy configuration from Ansible to Azure Blob... gather_facts: no pre_tasks: - include_vars: /etc/ansible/sftp_secrets.yml hosts: AzureBlobStorage tasks: # 扫描备份目录获取所有文件 - name: Get all backup files ansible.builtin.find: path: "/etc/ansible/backups" recurse: yes patterns: "*.txt" delegate_to: localhost register: backup_files # 循环上传每个文件 - name: Copying files to Azure blob storage via SFTP... ansible.netcommon.net_put: src: "{{ item.path }}" protocol: sftp # 从路径中解析主机名(倒数第二个目录)和文件名 destination: "/{{ item.path.split('/')[-2] }}/{{ item.path.split('/')[-1] }}" loop: "{{ backup_files.files }}"
方案选型建议
- 方案1/2适合需要传递额外上下文变量(比如备份备注、自定义路径规则)的场景,能保留更多备份相关信息。
- 方案3适合备份路径规则固定、无需额外变量的情况,实现更简洁,不需要修改原有备份Play的逻辑。
内容的提问来源于stack exchange,提问作者Moridn
相关产品推荐
相关产品推荐

