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

Ansible如何仅在指定的primary主机上执行带with_items的任务?

Ansible任务仅在标记为primary的主机执行的问题

现有配置

group_vars/my_app 中的变量定义

ldap:
  - { name: machine1.domain.com, machine: primary }
  - { name: machine2.domain.com, machine: secondary }
  - { name: machine3.domain.com, machine: tertiary }
  - { name: machine4.domain.com, machine: quaternary }

Inventory 文件内容

[ldap]
machine1.domain.com
machine2.domain.com
machine3.domain.com
machine4.domain.com

需求

针对ldap组所有主机运行playbook,但其中一个替换任务仅需在ldap变量中标记为primary的主机上执行,原任务代码如下:

- name: Patch only first machine
  replace:
    dest: "/opt/data1.ldif"
    regexp: "{{item.regexp}}"
    replace: "{{item.line}}"
  with_items:
    - { regexp: '__ANSIBLE_BIND_PASSWD__', line: "{{secrets[env][role].bpasswd}}" }
    - { regexp: '__ANSIBLE_ADMIN_PASSWD__', line: "{{secrets[env][role].apasswd}}" }
  when: ???
  no_log: True

最初考虑通过遍历ldap列表并加条件判断,但任务已经使用with_items处理替换规则,不确定是否需要用with_nested。

解决方案

不需要使用嵌套循环,直接通过when条件筛选主机即可,有两种简洁的实现方式:

方式一:直接在when中使用过滤器筛选

利用Ansible的过滤器从ldap列表中提取所有primary主机的名称,再判断当前主机是否在该列表内:

- name: Patch only primary LDAP machine
  replace:
    dest: "/opt/data1.ldif"
    regexp: "{{item.regexp}}"
    replace: "{{item.line}}"
  with_items:
    - { regexp: '__ANSIBLE_BIND_PASSWD__', line: "{{secrets[env][role].bpasswd}}" }
    - { regexp: '__ANSIBLE_ADMIN_PASSWD__', line: "{{secrets[env][role].apasswd}}" }
  when: ansible_fqdn in (ldap | selectattr('machine', 'equalto', 'primary') | map(attribute='name') | list)
  no_log: True

方式二:预先定义primary主机变量

先在group_vars/my_app中定义一个专门的变量存储primary主机名:

# 在group_vars/my_app中添加
primary_ldap_host: "{{ ldap | selectattr('machine', 'equalto', 'primary') | map(attribute='name') | first }}"

然后任务的when条件直接判断当前主机是否匹配:

- name: Patch only primary LDAP machine
  replace:
    dest: "/opt/data1.ldif"
    regexp: "{{item.regexp}}"
    replace: "{{item.line}}"
  with_items:
    - { regexp: '__ANSIBLE_BIND_PASSWD__', line: "{{secrets[env][role].bpasswd}}" }
    - { regexp: '__ANSIBLE_ADMIN_PASSWD__', line: "{{secrets[env][role].apasswd}}" }
  when: ansible_fqdn == primary_ldap_host
  no_log: True

逻辑说明

任务中的with_items负责遍历替换规则,而主机的筛选通过when条件独立控制,这样既保留了原任务的替换逻辑,又确保只有标记为primary的主机会执行该任务,避免了嵌套循环带来的冗余执行逻辑。

内容的提问来源于stack exchange,提问作者echodrome

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 11:03:13