Ansible中使用通配符向服务器委派任务的问题排查
问题描述
我是Ansible新手,若表述不周请谅解。我们的Windows环境中有一批服务器,命名规则如下:
ServerXydv1 ServerXydv2 ServerYzdv1 ServerYzdv2 ServerXyqa1 ServerXyqa2 ServerYzqa1 ServerYzqa2 ServerXy1 ServerXy2 ServerYz1 ServerYz2
host.ini文件按环境(dv、qa、pr)和功能(Xy、Yz)对这些服务器分组,示例如下:
[dev] ServerXydv1 ServerXydv2 ServerYzdv1 ServerYzdv2 [Xy] ServerXydv1 ServerXydv2 ServerXyqa1 ServerXyqa2 ServerXy1 ServerXy2
我希望通过两个YAML文件动态选择目标服务器。主YAML文件内容如下:
- name : "Start" hosts: "{{ host_names }}" vars: ansible_port: 5555 ansible_connection: winrm ansible_winrm_server_cert_validation: ignore ansible_winrm_transport: ntlm tasks: - name: Import Xy Hello import_tasks: file: "XyHello.yaml" when: inventory_hostname in groups["Xy"]
XyHello.yaml内容如下:
- name: XES1 Say Hello win_shell: echo "Say Hello Xy1" delegate_to: ServerX*1 - name: XES2 Say Hello win_shell: echo "Say Hello Xy2" delegate_to: ServerX*2
当host_names设为dev时,剧本能连接服务器、跳过不符合条件的服务器并导入任务,但delegate_to中的通配符*无法被识别。最终我需要根据服务器编号(1或2)运行不同任务,请问我遗漏了什么?如何实现正确的任务委派同时保持剧本环境无关?
解决方案
问题根源
delegate_to不支持直接使用通配符匹配主机名,它需要明确的主机名或者能被Ansible解析的主机变量/分组引用。
具体实现方法
1. 基于功能组筛选对应编号主机
通过Ansible的groups变量和过滤器,从Xy功能组中筛选出对应编号的服务器,修改XyHello.yaml如下:
- name: XES1 Say Hello win_shell: echo "Say Hello Xy1" delegate_to: "{{ groups['Xy'] | select('match', '.*1$') | first }}" - name: XES2 Say Hello win_shell: echo "Say Hello Xy2" delegate_to: "{{ groups['Xy'] | select('match', '.*2$') | first }}"
groups['Xy']:调用Xy功能组的所有主机列表select('match', '.*1$'):筛选出主机名以1结尾的服务器first:取筛选结果中的第一个主机(适合同一编号对应唯一主机的场景)
2. 结合当前环境动态筛选
如果需要限定在指定环境内筛选目标主机,可以通过组交集缩小范围,确保任务只委派到当前环境的对应服务器:
- name: XES1 Say Hello win_shell: echo "Say Hello Xy1" delegate_to: "{{ groups[host_names] | intersect(groups['Xy']) | select('match', '.*1$') | first }}" - name: XES2 Say Hello win_shell: echo "Say Hello Xy2" delegate_to: "{{ groups[host_names] | intersect(groups['Xy']) | select('match', '.*2$') | first }}"
groups[host_names]:获取当前指定环境的所有主机intersect(groups['Xy']):取环境组和Xy功能组的交集,得到当前环境下的Xy服务器
3. 优化任务导入逻辑
原剧本中import_tasks的when条件会让每个主机都执行一次判断,可直接通过主机组交集简化目标范围,主剧本修改如下:
- name : "Start" hosts: "{{ host_names }}:&Xy" vars: ansible_port: 5555 ansible_connection: winrm ansible_winrm_server_cert_validation: ignore ansible_winrm_transport: ntlm tasks: - name: Import Xy Hello import_tasks: "XyHello.yaml"
这里{{ host_names }}:&Xy表示取指定环境组和Xy功能组的交集主机,直接作为任务目标,无需额外的when判断。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

