【问题标题】:How to keep ansible role from running multiple times when listed as a dependency?当列为依赖项时,如何防止ansible角色多次运行?
【发布时间】:2025-12-06 15:25:01
【问题描述】:

我们将庞大的 ansible 工作区分解为可以独立运行的单个简单角色。它们都依赖于我们提供存储库等的 yum 角色,并且所有角色(A、B、C)都在其meta.yml 中列出:

./roles_galaxy/A/meta/main.yml:
dependencies:
  - name: yum-repo
    src: foo

./roles_galaxy/B/meta/main.yml:
dependencies:
  - name: yum-repo
    src: foo

./roles_galaxy/C/meta/main.yml:
dependencies:
  - name: yum-repo
    src: foo

但是,这会导致 yum-repo 角色在我们的部署手册运行时多次执行,因此我们看到yum-repo 角色的多次执行。我们不希望它这样做,因为它只会占用额外的时间并重复运行:

剧本:

- name: Common Roles
  hosts: things
  roles:
    - A
    - B
    - C

输出:

PLAY [Role A] 
...
TASK [yum-repo ...]

PLAY [Role B] 
...
TASK [yum-repo ...]

PLAY [Role C] 
...
TASK [yum-repo ...]

我在ansible.cfg 中尝试过allow_duplicates = false,但我认为这不是正确的解决方案,因为它仍然会执行多次。

如果需要更多信息,我非常乐意尝试提供一个经过整理的版本。目前正在运行 ansible-2.5.5。

【问题讨论】:

  • 您使用的是import_role 还是include_role?如果是这样,请参阅Include_role loop installs role and dependencies multiple times
  • 角色 A/B/C 是否有不同的标签? “Ansible 只执行一次角色依赖,即使定义了多次,除非角色上定义的 参数、标签或 when 子句对于每个定义都不同。”

标签: ansible ansible-role


【解决方案1】:

假设您使用的是import_role 和/或include_role,直到Include_role loop installs role and dependencies multiple times 得到修复,我建议您如下:

  1. 不要将您的依赖角色指定为依赖项。
  2. 仅在调用 import_role 和/或 include_role 时指定它们。

【讨论】:

  • 这也是为了防止由于角色执行规则而在角色任务之前执行角色规范: - 角色 meta/main.yml 中定义的任何角色依赖项将首先运行,受标签过滤和条件。见docs.ansible.com/ansible/latest/user_guide/…
【解决方案2】:

一年多过去了,ansible 重复检测仍然失败。

我设置了一个 ansible fact,然后在其他角色中,使用

- 名称:包括依赖角色 包括角色: 名称: 萨默罗 何时: has_it_run_fact 未定义

【讨论】:

    【解决方案3】:

    查看docs which cover this subject (Role Duplication and Execution)

    Ansible 力求采用最有效的方法,并避免多次运行一个角色,除非它使用的任何参数在您的游戏中每次声明时都不同。是不是每次你的 yum 角色运行时,它都在配置不同的 yum repo?

    不确定在 Yum 角色的情况下它有多相关,但是一种可能的策略是将共同的、一次性的东西拆分为单独的角色,然后将共同角色 a dependency of the main role。这导致应用一次的公共角色,然后针对 params 中的每个差异调用任意数量的主要角色。

    【讨论】:

    • 是否每次你的 yum 角色运行时,它都在配置不同的 yum 存储库? 不,它被配置为在没有任何变量的情况下运行,即我们所有的角色对yum-repo 角色的调用与meta/main.yml 中列出的内容完全相同。我尝试将allow_duplicates: false 附加到所有meta.yml 文件中,不幸的是这并没有改变任何东西。
    【解决方案4】:

    在运行剧本时使用寄存器变量

    类似

    • 名称:执行首次设置

      角色:abc

      注册:role_abc_var

      changed_when: "'abc Setup already executed' 不在 role_abc_var.stdout 中"

    详细解释见
    https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

    【讨论】:

      最近更新 更多