Ansible主Play中能否设置子Play,实现分组防火墙无跳过配置?
问题描述
我有一个多层级的Ansible Inventory结构,示例如下:
my_large_infrastructure: children: frontend_servers: children: frontend_servers_cluster1: hosts: server1: ansible_host: 10.0.0.1 server2: ansible_host: 10.0.0.2 frontend_server_cluster2: hosts: server3: ansible_host: 10.0.0.3 server4: ansible_host: 10.0.0.4 [...]
当前我有一个针对整个集群的防火墙配置Playbook,但需要针对每个子组单独执行对应的防火墙规则任务。如果为每个子组单独创建Play,不够优雅;用when: frontend_servers_cluster1 in group_names会导致大量主机被跳过,不符合预期。
我希望保留一个名为Apply firewall rules to My Large infrastructure的主Play,在其下实现针对子组的精准任务执行,最终输出无跳过主机的结果,类似:
PLAY [Apply firewall rules to My Large infrastructure] ***************************************************************************************** TASK [Gathering Facts] ***************************************************************************************** ok: [server1] ok: [server2] ok: [server3] ok: [server4] TASK [Apply firewall rules on the Frontend Cluster1 Servers] ***************************************************************************************** ok: [server1] ok: [server2] TASK [Apply firewall rules on the Frontend Cluster2 Servers] ***************************************************************************************** ok: [server3] ok: [server4]
解决方案
方法1:任务级hosts参数(Ansible 2.10+)
Ansible 2.10及以上版本支持在任务级别指定hosts参数,直接限定任务仅在目标子组上执行,不会产生跳过的主机记录。修改后的Playbook如下:
--- - name: Apply firewall rules to My Large infrastructure hosts: my_large_infrastructure become: true tasks: - name: Apply firewall rules on the Frontend Cluster1 Servers include_role: name: firewall_management vars: config_file: 'ipv4_firewall_cluster1.j2' ipv6_config_file: 'ipv6_firewall_cluster1.j2' hosts: frontend_servers_cluster1 - name: Apply firewall rules on the Frontend Cluster2 Servers include_role: name: firewall_management vars: config_file: 'ipv4_firewall_cluster2.j2' ipv6_config_file: 'ipv6_firewall_cluster2.j2' hosts: frontend_server_cluster2
该方案直接在任务中指定执行的目标子组,任务仅在对应子组的主机上运行,其他主机不会触发该任务,自然不会出现跳过记录。
方法2:动态临时组+子Play(兼容旧版Ansible)
如果你的Ansible版本低于2.10,可通过动态添加主机到临时组,再在子Play中指定目标:
--- - name: Apply firewall rules to My Large infrastructure hosts: my_large_infrastructure become: true tasks: - name: 收集cluster1所有主机到临时组 add_host: name: "{{ item }}" groups: temp_cluster1 loop: "{{ groups['frontend_servers_cluster1'] }}" run_once: true - name: 收集cluster2所有主机到临时组 add_host: name: "{{ item }}" groups: temp_cluster2 loop: "{{ groups['frontend_server_cluster2'] }}" run_once: true - name: Apply firewall rules on the Frontend Cluster1 Servers hosts: temp_cluster1 become: true tasks: - include_role: name: firewall_management vars: config_file: 'ipv4_firewall_cluster1.j2' ipv6_config_file: 'ipv6_firewall_cluster1.j2' - name: Apply firewall rules on the Frontend Cluster2 Servers hosts: temp_cluster2 become: true tasks: - include_role: name: firewall_management vars: config_file: 'ipv4_firewall_cluster2.j2' ipv6_config_file: 'ipv6_firewall_cluster2.j2'
这种方式通过临时组精准定位子组主机,每个子Play只处理对应主机,同样不会产生跳过记录。
内容的提问来源于stack exchange,提问作者Tony
相关产品推荐
相关产品推荐

