Playbook

playbooks 是 Ansible 的配置,部署,编排语言。它们可以描述您希望远程系统执行的策略,或者 IT 流程中的一组步骤。

Ansible 模块是你的工作区的工具,playbooks 是你的介绍手册,库存中的主机是你的原始资料。

最基本的,Ansible 可以被用来管理配置,在远程机器上部署。 高级一点的,它们可以对涉及滚动更新的多层滚动进行排序,还可以将操作指派给其他主机,与监控服务器和负载平衡器进行交互。

虽然这里有很多信息,但是没有必要一次学习所有的东西。您可以从一小点开始,随着时间的推移获得更多需要的功能。

剧本被设计成容易读的,并且是用一种基本的文本语言开发的。 有多种方法来管理 playbook 和它们所包含的文件,我们将提供一些建议,以最大限度地使用 Ansible。

你应该看例子当你在阅读这些文档的时候。 这些例子将最佳实践以及许多不同的概念放在一起。

[TOC]

介绍 Playbook

关于 Playbooks

Playbooks 和 ad-hoc 命令模式是完全不同的,playbook 更加强大。

简单地说,playbook 是一个非常简单的配置管理和多机部署系统的基础,不像任何已经存在的系统,它非常适合部署复杂的应用程序。

playbook 可以声明配置,但它们也可以编排任何手动排序过程的步骤,即使不同的步骤必须在特定的机器之间来回切换。它们可以同步或异步地启动任务。

虽然你可以使用ansible运行 ad-hoc 任务,但 playbook 更适合保存在源代码中,用于更新您的配置或确保远程系统的配置符合规范。

Playbook 例子

Playbook 使用 YAML 语法,它不是一种编程语言或脚本,而是配置或流程的模型。

每个 playbook 由一个或多个 play 组成。

通过编写包含多个 plays 的 playbook,可以编排多机部署, 在 webservers 组中的所有计算机上运行某些步骤,然后在 dbserver 组中运行某些步骤,然后在 webservers 组中返回更多命令,等等。

plays 类似运动。你可以有很多 plays 来影响你的系统,并去做很多事情。 你只是定义了一个特定的状态或模型,你可以在不同的时间运行不同的 plays。

这里有一个包含一个 play 的 playbooks:

包含多个 plays 的 playbooks,你可能有一个 playbook,它的目标是 web servers,然后是 database servers:

您可以使用此方法在目标主机组、登录到远程服务器的用户名、是否使用 sudo 等之间进行切换。 和任务一样,play 也是按照 playbook 中从上到下的顺序运行。

基础

主机和用户

对于每个 playbook,你可以选择目标机器和远程用户。

host行可以是主机或组或匹配的主机,由冒号分割。remote_user:是用户的账户:

远程用户也可以在每个任务指定:

使用另一个用户运行也是可以的:

你可以使用become关键词在任务中指定:

也可以设置成为其他用户:

使用其他提权方式:

如果您需要为 sudo 指定一个密码,运行 ansible-playbook, 使用—ask-become-pass或使用旧的 sudo 语法–ask-sudo-pass (-K)。 如果您运行了一个成为 playbook,但 playbook 似乎挂起,它可能卡在提权提示的步骤。 只需Control-C杀死它,然后再运行一次,并输入密码。

注意:当对 root 用户以外的用户使用become_use时,模块参数被写入 /tmp 中的随机 tempfile 中。 这些在命令执行后立即删除。 这只发生在将用户的权限从bob更改为timmy时,而不是从bob更改为root或直接以bobroot登录时。 如果您担心这些数据是可读的(而不是可写的),请避免使用 become_user 设置来传输未加密的密码。 在其他情况下,不使用 /tmp,Ansible 也不记录密码。

您还可以控制主机的运行顺序。默认是库存提供的顺序:

可以提供排序的值:

  • inventory:默认项。库存文件内提供的顺序。

  • reverse_inventory:库存文件内提供的顺序相反。

  • sorted:名字按照字母排序。

  • reverse_sorted

  • shuffle:随机

任务列表

每个 playbook 都包含一个任务列表。 在转移到下一个任务之前,任务是按顺序执行的,一次一个任务,对所有与主机模式匹配的机器执行。 在一个剧本中,所有的主机都将获得相同的任务指令。play 的目的是让主机执行任务。

从上到下运行 playbook 时,如果一个任务失败,则将退出整个 playbook 执行。 如果执行失败了,只需修改 playbook 文件并重新运行。

每个任务的目标是执行一个具有参数的模块。如上所述,变量可以用于模块的参数。

模块应该是幂等的,也就是说,按顺序运行一个模块多次应具有与仅运行一次相同的效果。 实现幂等的一种方法是让模块检查是否已达到其所需的最终状态,如果已经达到该状态,则不执行任何操作即可退出。 如果剧本使用的所有模块都是幂等的,则剧本本身很可能是幂等的,因此重新运行剧本应该是安全的。

commandshell模块通常会再次重新运行同一命令,如果该命令是诸如chmodsetsebool等,总的来说可以。 尽管有一个create标志可用于使这些模块也成为幂等。

每个任务都应有一个name,该名称包含在运行 playbook 的输出中。 这是人类可读的输出,因此提供每个任务步骤的良好描述很有用。 如果未提供名称,则输入到action的字符串将用于输出。

可以使用传统动作:action: module options,但是建议您使用更传统的模块:action: options。 这种推荐的格式在整个文档中都有使用,但是您可能会在一些剧本中遇到旧的格式。

最基础的任务是像这样的。正如大部分模块,service模块使用key=value参数:

commandshell模块只需要参数列表,而不需要key=value格式。

commandshell关注返回码,假如你有一个命令希望成功的返回码不是 0, 可以这样:

或者:

如果动作的行太长,你可以用空格和缩进换行:

在动作行中可以使用变量。例如在vars部分中有vhost变量:

这些相同的变量也可以在模板中使用。

动作简写

Ansible 跟喜欢这种格式:

Handler:在变更后执行

正如我们已经提到的,模块应该是幂等的,并且在远程系统上更改后可以继续。 playbook 认识到这一点,并具有可用于响应变化的基本事件系统。

这些notify动作在任务的末尾触发,即使通知了多次,也只触发一次。

例如,多个操作以为配置变更而指定 Apache 需要重启,但是 Apache 只会重启一次,避免不必要的重启。

这里有一个例子,在一个文件内容变更后需要重启两个服务:

notify处的任务被称为 handlers。

Handlers 是任务的列表,和常规任务没有什么区别,这里引用全局唯一名字,并由通知程序通知。 假如 handler 没有被通知,它就不会运行。 不管有多少任务通知 handler,在一个 play 中的所有任务完成之后,它都只运行一次

从 Ansible 2.2 开始,handler 还可以监听通用任务,任务可以像下面这样通知 handler:

这样可以容易的触发多个 handler。它也将 handler 和它的名字解耦,使它更容易的在整个 playbook 和角色中共享。

注意:

  • Notify handler 总是按照定义它们的顺序运行,

    而不是按照 Notify -statement 中列出的顺序。使用 listen 的 handler 也是如此。

  • handler 名字和 listen 名字保存在全局命名空间中。

  • 假如两个 handler 名字相同,只有一个运行。

  • 不能通知在 include 中定义的 handler。

角色将在之后讲,但是值得指出的是:

  • 在每个pre_taskstaskspost_tasks末尾部分,handler 通知将会自动刷新。

  • roles部分中通知的 handler 将在任务末尾自动刷新,但在所有 handler 之前。

假如你希望马上处理所有 handler:

在上面的例子中,当到达meta语句时,任何排队的 handler 都会被提前处理。

执行 playbook

使用 10 个并行进程:

提示和技巧

使用--syntax-check检查语法。使用--verbose展示详细的输出。

创建可重用的 playbooks

虽然可以将 playbook 编写成一个大文件,但最终您需要重用文件部分的内容。 在 Ansible,有三种方法可以做到这一点:includes,imports,roles。

Include 和 import 允许将一个大文件切分成小文件,小文件可以跨多个父 Playbook 使用,甚至可以在同一个 Playbook 中多次使用。

角色不仅允许将任务打包在一起,还可以包含变量、handler、甚至模块和其他插件。

动态和静态

Ansible 有两种方式操作可重用内容:dynamic and static。

在 Ansible 2.0 中,引入了动态包含的概念。 由于这种方式动态 include 存在一些限制,因此 Ansible 2.1 中引入了强制 include静态的能力。 由于 include 任务可以包含静态和动态语法,并且 include 的默认行为可能会根据 Task 上设置的其他选项而改变, 因此 Ansible 2.4 引入了 include vs import 的概念。

如果您使用任何import*任务(import_playbookimport_tasks等),它是静态的。 如果您使用任何include*任务(include_tasksinclude_role等),它是动态的。

include现在也是可用的,但是将被弃用。

动态和静态的区别

两种操作模式非常简单:

  • 在 playbook 解析时,Ansible 预处理所有静态导入(static imports)

  • 动态包含(dynamic include)是在运行时遇到任务时处理的

当 Ansible 任务遇到tagswhen选项时:

  • 对于静态 import,父任务的选项将复制到子任务

  • 对于动态 include,任务选项只在评估动态任务时适用,并且不会拷贝到子任务

注意:角色是比较特殊的情况。 在 Ansible 2.3 之前,角色总是通过特殊角色静态地包括:一个给定的 play 选项,总是在任何其他 play 任务之前执行(除非使用 pre_tasks)。 角色仍然可以这样使用,但是,Ansible 2.3 引入了 include_role 选项,允许角色与其他任务内联执行。

include 和 import 之间的折中和陷阱

使用include*import*有一些优点,也有一些折衷,用户在选择使用它们时应该加以考虑:

使用include*语句的主要优点在循环。 当循环与include一起使用时,include 的任务或角色将对循环中的每个项执行一次。

使用 include 相比较 import 有一些限制:

  • 只存在于动态 include 中的标记不会出现在—list-tags输出中。

  • 只存在于动态 include 中的任务不会出现在—list-tasks输出中。

  • 当来自于动态 include,不能使用notify触发 handler。

  • 不能使用——start-at-task在动态 include 中开始执行任务。

使用 import 相比较 include 有一些限制:

  • 循环不能使用 import

  • 将变量用作目标文件或角色名称时,无法使用清单资源(主机/组变量等)中的变量。

注意:动态任务使用notify仍然可以触发动态 include 本身,这将导致运行 include 中的所有任务。

变量

自动化的存在使事情更容易重复,但所有系统不一定相同,有的配置可能和其他的不同。 在一些情况下,系统的行为或状态可能影响到配置其他系统。 例如,你可能需要查找系统的 IP,然后把它作为值配置在另一个系统。

Ansible 使用变量处理系统间的不同。

为了理解变量,你需要阅读条件循环。 在管理不同系统之间,group_bywhen也可以和变量一起使用。

命名

变量以字母开始,后续为字母、数字、下划线组成。

foo_portfoo5是正确的命名。

foo-portfoo barfoo.port12都是错误的命名。

YAML 也支持字典:

你可以引用指定的字典字段,通过[].

关键字:

add, append, as_integer_ratio, bit_length, capitalize, center, clear, conjugate, copy, count, decode, denominator, difference, difference_update, discard, encode, endswith, expandtabs, extend, find, format, fromhex, fromkeys, get, has_key, hex, imag, index, insert, intersection, intersection_update, isalnum, isalpha, isdecimal, isdigit, isdisjoint, is_integer, islower, isnumeric, isspace, issubset, issuperset, istitle, isupper, items, iteritems, iterkeys, itervalues, join, keys, ljust, lower, lstrip, numerator, partition, pop, popitem, real, remove, replace, reverse, rfind, rindex, rjust, rpartition, rsplit, rstrip, setdefault, sort, split, splitlines, startswith, strip, swapcase, symmetric_difference, symmetric_difference_update, title, translate, union, update, upper, values, viewitems, viewkeys, viewvalues, zfill.

在库存中定义变量

Working with Inventory

在 playbook 中定义变量

它是非常好的在阅读 playbook 的时候。

Jinja2 使用变量

一旦你定义了变量,就可以在 Jinja2 中使用:

这个提供了最简单的变量替换。

你可以在 playbook 使用相同的语法:

这里定义了文件的路径,但是不同系统之间可能不同。

在模板中,您可以访问主机范围内的所有变量。 实际上,你还可以读取其他主机的变量。我们稍后将展示如何做到这一点。

注意

YAML 要求{{ foo }}开始的值需要使用“”包裹。

不正确:

正确:

发现系统变量

Facts 是远程系统的信息。 你可以发现完整的值通过ansible_facts变量,大部分 facts 保存在以ansible_为前缀的变量中,还有一些因为冲突被丢弃。 可以通过INJECT_FACTS_AS_VARS设置。

一个例子是发现远程机器的 IP 或系统。

为了看ansible_facts的值,可以:

获取原始信息:

将返回以下信息:

第一块硬盘的 model:

主机名:

Facts 经常在条件(conditionals)语句和模板(templates)中用到。

Facts 还可以创建符合特定条件的动态主机组, 看ConditionalsImporting Modules

关闭 facts

本地 facts

假如远程机器有/etc/ansible/facts.d文件夹,文件夹内有 Json、INI 等格式的以.fact结尾的文件, 或者返回 JSON 的可执行文件,它们就是本地 facts。 也可以通过 fact_path指定文件夹路径。

例如,/etc/ansible/facts.d/preferences.fact包含:

则会生成名为general,成员为asdfbar的变量:

你将看到:

template/playbook中使用:

本地命名空间可以防止任何用户提供的 fact 覆盖在 playbook 中定义的系统 fact 或变量。

注意:ansible_localkey都将被转化为小写, 例如XYZ=3,则将是{{ ansible_local['preferences']['general']['xyz'] }}

假如拷贝了一份 fact 到远程主机,如果需要使用,则必须显性再调用setup,或者等下次 play。

Ansible 版本

facts 缓存

一个服务器可以调用连一个服务器的变量:

在禁用 facts 缓存的情况下, 为了做到这一点,Ansible 必须在当前剧本中与asdf.example.com进行了对话,或者在之前 play 中进行了对话。

为了避免这样,Ansible 1.8 允许两个 playbook 之间保存 facts,这个特性需要手动开启。

在拥有数千台主机的大型基础设施中,可以将 facts 缓存配置为每晚运行。 一小组服务器的配置可以临时运行,也可以在一天中定期运行。 启用了 facts 缓存后,就不需要访问所有服务器来引用变量和有关变量的信息。

Ansible 支持redisjsonfile缓存插件。

配置redis缓存插件,在ansible.cfg

现在不支持redis 的 port 和 password 配置

jsonfile:

注册变量

变量的另一个主要用途是运行命令并将该命令的结果注册为变量。

任务的值将被保存为变量,并在之后使用。

当在循环中注册变量,每次的结果都会保存在result属性列表中

注意:当任务跳过或失败,变量任然注册为失败或跳过。只有使用 tag 的条件下,可以避免注册变量。

访问复杂的变量

得到 IP 地址:

或者:

访问其他主机的信息

不管您是否定义了任何变量,您都可以使用 Ansible 提供的特殊变量来访问有关主机的信息, 包括变量、facts和连接变量。不要使用这些名称设置变量。 变量environment也被保留。

hostvars:访问另一个主机的变量,包括 facts。

groups:库存中组或主机的列表。

经常使用到的,看主机的 IP:

group_names:所有的组。

inventory_hostname是在 Ansible 的 inventory 主机文件中配置的主机名。 当您禁用了 facts 收集,或者您不希望依赖于所发现的主机名ansible_hostname时,这可能会很有用。 如果您有一个长 FQDN,您可以使用inventory_hostname_short,它包含第一个周期之前的部分,而不包含域的其余部分。

其他魔法变量:ansible_play_hostsansible_play_batch,ansible_playbook_python, inventory_dir,playbook_dir, role_path, ansible_check_mode

文件中定义变量

使用额外的变量文件:

消除了共享时敏感数据的泄漏问题。

变量文件的格式:

命令行解析变量

除了vars_promptvars_files,还可以通过 --extra-vars设置变量:

JSON 格式:

YAML 格式:

YAML 或 JSON 文件:

确保您对标记(例如 JSON)和正在操作的 shell 都进行了适当的转义。

在这些情况下,最好使用包含变量定义的 JSON 或 YAML 文件。

变量优先级

下面是优先级从最小到最大的顺序:

  • command line values (eg “-u user”)

  • role defaults [1]

  • inventory file or script group vars [2]

  • inventory group_vars/all [3]

  • playbook group_vars/all [3]

  • inventory group_vars/* [3]

  • playbook group_vars/* [3]

  • inventory file or script host vars [2]

  • inventory host_vars/* [3]

  • playbook host_vars/* [3]

  • host facts / cached set_facts [4]

  • play vars

  • play vars_prompt

  • play vars_files

  • role vars (defined in role/vars/main.yml)

  • block vars (only for tasks in block)

  • task vars (only for the task)

  • include_vars

  • set_facts / registered vars

  • role (and include_role) params

  • include params

  • extra vars (always win precedence)

基本上,任何涉及“角色 default”(角色内的 default 文件夹)的东西都是很容易被覆盖的。 角色的 vars 目录中的所有内容都会覆盖命名空间中该变量的先前版本。 这里要遵循的想法是,范围越明确,在命令行中的优先级就越高,-e总是比额外的 var 优先。 主机变量或清单变量可以覆盖角色 default 值,但不能像 vars 目录或 include_vars 任务那样显式 incude。

[1] 每个角色的任务都会看到自己角色的 default。在角色外部定义的任务将看到最后一个角色的 default。

[2] (1,2)库存文件中定义或动态库存提供的变量。

[3] (1,2,3,4,5,6)包括 vars 插件添加的 vars,以及 host_vars 和 group_vars, 这些都是由 Ansible 自带的 vars 插件添加的。

[4]使用 set_facts 的可缓存选项创建时,变量在 play 中具有较高的优先级,但是当它们来自缓存时,它们的优先级与主机 facts 相同。

注意:在任何部分中,重新定义 var 将覆盖前面的值。如果多个组具有相同的变量,则最后加载的组获胜。 如果在一个 play,定义一个变量两次,则第二个变量获胜。

一个重要的事情是连接变量覆盖配置,命令行,play,角色,任务指定的选项和关键词。 例如,假如你库存指定ansible_ssh_user: ramon,然后运行:

这将会继续使用 ramon连接,因为来自变量的值具有优先权(在这种情况下,变量来自库存,但是无论在何处定义变量都一样)。

对于reote_user也是一样:

将会使用remote_user覆盖ansible_ssh_user

这样做是为了使特定主机的设置可以覆盖常规设置。 这些变量通常是按库存中的主机或组定义的,但它们的行为与其他变量类似。

假如你希望覆盖全局,请使用:

lola值仍然被忽略,但是ansible_user = maria优先于设置ansible_user(或ansible_ssh_userremote_user)的所有位置。

你也可以在 play 中使用普通变量覆盖:

变量范围

  • global:配置,环境,和命令行

  • play:play 和包含的结构,vars(vars_files,vars_prompt),角色的 default 和 vars

  • host:库存,include_vars,facts,注册变量

条件

When 语句

一些时候,你可能想一部分主机跳过某些步骤。 例如,如果操作系统是一个特定的版本,就不安装某个包,或者如果文件系统已经满了,就执行一些清理步骤。

这在 Ansible 中很容易做到,因为它包含一个没有双花括号的原始 Jinja2 表达式:

你也可以使用()分组:

多个条件都要满足,可以使用列表:

许多 Jinja2 测试和过滤器也可以用于 when 语句,其中一些由 Ansible 提供。 假设我们想要忽略一个语句的错误,然后决定根据成功或失败有条件地做一些事情:

要查看特定系统上有哪些 facts 可用,可以在 playbook 中执行以下操作:

提示: 有时你会得到一个字符串变量,你需要对它做一个数学运算比较。你可以这样做:

也可以基于变量的值:

假如要求变量没有被设置:

如示例所示,您不需要使用{{}}来包含条件中的变量,因为这些已隐含。

循环与条件

when和循环(loop)组合,when语句会处理循环的每一个元素。

如果需要根据定义的循环变量跳过整个任务,可以使用|default()过滤器提供一个空迭代器:

循环字典:

在角色,导入,包括中使用 when

请注意,如果您有多个任务都共享同一个条件语句,则可以将该条件附加到include_tasks语句, 如下所示。所有的任务都会被计算,每个任务都应用了条件:

或者:

当条件句与include_*一起使用,而不是与import一起使用时,它仅应用于include任务本身, 而不应用于include文件中的任何其他任务:

使用 include

假如x未定义,debug任务将会跳过。使用inlude_tasks代替inport_tasks,两个任务都会执行。

有条件导入

根据不同标准,做一些不同的事情:

变量 YAML 只包含键值:

基于变量选择文件和模板

注册变量

register关键字可以保存执行的结果。之后可以在模板、commandwhen语句中使用。

如果注册的结果被转换为列表(或者已经是列表),则可以在任务的循环中使用:

注册的变量是字符串内容。可以检查变量字符串内容是否为空:

循环

标准循环

和这个相等:

yumapt直接添加列表到name中,比使用循环更好:

遍历 hash 列表:

遍历 字典:

在这里,我们不想设置空标签,所以我们创建了一个只包含非空标签的字典。

复杂的循环

使用 Jinja2 表达式生成复杂的列表:

注意:with_循环实际是with_+ lookup()组合。

在循环使用 lookup 或 query

query提供了更简单的接口和比lookup插件的更可预测的输出,从而确保了更好的与循环的兼容性。

以下调用是等效的,使用带有查找的wantlist=True来确保列表的返回类型:

Do-until 循环

直到某个条件退出循环:

如果until参数未定义,则retries参数的值将强制为 1。

在循环中使用 register

运行的结果将包含在 register中的results列表中:

这与不使用循环的 register 时返回的数据结构不同:

在注册变量上进行后续循环以检查结果:

在迭代期间,将当前项的结果放在变量中:

循环 inventory

循环控制

在 Ansible 2.2(多了 pasue):

在 Ansible 2.5 可以这样(多了 index_var):

从 with_* 到 loop

with_list

with_items

with_indexed_items

with_flattened

with_together

with_dict

with_sequence

with_subelements

with_nested/with_cartesian

with_random_choice

块(blocks)

逻辑分组和错误处理。

在上面的例子中,这 3 个任务都是在when条件之后执行的。它们还继承了特权升级指令,使become能够包含所有任务。

错误处理

这将revert运行任务的失败状态,并且 play 就像成功一样继续。

always无论如何都会运行:

包含所有的:

运行 handlers 之后的错误救援:

Ansible 为 rescue提供的变量:

  • ansible_failed_task:捕获的触发救援的失败任务

  • ansible_failed_result: 捕获的触发救援的失败任务的返回结果

异步和轮询

为了避免阻塞或 SSH 超时问题,可以使用异步模式一次运行所有任务,然后轮询,直到完成为止。

若要异步启动任务,请指定其最大运行时以及轮询状态的频率。如果不为轮询指定值,则默认轮询值为 10 秒。

如果不需要等待任务完成,可以指定一个轮询值 0 来异步运行任务:

如果希望异步执行某个任务,并在稍后进行检查:

注意: 如果async:的值不够高,这将导致稍后的任务检查失败,因为async status:正在寻找的临时状态文件将不会被写入或不存在

运行多个异步任务,同时限制并发运行的任务数量:

滚动更新数量

默认情况下,Ansible 会尝试并行地管理一个 playbook 中引用的所有机器。 对于滚动更新用例,可以使用serial关键字定义 Ansible 在同一时间应该管理多少台主机:

输出:

serial 也可以使用百分数,列表([1,3,5])或混合使用:

最大失败百分数

默认情况下,只要批处理中有尚未失败的主机,Ansible 就会继续执行。当达到一定的故障阈值时,可能希望中止 play:

如果组中的 10 台服务器中有 3 台以上(必须超过 30%)发生故障,则将终止其余的操作。

指派

简写:

如果需要其余参数:

指派 facts

将收集 facts 的工作指派给其他主机:

注意:使用 hostvars[‘dbhost1’][‘default_ipv4’][‘address’]等获取 facts。

Run Once

和指派一起用:

本地 Playbooks

自己运行 playbook:

或:

错误后中断执行

使用any_errors_fatal选项,多主机 play 中任何主机上的任何失败都将被视为致命的,Ansible 将立即退出,而无需等待其他主机。

错误处理

忽略错误

重置不可达主机

连接失败被设置为 unreachable,通过meta: clear_host_errors重置。

Handlers 错误

如过任务运行失败,但是之前任务触发的的 handlers 未运行,可能会导致配置修改却未加载等等的错误。

设置force_handlers: True--force-handlers,即使任务失败,Handlers 也会执行。

定义错误

或:

覆盖 Result

终止 play

any_errors_fatal选项将标记为所有主机失败,如果任何一个 play 失败,将立即中止:

提示

设置默认值:

隐藏输入:

标签(tags)

使用标签:

跳过标签:

标签重用

标签继承

添加tags:, 将这些标签添加到 playbook 或静态导入的任务和角色中。 这称为标记继承。标记继承不适用于include_roleinclude_tasks等动态include

标记了两个剧本中的所有任务。第一个 play 的所有任务都用 bar 标记,第二个 play 的所有任务都用 foo 标记。

roles中:

添加 import_roleimport_tasks语句:

特殊标记

always始终运行,除非指明跳过(--skip-tags always):

neveralways相反:

其他:tagged, untagged, all

关键词

查找Keywords

模块默认值

如果发现自己使用相同的参数重复调用相同的模块,则使用module_defaults属性为该特定模块定义默认参数:

最佳实践

目录布局

备用布局

最佳实践

Working With Playbooks

Last updated

Was this helpful?