标签

如果您有一个大型剧本,可能需要只运行剧本的特定部分,而不是运行整个剧本。您可以使用 Ansible 标签来实现。使用标签来执行或跳过选定的任务是一个两步过程

  1. 将标签添加到您的任务,可以单独添加,也可以从块、剧本、角色或导入中继承标签。

  2. 在运行剧本时选择或跳过标签。

注意

tags 关键字是剧本“预处理”的一部分,在决定哪些任务可供执行时具有很高的优先级。

使用 tags 关键字添加标签

您可以向单个任务或包含文件添加标签。您还可以通过在块、剧本、角色或导入文件级别定义标签来向多个任务添加标签。关键字 tags 解决了所有这些用例。 tags 关键字始终定义标签并将它们添加到任务;它不会选择或跳过要执行的任务。您只能在运行剧本时使用命令行根据标签选择或跳过任务。有关更多详细信息,请参见 在运行剧本时选择或跳过标签

向单个任务添加标签

在最简单的级别,您可以将一个或多个标签应用于单个任务。您可以在剧本、任务文件中或角色中向任务添加标签。这是一个使用不同标签标记两个任务的示例

tasks:
- name: Install the servers
  ansible.builtin.yum:
    name:
    - httpd
    - memcached
    state: present
  tags:
  - packages
  - webservers

- name: Configure the service
  ansible.builtin.template:
    src: templates/src.j2
    dest: /etc/foo.conf
  tags:
  - configuration

您可以将相同的标签应用于多个单个任务。此示例使用相同的标签“ntp”标记了几个任务

---
# file: roles/common/tasks/main.yml

- name: Install ntp
  ansible.builtin.yum:
    name: ntp
    state: present
  tags: ntp

- name: Configure ntp
  ansible.builtin.template:
    src: ntp.conf.j2
    dest: /etc/ntp.conf
  notify:
  - restart ntpd
  tags: ntp

- name: Enable and run ntpd
  ansible.builtin.service:
    name: ntpd
    state: started
    enabled: true
  tags: ntp

- name: Install NFS utils
  ansible.builtin.yum:
    name:
    - nfs-utils
    - nfs-util-lib
    state: present
  tags: filesharing

如果您使用 --tags ntp 在剧本中运行这四个任务,Ansible 将运行三个标记为 ntp 的任务,并跳过没有该标签的一个任务。

向处理程序添加标签

处理程序是任务的一种特殊情况,它们仅在收到通知时才会执行,因此它们会忽略所有标签,并且不能选择或反对它们。

向块添加标签

如果要将标签应用于剧本中的许多(但不是所有)任务,请使用一个 并在该级别定义标签。例如,我们可以编辑上面显示的 NTP 示例以使用块

# myrole/tasks/main.yml
- name: ntp tasks
  tags: ntp
  block:
  - name: Install ntp
    ansible.builtin.yum:
      name: ntp
      state: present

  - name: Configure ntp
    ansible.builtin.template:
      src: ntp.conf.j2
      dest: /etc/ntp.conf
    notify:
    - restart ntpd

  - name: Enable and run ntpd
    ansible.builtin.service:
      name: ntpd
      state: started
      enabled: true

- name: Install NFS utils
  ansible.builtin.yum:
    name:
    - nfs-utils
    - nfs-util-lib
    state: present
  tags: filesharing

请注意,tag 选择优先于大多数其他逻辑,包括 block 错误处理。在 block 中的任务上设置标签,但在 rescuealways 部分不设置标签,如果您的标签选择不涵盖这些部分中的任务,将阻止它们触发。

- block:
 - debug: msg=run with tag, but always fail
   failed_when: true
   tags: example

 rescue:
 - debug: msg=I always run because the block always fails, except if you select to only run 'example' tag

 always:
 - debug: msg=I always run, except if you select to only run 'example' tag

此示例在没有指定 --tags 的情况下调用时运行所有 3 个任务,但在使用 --tags example 运行时仅运行第一个任务。

向剧本添加标签

如果剧本中的所有任务都应该获得相同的标签,您可以在剧本级别添加标签。例如,如果您有一个只包含 NTP 任务的剧本,您可以标记整个剧本

- hosts: all
  tags: ntp
  tasks:
  - name: Install ntp
    ansible.builtin.yum:
      name: ntp
      state: present

  - name: Configure ntp
    ansible.builtin.template:
      src: ntp.conf.j2
      dest: /etc/ntp.conf
    notify:
    - restart ntpd

  - name: Enable and run ntpd
    ansible.builtin.service:
      name: ntpd
      state: started
      enabled: true

- hosts: fileservers
  tags: filesharing
  tasks:
  ...

注意

标记的任务将包括剧本的所有隐式任务(如事实收集),包括通过角色添加的任务。

向角色添加标签

有三种方法可以向角色添加标签

  1. 通过在 roles 下设置标签,将相同标签或标签添加到角色中的所有任务。请参见本节中的示例。

  2. 通过在剧本中静态 import_role 上设置标签,将相同标签或标签添加到角色中的所有任务。请参见 向导入文件添加标签 中的示例。

  3. 向角色本身的单个任务或块添加标签或标签。这是唯一允许您选择或跳过角色中某些任务的方法。要选择或跳过角色中的任务,您必须在单个任务或块上设置标签,在剧本中使用动态 include_role,并将相同标签或标签添加到包含文件。当您使用这种方法,然后使用 --tags foo 运行剧本时,Ansible 将运行包含文件本身以及角色中也具有标签 foo 的任何任务。有关详细信息,请参见 向包含文件添加标签

当您使用 roles 关键字在剧本中静态包含角色时,Ansible 会将您定义的任何标签添加到角色中的所有任务。例如

roles:
  - role: webserver
    vars:
      port: 5000
    tags: [ web, foo ]

---
- hosts: webservers
  roles:
    - role: foo
      tags:
        - bar
        - baz
    # using YAML shorthand, this is equivalent to:
    # - { role: foo, tags: ["bar", "baz"] }

注意

在角色级别添加标签时,不仅所有任务都被标记,而且角色的依赖项也会对其任务进行标记。有关详细信息,请参见标签继承部分。

向包含文件添加标签

您可以在剧本中向动态包含文件应用标签。与单个任务上的标签一样,include_* 任务上的标签仅应用于包含文件本身,而不应用于包含文件中或角色中的任何任务。如果向动态包含文件添加 mytag,然后使用 --tags mytag 运行该剧本,Ansible 将运行包含文件本身,运行包含文件中或角色中标记为 mytag 的任何任务,并跳过包含文件中或角色中没有该标签的任何任务。有关更多详细信息,请参见 选择性运行可重用文件中带有标签的任务

您向包含文件添加标签的方式与向任何其他任务添加标签的方式相同

---
# file: roles/common/tasks/main.yml

- name: Dynamic reuse of database tasks
  include_tasks: db.yml
  tags: db

您可以仅向角色的动态包含文件添加标签。在此示例中,foo 标签 不会应用于 bar 角色内部的任务

---
- hosts: webservers
  tasks:
    - name: Include the bar role
      include_role:
        name: bar
      tags:
        - foo

向导入文件添加标签

您还可以将标签或标签应用于由静态 import_roleimport_tasks 语句导入的所有任务

---
- hosts: webservers
  tasks:
    - name: Import the foo role
      import_role:
        name: foo
      tags:
        - bar
        - baz

    - name: Import tasks from foo.yml
      import_tasks: foo.yml
      tags: [ web, foo ]

包含文件的标签继承:块和 apply 关键字

默认情况下,Ansible 不会将 标签继承 应用于使用 include_roleinclude_tasks 进行的动态重用。如果向包含文件添加标签,它们仅应用于包含文件本身,而不应用于包含文件中或角色中的任何任务。这使您能够在运行剧本时执行角色或任务文件中的选定任务 - 请参见 选择性运行可重用文件中带有标签的任务

如果您想要标签继承,您可能需要使用导入。但是,在单个剧本中同时使用包含和导入会导致难以诊断的错误。因此,如果您的剧本使用 include_* 来重用角色或任务,并且您需要在某个包含中进行标签继承,Ansible 提供了两种解决方法。您可以使用 apply 关键字

- name: Apply the db tag to the include and to all tasks in db.yml
  include_tasks:
    file: db.yml
    # adds 'db' tag to tasks within db.yml
    apply:
      tags: db
  # adds 'db' tag to this 'include_tasks' itself
  tags: db

或者您可以使用一个块

- block:
   - name: Include tasks from db.yml
     include_tasks: db.yml
  tags: db

特殊标签

Ansible 为特殊行为保留了几个标签名称:alwaysnevertaggeduntaggedallalwaysnever 主要用于标记任务本身,另外三个用于选择要运行或跳过的标签。

始终和从不

Ansible 为特殊行为保留了几个标签名称,其中两个是 alwaysnever。如果您将 always 标签分配给任务或剧本,Ansible 将始终运行该任务或剧本,除非您明确跳过它(--skip-tags always)或该任务定义的另一个标签。

例如

tasks:
- name: Print a message
  ansible.builtin.debug:
    msg: "Always runs"
  tags:
  - always

- name: Print a message
  ansible.builtin.debug:
    msg: "runs when you use specify tag1, all(default) or tagged"
  tags:
  - tag1

- name: Print a message
  ansible.builtin.debug:
    msg: "always runs unless you explicitly skip, like if you use ``--skip-tags tag2``"
  tags:
     - always
     - tag2

警告

  • 默认情况下,内部事实收集任务被标记为 "always"。但是,如果您对剧本应用标签并直接跳过它(--skip-tags)或在使用 --tags 并省略它时间接跳过它,则可以跳过它。

警告

  • 默认情况下,角色参数规范验证任务被标记为 "always"。如果您使用 --skip-tags always,将跳过此验证。

版本 2.5 中的新增功能。

如果您将 never 标签分配给任务或剧本,Ansible 会跳过该任务或剧本,除非您明确请求它(--tags never)或为该任务定义的另一个标签。

例如

tasks:
  - name: Run the rarely-used debug task, either with ``--tags debug`` or ``--tags never``
    ansible.builtin.debug:
     msg: '{{ showmevar }}'
    tags: [ never, debug ]

上面示例中很少使用的调试任务仅在您明确请求 debugnever 标签时运行。

运行剧本时选择或跳过标签

将标签添加到任务、包含、块、剧本、角色和导入后,您可以在运行 ansible-playbook 时根据其标签选择性地执行或跳过任务。Ansible 运行或跳过所有与您在命令行传递的标签匹配的标签的任务。如果您在块或剧本级别添加了标签,使用 roles,或者使用导入,则该标签将应用于块、剧本、角色或导入角色或文件中的每个任务。如果您有一个具有多个标签的角色,并且您希望在不同的时间调用角色的子集,请使用动态包含,或将角色拆分为多个角色。

ansible-playbook 提供五个与标签相关的命令行选项

  • --tags all - 运行所有任务,包括已标记和未标记的任务,除非是 never(默认行为)。

  • --tags tag1,tag2 - 仅运行带有标签 tag1 或标签 tag2 的任务(以及标记为 always 的任务)。

  • --skip-tags tag3,tag4 - 运行所有任务,除了带有标签 tag3 或标签 tag4 或者 never 的任务。

  • --tags tagged - 仅运行至少具有一个标签的任务(never 覆盖)。

  • --tags untagged - 仅运行没有标签的任务(always 覆盖)。

例如,要在非常长的剧本中仅运行标记为 configurationpackages 的任务和块

ansible-playbook example.yml --tags "configuration,packages"

要运行除标记为 packages 的任务之外的所有任务

ansible-playbook example.yml --skip-tags "packages"

要运行所有任务,即使是由于标记为 never 而被排除的任务

ansible-playbook example.yml --tags "all,never"

运行带有 tag1 或 tag3 的任务,但跳过也带有 tag4 的任务

ansible-playbook example.yml --tags "tag1,tag3" --skip-tags "tag4"

标签优先级

跳过始终优先于显式标签,例如,如果您同时指定了 --tags--skip-tags,则后者优先。例如,--tags tag1,tag3,tag4 --skip-tags tag3 仅运行标记为 tag1 或 tag4 的任务,但不运行标记为 tag3 的任务,即使任务具有其他标签也是如此。

预览使用标签的结果

在运行角色或剧本时,您可能不知道或不记得哪些任务具有哪些标签,或者哪些标签存在。Ansible 为 ansible-playbook 提供两个命令行标志,可帮助您管理带标签的剧本

  • --list-tags - 生成可用标签的列表

  • --list-tasks - 与 --tags tagname--skip-tags tagname 一起使用时,生成已标记任务的预览

例如,如果您不知道剧本、角色或任务文件中配置任务的标签是 config 还是 conf,则可以在不运行任何任务的情况下显示所有可用标签

ansible-playbook example.yml --list-tags

如果您不知道哪些任务具有标签 configurationpackages,则可以传递这些标签并添加 --list-tasks。Ansible 会列出这些任务,但不会执行任何任务。

ansible-playbook example.yml --tags "configuration,packages" --list-tasks

这些命令行标志有一个限制:它们无法显示动态包含的文件或角色中的标签或任务。有关静态导入和动态包含之间差异的更多信息,请参见 比较包含和导入:动态和静态重用

在可重用文件中选择性地运行已标记任务

如果您有一个角色或任务文件,在任务或块级别定义了标签,则可以使用动态包含而不是静态导入,在剧本中选择性地运行或跳过这些已标记任务。您必须在包含的任务和包含语句本身中使用相同的标签。例如,您可以创建一个包含一些已标记和一些未标记任务的文件

# mixed.yml
tasks:
- name: Run the task with no tags
  ansible.builtin.debug:
    msg: this task has no tags

- name: Run the tagged task
  ansible.builtin.debug:
    msg: this task is tagged with mytag
  tags: mytag

- block:
  - name: Run the first block task with mytag
    ...
  - name: Run the second block task with mytag
    ...
  tags:
  - mytag

您可以在剧本中包含上面的任务文件

# myplaybook.yml
- hosts: all
  tasks:
  - name: Run tasks from mixed.yml
    include_tasks:
      name: mixed.yml
    tags: mytag

使用 ansible-playbook -i hosts myplaybook.yml --tags "mytag" 运行剧本时,Ansible 会跳过没有标签的任务,运行已标记的单个任务,以及运行块中的两个任务。此外,由于它被标记为 always,它还可以运行事实收集(隐式任务)。

标签继承:将标签添加到多个任务

如果您想将相同的标签或标签应用于多个任务,而不必在每个任务中添加 tags 行,则可以在剧本或块级别定义标签,或者在添加角色或导入文件时定义标签。Ansible 会将这些标签应用于依赖项链中的所有子任务。对于角色和导入,Ansible 会将 roles 部分或导入设置的标签附加到角色或导入文件中单个任务或块设置的任何标签。这称为标签继承。标签继承很方便,因为您不必标记每个任务。但是,这些标签仍然单独应用于这些任务。

对于剧本、块、role 关键字和静态导入,Ansible 会应用标签继承,将您定义的标签添加到剧本、块、角色或导入文件中每个任务中。但是,标签继承不会应用于使用 include_roleinclude_tasks 的动态重用。使用动态重用(包含),您定义的标签仅应用于包含本身。如果您需要标签继承,请使用静态导入。如果您无法使用导入,因为您的剧本的其余部分使用包含,请参阅 包含的标签继承:块和 apply 关键字,了解如何解决此行为。

您可以在剧本中向动态包含文件应用标签。与单个任务上的标签一样,include_* 任务上的标签仅应用于包含文件本身,而不应用于包含文件中或角色中的任何任务。如果向动态包含文件添加 mytag,然后使用 --tags mytag 运行该剧本,Ansible 将运行包含文件本身,运行包含文件中或角色中标记为 mytag 的任何任务,并跳过包含文件中或角色中没有该标签的任何任务。有关更多详细信息,请参见 选择性运行可重用文件中带有标签的任务

全局配置标签

如果您默认运行或跳过某些标签,则可以使用 Ansible 配置中的 TAGS_RUNTAGS_SKIP 选项来设置这些默认值。

另请参阅

Ansible 剧本

剧本简介

角色

按角色组织剧本

交流

有疑问?需要帮助?想分享您的想法?请访问 Ansible 交流指南