使用Ansible的include_tasks指令,结合子任务的标签进行操作。

Ansible 2.8.1 在我的playbook的tasks/目录中:
main.yml
dev.yml
main.yml中,我有一个类似这样的代码块:
- include_tasks: dev.yml
  when: ec2_tag_env == 'dev'

它运行得很好


然而,如果我尝试使用标签在dev.yml中调用特定任务,则在运行过程中不会限定该任务。

例如,这个标记的任务在dev.yml中:

- name: Pull the latest image
  docker_image:
    name: "{{ dev_image }}"
    source: pull
  tags:
    - container
当我使用-t container运行playbook时,它将不会被匹配,因为include_tasks步骤没有该标签。
将标签添加到include_tasks当然可以解决这个问题,但我还需要跟踪标签添加到子任务中,并在这里添加它们:
- include_tasks: dev.yml
  when: ec2_tag_env == 'dev'
  tags:
    - container

问题

  • 是否可能让Ansible自动识别include_tasks块中的任务并提取相应的标签?

  • 实现这个目标的最佳做法是什么?

我不愿意做的事情:

  • 把所有任务都放在main.yml中。我的playbook中有很多任务,我真的希望能够将它们组织成文件。
  • 手动为所有的include_tasks块及其子标签打上标签。听起来像是一个管理的噩梦。
3个回答

有点老问题了,但是对于其他可能因为想要或需要使用include_tasks而感到困惑的人来说,我建议使用import_tasks。对于那些可以同时使用两者的人,我也强烈推荐像之前回答过的那样使用import_tasks: 在官方Ansible手册中,开发人员建议在include_tasks本身上使用tags: always,同时使用apply:将其他标签应用于包含的任务。 看这个例子(从手册复制过来的):
- name: Apply tags to tasks within included file
  include_tasks:
    file: install.yml
    apply:
      tags:
        - install
  tags:
    - always
这种方式确保Ansible始终(除非使用--skip-tags always参数调用)包含外部任务,以便能够查看那些特定的标签。因此,如果install.yml中包含一个带有tags: download的任务,那么当使用--tags download(而不添加install)参数调用Ansible时,该任务将被执行。

Q: "Ansible能否自动识别include_tasks块中的任务,并提取适用的标签?" A: 在控制流到达include_task语句并包含文件后,包含的任务内容将会可用。请参考下面的示例。例如,这样的标签不会出现在可用标签列表中。请查看ansible-playbook的--list-tags选项。从这个角度来看,答案是否定的。但是,如果在include_task的级别上也指定了这些标签,那么在控制流到达include_task语句后,这些标签可能会可用。此外,特殊标签always可以使这些标签可用。 Q: "实现这个目标的最佳实践是什么?" A: 有两种选择: 要么使用import_tasks。这些导入在playbook启动时读取。 或者,使用特殊标签always。Ansible将始终包含来自文件的任务。
澄清一下差异。给定以下文件 shell> cat install.yml - debug: msg: 任务2 tags: t2 - debug: msg: 任务3 tags: t3 1. Playbook shell> cat pb1.yml - hosts: localhost tasks: - debug: msg: 任务1 tags: t1 - include_tasks: file: install.yml 按预期工作 shell> ansible-playbook pb1.yml PLAY [localhost] ***************************************************************************** TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务1 TASK [include_tasks] ************************************************************************* included: /export/scratch/tmp8/test-828/install.yml for localhost TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务2 TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务3 PLAY RECAP *********************************************************************************** localhost: ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 当使用标签“-t t1,t2”时,执行了标记为t1的任务,但未执行标记为t2的任务,因为文件未被包含 shell> ansible-playbook pb1.yml -t t1,t2 PLAY [localhost] ***************************************************************************** TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务1 PLAY RECAP *********************************************************************************** localhost: ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 请注意,启动时应用程序对包含文件中的标签一无所知 shell> ansible-playbook pb1.yml --list-tags playbook: pb1.yml play #1 (localhost): localhost TAGS: [] TASK TAGS: [t1] 2. 将任务“include_tasks”标记为“always” shell> cat pb2.yml - hosts: localhost tasks: - debug: msg: 任务1 tags: t1 - include_tasks: file: install.yml tags: always 启动时,应用程序仍然对包含文件中的标签一无所知,但任务将始终被包含 shell> ansible-playbook pb2.yml --list-tags playbook: pb1.yml play #1 (localhost): localhost TAGS: [] TASK TAGS: [always, t1] 现在使用标签“-t t1,t2”,同时执行标记为t1和t2的任务 shell> ansible-playbook pb2.yml -t t1,t2 PLAY [localhost] ***************************************************************************** TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务1 TASK [include_tasks] ************************************************************************* included: /export/scratch/tmp8/test-828/install.yml for localhost TASK [debug] ********************************************************************************* ok: [localhost] => msg: 任务2 PLAY RECAP *********************************************************************************** localhost: ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 3. 标签“always”导致当控制流达到“include_task”语句时,文件“install.yml”将始终被包含。但此标签仅适用于“include_task”。它不会被包含文件内的任务继承。如果要将标签应用于包含文件内的任务,请使用参数“apply”。例如 shell> cat pb3.yml - hosts: localhost tasks: - debug: msg: 任务1 tags: t1 - include_tasks: file: install.yml apply: tags: install tags: always 请注意,同样在启动时,应用程序对应用的标签和包含文件中的标签一无所知 shell> ansible-playbook pb3.yml --list-tags playbook: pb3.yml play #1 (localhost): localhost TAGS: [] TASK TAGS: [always, t1] 应用的标签唯一的区别是所有包含的任务都可以通过此标签触发,例如 shell> ansible-playbook pb3.yml -t install PLAY [localhost] ***************************************************************************** TASK [include_tasks] ************************************************************************* included: /export/scratch/tmp8/test-828/install.yml for localhost TASK [debug] ********************************************************************************* ok: [localhost] => msg

我是否正确理解了?也就是说,apply: 标签构造使得被包含的任务文件中的每个任务都表现得好像它们有应用的标签吗?在 install.yml 中的每个任务上添加 tags: 'install' 是否类似于将 'install' 标签应用于 include_task 上? - Jeter-work
1确切地说!这就是“apply: tags”的目的。它替代了include_tasks级别上缺失的标签继承。 - Vladimir Botka


1虽然这个链接可能回答了问题,但最好在这里包含答案的关键部分,并提供链接作为参考。仅有链接的答案如果链接页面发生变化,就会失效。- 来自审查 - Dave M