重用 Ansible 工件

您可以编写一个非常大的单个文件中包含简单 playbook,大多数用户首先学习这种单文件方法。但是,将您的自动化工作分解成更小的文件是组织复杂任务集并重复使用它们的绝佳方法。更小、更分散的工件使您可以重复使用多个 playbook 中的相同变量、任务和剧本以解决不同的用例。您可以在多个父 playbook 中或甚至在一个 playbook 中多次使用分布式工件。例如,您可能希望在几个不同的 playbook 中更新您的客户数据库。如果您将所有与更新数据库相关的任务放在一个 tasks 文件或一个角色中,则可以在许多 playbook 中重复使用它们,同时只需在一个地方维护它们。

创建可重用文件和角色

Ansible 提供四种分布式、可重用的工件:变量文件、任务文件、playbook 和角色。

  • 变量文件仅包含变量。

  • 任务文件仅包含任务。

  • playbook 至少包含一个剧本,并且可能包含变量、任务和其他内容。您可以重用重点明确的 playbook,但只能静态地重用它们,不能动态地重用。

  • 角色包含一组相关的任务、变量、默认值、处理器,甚至在定义的文件树中的模块或其他插件。与变量文件、任务文件或 playbook 不同,角色可以通过 Ansible Galaxy 轻松上传和共享。有关创建和使用角色的详细信息,请参阅角色

版本 2.4 中的新增功能。

重用 playbook

您可以将多个 playbook 整合到主 playbook 中。但是,您只能使用导入来重用 playbook。例如

- import_playbook: webservers.yml
- import_playbook: databases.yml

导入以静态方式将 playbook 整合到其他 playbook 中。Ansible 按列出的顺序运行每个导入的 playbook 中的剧本和任务,就像它们已在主 playbook 中直接定义一样。

您可以通过使用变量定义导入的 playbook 文件名,然后使用--extra-varsvars关键字传递变量来选择要在运行时导入哪个 playbook。例如

- import_playbook: "/path/to/{{ import_from_extra_var }}"
- import_playbook: "{{ import_from_vars }}"
  vars:
    import_from_vars: /path/to/one_playbook.yml

如果您使用ansible-playbook my_playbook -e import_from_extra_var=other_playbook.yml运行此 playbook,则 Ansible 会导入 one_playbook.yml 和 other_playbook.yml。

何时将 playbook 转换为角色

对于某些用例,简单的 playbook 可以很好地工作。但是,从一定的复杂程度开始,角色比 playbook 更有效。角色允许您将默认值、处理器、变量和任务存储在单独的目录中,而不是存储在一个长的文档中。角色易于在 Ansible Galaxy 上共享。对于复杂的用例,大多数用户发现角色比多合一 playbook 更易于阅读、理解和维护。

重用文件和角色

Ansible 提供两种在 playbook 中重用文件和角色的方法:动态和静态。

任务包含和导入语句可以在任意深度使用。

您仍然可以在剧本级别使用裸roles关键字以静态方式将角色合并到 playbook 中。但是,裸include关键字(曾经用于任务文件和 playbook 级别的包含)现在已弃用。

包含:动态重用

包含角色、任务或变量会动态地将它们添加到 playbook 中。Ansible 在 playbook 中遇到包含的文件和角色时处理它们,因此包含的任务可能会受到顶级 playbook 中较早任务的结果的影响。包含的角色和任务类似于处理器 - 它们可能运行也可能不运行,具体取决于顶级 playbook 中其他任务的结果。

使用include_*语句的主要优势是循环。当循环与 include 一起使用时,包含的任务或角色将为循环中的每个项目执行一次。

包含的角色、任务和变量的文件名在包含之前会被模板化。

您可以将变量传递到 include 中。有关变量继承和优先级的更多详细信息,请参阅变量优先级:我应该在哪里放置变量?

导入:静态重用

导入角色、任务或 playbook 会静态地将它们添加到 playbook 中。Ansible 在运行 playbook 中的任何任务之前预处理导入的文件和角色,因此导入的内容永远不会受到顶级 playbook 中其他任务的影响。

导入的角色和任务的文件名支持模板化,但当 Ansible 预处理导入时,必须可以使用变量。这可以通过vars关键字或使用--extra-vars来完成。

您可以将变量传递到导入中。如果您想在一个 playbook 中多次运行导入的文件,则必须传递变量。例如

tasks:
- import_tasks: wordpress.yml
  vars:
    wp_user: timmy

- import_tasks: wordpress.yml
  vars:
    wp_user: alice

- import_tasks: wordpress.yml
  vars:
    wp_user: bob

有关变量继承和优先级的更多详细信息,请参阅变量优先级:我应该在哪里放置变量?

比较包含和导入:动态和静态重用

每种重用分布式 Ansible 工件的方法都有优点和局限性。您可以为某些 playbook 选择动态重用,为其他 playbook 选择静态重用。尽管您可以在单个 playbook 中同时使用动态和静态重用,但最好为每个 playbook 选择一种方法。混合使用静态和动态重用可能会导致 playbook 中出现难以诊断的错误。此表总结了主要区别,以便您可以为创建的每个 playbook 选择最佳方法。

Include_*

Import_*

重用类型

动态

静态

何时处理

在运行时遇到时

在 playbook 解析期间预处理

任务或剧本

所有 include 都是任务

import_playbook不能是任务

任务选项

仅应用于 include 任务本身

应用于导入中的所有子任务

从循环中调用

为每个循环项执行一次

不能在循环中使用

使用--list-tags

include 中的标签未列出

所有标签都显示在--list-tags

使用--list-tasks

include 中的任务未列出

所有任务都显示在--list-tasks

通知处理器

无法触发 include 中的处理器

可以触发单个导入的处理器

使用--start-at-task

无法从 include 中的任务开始

可以从导入的任务开始

使用清单变量

可以include_*: {{ inventory_var }}

不能import_*: {{ inventory_var }}

使用 playbook

没有include_playbook

可以导入完整的 playbook

使用变量文件

可以包含变量文件

使用vars_files:导入变量

注意

  • 在资源消耗和性能方面也存在很大差异,导入非常精简和快速,而 include 需要大量管理和计算。

重用任务作为处理器

您也可以在 playbook 的 Handlers:运行更改操作 部分中使用 includes 和 imports。例如,如果您想定义如何重新启动 Apache,您只需为所有 playbook 执行一次即可。您可以创建一个类似于 restarts.yml 的文件

# restarts.yml
- name: Restart apache
  ansible.builtin.service:
    name: apache
    state: restarted

- name: Restart mysql
  ansible.builtin.service:
    name: mysql
    state: restarted

您可以从 import 或 include 触发 handlers,但每种重用方法的过程不同。如果您包含该文件,则必须通知 include 本身,这将触发 restarts.yml 中的所有任务。如果您导入该文件,则必须通知 restarts.yml 中的单个任务。您可以将直接任务和 handlers 与包含或导入的任务和 handlers 混合使用。

触发包含的(动态)handlers

Includes 在运行时执行,因此 include 的名称在 playbook 执行期间存在,但包含的任务在 include 本身被触发之前不存在。要使用 Restart apache 任务进行动态重用,请参考 include 本身的名字。这种方法会将包含文件中的所有任务都作为 handlers 触发。例如,使用上面显示的任务文件

- name: Trigger an included (dynamic) handler
  hosts: localhost
  handlers:
    - name: Restart services
      include_tasks: restarts.yml
  tasks:
    - command: "true"
      notify: Restart services

触发导入的(静态)handlers

Imports 在 playbook 开始之前进行处理,因此 import 的名称在 playbook 执行期间不再存在,但导入的单个任务的名称确实存在。要使用 Restart apache 任务进行静态重用,请参考导入文件内每个任务或任务的名称。例如,使用上面显示的任务文件

- name: Trigger an imported (static) handler
  hosts: localhost
  handlers:
    - name: Restart services
      import_tasks: restarts.yml
  tasks:
    - command: "true"
      notify: Restart apache
    - command: "true"
      notify: Restart mysql

另请参阅

实用程序模块

此处讨论的 include*import* 模块的文档。

使用 playbook

回顾基本的 Playbook 语言特性

使用变量

Playbook 中的所有变量

条件语句

Playbook 中的条件语句

循环

Playbook 中的循环

一般提示

Playbook 的提示和技巧

Galaxy 用户指南

如何在 Galaxy 上共享角色,角色管理

沟通

有问题?需要帮助?想分享你的想法?请访问 Ansible 沟通指南