Working With Playbooks--Intro to Playbooks
Intro to Playbooks
Playbooks简介
About Playbooks
关于剧本
Playbooks are a completely different way to use ansible than in adhoc task execution mode, and are particularly powerful.
与adhoc任务执行模式相比,Playbooks使用ansible是一种完全不同的方式,并且功能特别强大。
Simply put, playbooks are the basis for a really simple configuration management and multi-machine deployment system, unlike any that already exist, and one that is very well suited to deploying complex applications.
简而言之,playbooks是真正简单的配置管理和多机器部署系统的基础,与已有的系统不同,并且非常适合部署复杂的应用程序。
Playbooks can declare configurations, but they can also orchestrate steps of any manual ordered process, even as different steps must bounce back and forth between sets of machines in particular orders. They can launch tasks synchronously or asynchronously.
Playbooks可以声明配置,但它们也可以协调任何手动订购流程的步骤,即使不同的步骤必须在特定订单的机器组之间来回跳转。他们可以同步或异步启动任务。
While you might run the main /usr/bin/ansible
program for ad-hoc tasks, playbooks are more likely to be kept in source control and used to push out your configuration or assure the configurations of your remote systems are in spec.
虽然您可以运行/usr/bin/ansible
主程序来执行临时任务,但是更有可能将源代码保留在源代码管理中并用于推出配置或确保远程系统的配置符合规范。
There are also some full sets of playbooks illustrating a lot of these techniques in the ansible-examples repository. We’d recommend looking at these in another tab as you go along.
在ansible-examples存储库中还有一些完整的手册说明了很多这些技术 。我们建议您在另一个标签中查看这些内容。
There are also many jumping off points after you learn playbooks, so hop back to the documentation index after you’re done with this section.
在学习了剧本后,还有许多跳跃点,所以在完成本节后,请跳回文档索引。
Playbook Language Example
Playbook语言示例
Playbooks are expressed in YAML format (see YAML Syntax) and have a minimum of syntax, which intentionally tries to not be a programming language or script, but rather a model of a configuration or a process.
Playbooks以YAML格式表示(请参阅YAML语法),并且具有最少的语法,有意尝试不是编程语言或脚本,而是配置或进程的模型。
Each playbook is composed of one or more ‘plays’ in a list.
每个剧本由列表中的一个或多个“剧本”组成。
The goal of a play is to map a group of hosts to some well defined roles, represented by things ansible calls tasks. At a basic level, a task is nothing more than a call to an ansible module (see Working With Modules).
游戏的目标是将一组主机映射到一些定义明确的角色,由ansible调用任务表示。在基本级别,任务只不过是对ansible模块的调用(请参阅使用模块)。
By composing a playbook of multiple ‘plays’, it is possible to orchestrate multi-machine deployments, running certain steps on all machines in the webservers group, then certain steps on the database server group, then more commands back on the webservers group, etc.
通过编写多个“播放”的剧本,可以编排多机部署,在Web服务器组中的所有计算机上运行某些步骤,然后在数据库服务器组上执行某些步骤,然后在Web服务器组上执行更多命令,等等。
“plays” are more or less a sports analogy. You can have quite a lot of plays that affect your systems to do different things. It’s not as if you were just defining one particular state or model, and you can run different plays at different times.
“戏剧”或多或少是体育比喻。你可以有很多戏剧影响你的系统做不同的事情。这并不是说你只是定义了一个特定的状态或模型,而是可以在不同的时间运行不同的plays。
For starters, here’s a playbook that contains just one play:
对于初学者来说,这是一个只包含一个游戏的剧本:
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version 确保apache是最新版本
yum:
name: httpd
state: latest
- name: write the apache config file 写apache是最新版本
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running 确保apache正在进行
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted
Playbooks can contain multiple plays. You may have a playbook that targets first the web servers, and then the database servers. For example:
Playbooks可以包含多个plays。您可能有一个首先针对Web服务器,然后是数据库服务器的手册。例如:
---
- hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version 确保apache是最新版本
yum:
name: httpd
state: latest
- name: write the apache config file 编写apache配置文件
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
- hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version 确保postgresql是最新版本
yum:
name: postgresql
state: latest
- name: ensure that postgresql is started 确保postgresql启动
service:
name: postgresql
state: started
You can use this method to switch between the host group you’re targeting, the username logging into the remote servers, whether to sudo or not, and so forth. Plays, like tasks, run in the order specified in the playbook: top to bottom.
您可以使用此方法在您要定位的主机组,登录到远程服务器的用户名,是否为sudo等之间切换。与任务一样,播放按照剧本中指定的顺序运行:从上到下。
Below, we’ll break down what the various features of the playbook language are.
下面,我们将分解playbook语言的各种功能。
Basics
基础知识
Hosts and Users
主机列表和用户
For each play in a playbook, you get to choose which machines in your infrastructure to target and what remote user to complete the steps (called tasks) as.
对于剧本中的每个游戏,您可以选择基础架构中的哪些计算机作为目标,以及用什么远程用户完成步骤(称为任务)。
The hosts
line is a list of one or more groups or host patterns, separated by colons, as described in the Working with Patterns documentation. The remote_user
is just the name of the user account:
该hosts
行是一个由冒号分隔的一个或多个组或主机模式的列表,如使用模式 文档中所述。这remote_user
只是用户帐户的名称:
---
- hosts: webservers
remote_user: root
The remote_user
parameter was formerly called just user
. It was renamed in Ansible 1.4 to make it more distinguishable from the user module (used to create users on remote systems).
该remote_user
参数以前只称为user
。它在Ansible 1.4中重命名,使其与用户模块(用于在远程系统上创建用户)更加区分。
Note 注意
The remote_user parameter was formerly called just user. It was renamed in Ansible 1.4 to make it more distinguishable from the user module (used to create users on remote systems).
该remote_user参数以前只称为user。它在Ansible 1.4中重命名,使其与用户模块(用于在远程系统上创建用户)更加区分。
Remote users can also be defined per task:
每个任务也可以定义远程用户:
---
- hosts: webservers
remote_user: root
tasks:
- name: test connection
ping:
remote_user: yourname
Support for running things as another user is also available (see Understanding Privilege Escalation):
还可以支持以另一个用户身份运行(请参阅了解权限提升):
---
- hosts: webservers
remote_user: yourname
become: yes
You can also use become on a particular task instead of the whole play:
您还可以使用成为特定任务而不是整个游戏:
---
- hosts: webservers
remote_user: yourname
tasks:
- service:
name: nginx
state: started
become: yes
become_method: sudo
You can also login as you, and then become a user different than root:
您也可以像您一样登录,然后成为与root不同的用户:
---
- hosts: webservers
remote_user: yourname
become: yes
become_user: postgres
You can also use other privilege escalation methods, like su:
您还可以使用其他权限提升方法,例如su:
---
- hosts: webservers
remote_user: yourname
become: yes
become_method: su
If you need to specify a password to sudo, run ansible-playbook
with --ask-become-pass
or when using the old sudo syntax --ask-sudo-pass
(-K
). If you run a become playbook and the playbook seems to hang, it’s probably stuck at the privilege escalation prompt. Just Control-C to kill it and run it again adding the appropriate password.
如果您需要为sudo指定密码,请ansible-playbook
使用--ask-become-pass
或使用旧的sudo语法--ask-sudo-pass
(-K
)运行。如果你运行一个成为playbook并且剧本似乎挂起,它可能会停留在权限提升提示下。只需控制-C来杀死它并再次运行它添加适当的密码。
重要
When using become_user to a user other than root, the module arguments are briefly written into a random tempfile in /tmp. These are deleted immediately after the command is executed. This only occurs when changing privileges from a user like ‘bob’ to ‘timmy’, not when going from ‘bob’ to ‘root’, or logging in directly as ‘bob’ or ‘root’. If it concerns you that this data is briefly readable (not writable), avoid transferring unencrypted passwords with become_user set. In other cases, /tmp is not used and this does not come into play. Ansible also takes care to not log password parameters.
当使用become_user非root用户时,模块参数会被简单地写入随机的临时文件中/tmp。执行命令后立即删除它们。这种情况只发生在将用户从'bob'更改为'timmy'时的权限,而不是从'bob'更改为'root',或直接以'bob'或'root'身份登录时。如果您担心此数据可以短暂读取(不可写),请避免使用become_user设置传输未加密的密码 。在其他情况下,/tmp不使用,这不会发挥作用。Ansible还注意不记录密码参数。
New in version 2.4.版本2.4中的新功能。
You can also control the order in which hosts are run. The default is to follow the order supplied by the inventory:
您还可以控制运行主机的顺序。默认设置是遵循库存inventory提供的顺序:
- hosts: all
order: sorted
gather_facts: False
tasks:
- debug:
var: inventory_hostname
Possible values for order are:
顺序的值
- inventory:
- The default. The order is ‘as provided’ by the inventory
- 默认值。订单由库存“提供”
- reverse_inventory:
- As the name implies, this reverses the order ‘as provided’ by the inventory
- 顾名思义,这会反转库存“按提供”的顺序
- sorted:
- Hosts are alphabetically sorted by name
- 主机按名称按字母顺序排序
- reverse_sorted:
- Hosts are sorted by name in reverse alphabetical order
- 主机按名称按反向字母顺序排序
- shuffle:
- Hosts are randomly ordered each run
- 主机是每次运行随机排序的
Tasks list
任务列表
Each play contains a list of tasks. Tasks are executed in order, one at a time, against all machines matched by the host pattern, before moving on to the next task. It is important to understand that, within a play, all hosts are going to get the same task directives. It is the purpose of a play to map a selection of hosts to tasks.
每个游戏都包含一系列任务。在继续执行下一个任务之前,任务将按顺序执行,对应所有与主机模式匹配的计算机。重要的是要理解,在游戏中,所有主机都将获得相同的任务指令。播放的目的是将选择的主机映射到任务。
When running the playbook, which runs top to bottom, hosts with failed tasks are taken out of the rotation for the entire playbook. If things fail, simply correct the playbook file and rerun.
当运行从上到下运行的剧本时,具有失败任务的主机将从整个剧本的轮换中取出。如果事情失败,只需更正剧本文件并重新运行。
The goal of each task is to execute a module, with very specific arguments. Variables, as mentioned above, can be used in arguments to modules.
每个任务的目标是执行一个具有非常具体参数的模块。如上所述,变量可用于模块的参数。
Modules should be idempotent, that is, running a module multiple times in a sequence should have the same effect as running it just once. One way to achieve idempotency is to have a module check whether its desired final state has already been achieved, and if that state has been achieved, to exit without performing any actions. If all the modules a playbook uses are idempotent, then the playbook itself is likely to be idempotent, so re-running the playbook should be safe.
模块应该是幂等的,也就是说,在序列中多次运行模块应该与仅运行一次模块具有相同的效果。实现幂等性的一种方法是让模块检查是否已经实现了期望的最终状态,并且如果已经实现该状态,则退出而不执行任何动作。如果剧本使用的所有模块都是幂等的,那么剧本本身很可能是幂等的,因此重新运行剧本应该是安全的。
The command and shell modules will typically rerun the same command again, which is totally ok if the command is something like chmod
or setsebool
, etc. Though there is a creates
flag available which can be used to make these modules also idempotent.
该command和shell模块通常会再次运行相同的命令,这是完全确定的,如果命令是一样的东西 chmod
还是setsebool
等虽然有一个creates
可用的标志,它可以用来让这些模块也幂等。
Every task should have a name
, which is included in the output from running the playbook. This is human readable output, and so it is useful to provide good descriptions of each task step. If the name is not provided though, the string fed to ‘action’ will be used for output.
每个任务都应该有一个name
,它包含在运行playbook的输出中。这是人类可读的输出,因此提供每个任务步骤的良好描述是有用的。如果没有提供名称,则输入“action”的字符串将用于输出。
Tasks can be declared using the legacy action: module options
format, but it is recommended that you use the more conventional module: options
format. This recommended format is used throughout the documentation, but you may encounter the older format in some playbooks.
可以使用旧格式声明任务,但建议您使用更传统的格式。在整个文档中使用了此推荐格式,但在某些剧本中可能会遇到旧格式。action: module options
module: options
Here is what a basic task looks like. As with most modules, the service module takes key=value
arguments:
- 这是基本任务的样子。与大多数模块一样,服务模块采用
key=value
参数:
tasks:
- name: make sure apache is running
service:
name: httpd
state: started
The command and shell modules are the only modules that just take a list of arguments and don’t use the key=value
form. This makes them work as simply as you would expect:
该command 和shell 模块是只取参数列表,并没有使用唯一的模块key=value
形式。这使它们像您期望的那样工作:
tasks:
- name: enable selinux
command: /sbin/setenforce 1
The command and shell module care about return codes, so if you have a command whose successful exit code is not zero, you may wish to do this:
该command 和shell 模块关心的返回码,所以如果你有一个命令,其成功退出码不为零,你不妨这样做:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand || /bin/true
Or this:
或这个:
tasks:
- name: run this command and ignore the result
shell: /usr/bin/somecommand
ignore_errors: True
If the action line is getting too long for comfort you can break it on a space and indent any continuation lines:
如果动作线太长而不舒服,你可以在空格上打破它并缩进任何延续线:
tasks:
- name: Copy ansible inventory file to client
copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts
owner=root group=root mode=0644
Variables can be used in action lines. Suppose you defined a variable called vhost
in the vars
section, you could do this:
变量可用于动作行。假设您定义了一个vhost
在该vars
部分中调用的变量,您可以这样做:
tasks:
- name: create a virtual host file for {{ vhost }}
template:
src: somefile.j2
dest: /etc/httpd/conf.d/{{ vhost }}
Those same variables are usable in templates, which we’ll get to later.
这些相同的变量可以在模板中使用,我们将在稍后介绍。
Now in a very basic playbook all the tasks will be listed directly in that play, though it will usually make more sense to break up tasks as described in Creating Reusable Playbooks.
现在,在一个非常基本的游戏手册中,所有任务都将直接列在该游戏中,尽管按创建可重复使用的手册中的描述分解任务通常更有意义。
Action Shorthand
动作简写
New in version 0.8.
版本0.8中的新功能。
Ansible prefers listing modules like this:
Ansible更喜欢列出这样的模块:
template:
src: templates/foo.j2
dest: /etc/foo.conf
Early versions of Ansible used the following format, which still works:
早期版本的Ansible使用以下格式,它仍然有效:
action: template src=templates/foo.j2 dest=/etc/foo.conf
Handlers: Running Operations On Change
处理程序:在变更时运行操作
As we’ve mentioned, modules should be idempotent and can relay when they have made a change on the remote system. Playbooks recognize this and have a basic event system that can be used to respond to change.
正如我们所提到的,模块应该是幂等的,并且可以在他们对远程系统进行更改时进行中继。Playbooks认识到这一点,并拥有一个可用于响应变化的基本事件系统。
These ‘notify’ actions are triggered at the end of each block of tasks in a play, and will only be triggered once even if notified by multiple different tasks.
这些“通知”操作在游戏中的每个任务块结束时触发,即使由多个不同任务通知也只会触发一次。
For instance, multiple resources may indicate that apache needs to be restarted because they have changed a config file, but apache will only be bounced once to avoid unnecessary restarts.
例如,多个资源可能表示需要重新启动apache,因为他们已经更改了配置文件,但是apache只会被弹回一次以避免不必要的重启。
Here’s an example of restarting two services when the contents of a file change, but only if the file changes:
以下是在文件内容发生更改时重新启动两个服务的示例,但仅在文件更改时:
- name: template configuration file
template:
src: template.j2
dest: /etc/foo.conf
notify:
- restart memcached
- restart apache
The things listed in the notify
section of a task are called handlers.
notify
任务部分中列出的内容称为处理程序。
Handlers are lists of tasks, not really any different from regular tasks, that are referenced by a globally unique name, and are notified by notifiers. If nothing notifies a handler, it will not run. Regardless of how many tasks notify a handler, it will run only once, after all of the tasks complete in a particular play.
处理程序是由全局唯一名称引用并由通知程序通知的任务列表,与常规任务实际上没有任何不同。如果没有通知处理程序,它将不会运行。无论通知处理程序的任务有多少,在特定游戏中完成所有任务后,它只会运行一次。
Here’s an example handlers section:
这是一个示例处理程序部分:
handlers:
- name: restart memcached
service:
name: memcached
state: restarted
- name: restart apache
service:
name: apache
state: restarted
As of Ansible 2.2, handlers can also “listen” to generic topics, and tasks can notify those topics as follows:
从Ansible 2.2开始,处理程序也可以“监听”通用主题,任务可以通知如下主题:
handlers: - name: restart memcached service: name: memcached state: restarted listen: "restart web services" - name: restart apache service: name: apache state:restarted listen: "restart web services" tasks: - name: restart everything command: echo "this task will restart the web services" notify: "restart web services"
This use makes it much easier to trigger multiple handlers. It also decouples handlers from their names, making it easier to share handlers among playbooks and roles (especially when using 3rd party roles from a shared source like Galaxy).
这种使用使得触发多个处理程序变得更加容易。它还将处理程序与其名称分离,从而更容易在playbooks和角色之间共享处理程序(特别是在使用Galaxy等共享源中的第三方角色时)。
注意 Notify handlers are always run in the same order they are defined, not in the order listed in the notify-statement. This is also the case for handlers using listen. 通知处理程序始终按照定义的顺序运行,而不是以notify-statement中列出的顺序运行。使用listen的处理程序也是如此。 Handler names and listen topics live in a global namespace. 处理程序名称和侦听主题位于全局命名空间中。 If two handler tasks have the same name, only one will run. * 如果两个处理程序任务具有相同的名称,则只运行一个。 * You cannot notify a handler that is defined inside of an include. As of Ansible 2.1, this does work, however the include must be static. 您无法通知在include内定义的处理程序。从Ansible 2.1开始,这确实有效,但是include必须是静态的。
Roles are described later on, but it’s worthwhile to point out that:
角色将在后面描述,但值得指出的是:
- handlers notified within
pre_tasks
,tasks
, andpost_tasks
sections are automatically flushed in the end of section where they were notified; - 处理程序中通知
pre_tasks
,tasks
以及post_tasks
部分是在那里他们被通知部的端部自动刷新; - handlers notified within
roles
section are automatically flushed in the end oftasks
section, but before anytasks
handlers. roles
部分内通知的处理程序在部分末尾自动刷新tasks
,但在任何tasks
处理程序之前。
If you ever want to flush all the handler commands immediately you can do this:
如果您想立即刷新所有处理程序命令,可以执行以下操作:
tasks: - shell: some tasks go here - meta: flush_handlers - shell: some other tasks
In the above example any queued up handlers would be processed early when the meta
statement was reached. This is a bit of a niche case but can come in handy from time to time.
在上面的示例中,任何排队的处理程序将在meta
到达语句时尽早处理。这是一个利基案例,但可以不时派上用场。
Executing A Playbook
Now that you’ve learned playbook syntax, how do you run a playbook? It’s simple. Let’s run a playbook using a parallelism level of 10:
既然你已经学会了剧本语法,你如何运行剧本?这很简单。让我们使用10的并行度级别运行一个剧本
ansible-playbook playbook.yml -f 10
Ansible-Pull
Should you want to invert the architecture of Ansible, so that nodes check in to a central location, instead of pushing configuration out to them, you can.
如果您想要反转Ansible的体系结构,以便节点检入中心位置,而不是将配置推送到它们,您可以。
The ansible-pull
is a small script that will checkout a repo of configuration instructions from git, and then run ansible-playbook
against that content.
这ansible-pull
是一个小脚本,将从git检出配置指令的repo,然后ansible-playbook
针对该内容运行。
Assuming you load balance your checkout location, ansible-pull
scales essentially infinitely.
假设您对结帐位置进行负载均衡,则ansible-pull
无限扩展。
Run ansible-pull --help
for details.
运行详细信息。ansible-pull --help
There’s also a clever playbook available to configure ansible-pull
via a crontab from push mode.
还有一个聪明的手册可以ansible-pull
通过推送模式从crontab 进行配置。
Tips and Tricks
提示和技巧
To check the syntax of a playbook, use ansible-playbook
with the --syntax-check
flag. This will run the playbook file through the parser to ensure its included files, roles, etc. have no syntax problems.
要检查剧本的语法,使用ansible-playbook
与--syntax-check
标志。这将通过解析器运行playbook文件,以确保其包含的文件,角色等没有语法问题。
Look at the bottom of the playbook execution for a summary of the nodes that were targeted and how they performed. General failures and fatal “unreachable” communication attempts are kept separate in the counts.
查看playbook执行的底部,了解目标节点及其执行方式的摘要。一般失败和致命的“无法到达”的通信尝试在计数中保持分开。
If you ever want to see detailed output from successful modules as well as unsuccessful ones, use the --verbose
flag. This is available in Ansible 0.5 and later.
如果您想查看成功模块以及不成功模块的详细输出,请使用该--verbose
标志。这在Ansible 0.5及更高版本中可用。
To see what hosts would be affected by a playbook before you run it, you can do this:
要在运行之前查看哪个主机会受到剧本的影响,您可以执行以下操作:
ansible-playbook playbook.yml --list-hosts
See also 也可以看看
- YAML Syntax
- Learn about YAML syntax 了解YAML语法
- Best Practices
- Various tips about managing playbooks in the real world 关于在现实世界中管理剧本的各种提示
- All modules
- Learn about available modules 了解可用的模块
- Developing Modules
- Learn how to extend Ansible by writing your own modules 了解如何通过编写自己的模块来扩展Ansible
- Working with Patterns
- Learn about how to select hosts 了解如何选择主机
- Github examples directory
- Complete end-to-end playbook examples 完整的端到端剧本示例
- Mailing List
- Questions? Help? Ideas? Stop by the list on Google Groups 有问题吗?帮帮我?想法?停止在Google网上论坛列表中