重用 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-vars
或 vars
关键字传递变量,来选择在运行时要导入哪个 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 中重用文件和角色的方法:动态和静态。
对于动态重用,在剧集的 tasks 部分添加一个
include_*
任务对于静态重用,在剧集的 tasks 部分添加一个
import_*
任务
任务 include 和 import 语句可以在任意深度使用。
您仍然可以在剧集级别使用裸 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 都是任务 |
|
任务选项 |
仅应用于 include 任务本身 |
应用于导入中的所有子任务 |
从循环中调用 |
为每个循环项目执行一次 |
不能在循环中使用 |
使用 |
include 中的标签未列出 |
所有标签都显示在 |
使用 |
include 中的任务未列出 |
所有任务都显示在 |
通知处理程序 |
无法触发 include 中的处理程序 |
可以触发单个导入的处理程序 |
使用 |
无法从 include 中的任务开始 |
可以从导入的任务开始 |
使用清单变量 |
可以 |
不能 |
使用 playbook |
没有 |
可以导入完整的 playbook |
使用变量文件 |
可以包含变量文件 |
使用 |
注意
在资源消耗和性能方面也存在很大差异,导入(imports)非常精简且快速,而包含(includes)则需要大量的管理和记账。
将任务重用为处理程序
您也可以在 playbook 的处理程序:在更改时运行操作部分使用包含和导入。例如,如果您想定义如何重启 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
您可以从导入或包含中触发处理程序,但每种重用方法的过程都不同。如果您包含该文件,则必须通知包含本身,这将触发 restarts.yml
中的所有任务。如果您导入该文件,则必须通知 restarts.yml
中的单个任务。您可以将直接任务和处理程序与包含或导入的任务和处理程序混合使用。
触发包含的(动态)处理程序
包含在运行时执行,因此包含的名称在 playbook 执行期间存在,但包含的任务直到包含本身被触发之前不存在。要使用 Restart apache
任务进行动态重用,请参考包含本身的名称。这种方法会将包含文件中所有任务作为处理程序触发。例如,使用上面显示的任务文件
- name: Trigger an included (dynamic) handler
hosts: localhost
handlers:
- name: Restart services
include_tasks: restarts.yml
tasks:
- command: "true"
notify: Restart services
触发导入的(静态)处理程序
导入在 playbook 开始之前进行处理,因此导入的名称在 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 沟通指南