You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 17:33:02