|
如无书面授权,请勿转载
Larger Projects
Until now, we have been looking at single plays in one playbook file. This approach
will work for simple infrastructures, or when using Ansible as a simple deployment
mechanism. However, if you have a large and complicated infrastructure, then you
will need to take actions to prevent things from going out of control. This chapter
will include the following topics:
· Separating your playbooks into different files, and including them from some
other location
· Using roles to include multiple files that perform a similar function
· Methods for increasing the speed at which Ansible configures your machines
第四章 大型项目中Ansible的使用
至此,我们已经介绍了如何用一个playbook文件运行一个plays。在小型架构或则使用Ansible做一个简单的部署机制时这已经很有用了。但是,如果你有一个很大很复杂的系统架构,你可能需要一些额外的操作来保证事情不会超出我们的控制。本章包含以下主题:
- 将你的playbooks分离成多个文件,存储在不同的地方
- 使用角色包含多个文件来完成同样的功能
- 加速使用Ansible配置机器的方法
Includes
One of the first issues you will face with a complex infrastructure is that your
playbooks will rapidly increase in size. Large playbooks can become difficult to read
and maintain. Ansible allows you to combat this problem by the way of includes.
Includes allow you to split your plays into multiple sections. You can then include
each section from other plays. This allows you to have several different parts built
for a different purpose, all included in a main play.
There are four types of includes, namely variable includes, playbook includes,
task includes, and handler includes. Including variables from an external vars_file
files has been discussed already in Chapter 2, Simple Playbooks. The following is a
summary of what each includes does:
· Variable includes: They allow you to put your variables in external
YAML files
· Playbook includes: They are used to include plays from other files in a s
ingle playLarger Projects
· Task includes: They let you put common tasks in other files and include
them wherever required
· Handler includes: They let you put all your handlers in the one place
包含
在大型复杂架构中,你第一个要面对的问题就是不断增长的playbooks文件大小,一个很大的playbooks很难去理解和维护,解决办法是使用包含includes。将你的plays分解成多个不同的段,然后在其他的plays中包含他们。不同的段根据不同目的地分类,全部包含在主play中。
有四种类型的包含,分别是变量包含、playbook包含、任务包含、处理程序handler包含。从外部变量文件包含变量,在第二章已经讨论过。下面是每个包含类型的介绍:
- 变量包含:允许你将变量存在外部YAML文件
- playbook包含:一个大型项目中可以包含多个plays
- 任务包含:将任务放到普通文件中,当需要的时候包含他们
- 处理程序Handler包含:允许你将所有的handlers处理程序放到一个地方
Task includes
Task includes can be used when you have a lot of common tasks that will be
repeated. For example, you may have a set of tasks that removes a machine, from
monitoring, and a load balancer before you can configure it. You can put these tasks
in a separate YAML file, and then include them from your main task.
Task includes inherit the facts from the play they are included from. You can also
provide your own variables, which are passed into the task and available for use.
Finally, task includes can have conditionals applied to them. If you do this,
conditionals will separately be added to each included task. The tasks are all still
included. In most cases, this is not an important distinction, but in circumstances
where variables may change, it is.
The file to include as a task includes contains a list of tasks. If you assume the
existence of any variables and hosts or groups, then you should state them in
comments at the top. This makes reusing the file much easier.
So, if you wanted to create a bunch of users and set up their environment with their
public keys, you would split out the tasks that do a single user to one file. This file
would look similar to the following code:
---
# Requires a user variable to specify user to setup
- name: Create user account
#2
user: name={{ user }} state=present
#3
#1
- name: Make user SSH config dir
#4
file: path=/home/{{ user }}/.ssh owner={{ user }} group={{ user
}} mode=0600 state=directory
#5
- name: Copy in public key
#6
copy: src=keys/{{ user }}.pub dest=/home/{{ user
}}/.ssh/authorized_keys mode=0600 owner={{ user }} group={{ user
}}
#7
We expect that a variable named user will be passed to us, and that their public
key will be in the keys directory. The account is created, the ssh config directory
is made, and finally we can copy this in their public key. The easiest way to use this
config file would be to include it with the with_items keyword we learned about in
Chapter 3, Advanced Playbooks. This would look similar to the following code:
---
- hosts: ansibletest
user: root
tasks:
- include: usersetup.yml user={{ item }}
with_items:
- mal
- dan
- kate
任务包含
当你有很多类似的任务需要重复执行的时候,你可以使用任务包含。比如,在你配置一台设备之前,需要从负载均衡或者监控系统中删除这台设备,你可以把这种任务分别放进不同的YAML文件中,然后在你的主任务文件中包含他们。
被包含的任务facts会继承包含他的play的facts,你也可以自己提供变量,他们在play中都是可用的。
此外,任务包含可以是有条件的,如果你设定了条件,那么条件将会被添加到每一个包含它的任务中,任务会一直被包含。多数情况下,这样没什么重要的区别,但如果存在变量的话,就不一样了。一个任务文件可以包含很多任务,如果你要设定变量,最好在文件的顶部来注释他们,这样可以使得它更加易于被理解和利用。
比如你要创建很多用户,并用他们的公钥来设置环境变量。你可以先做好一个用户的的任务放到一个文件中,这个文件代码如下:
---
# Requires a user variable to specify user to setup
- name: Create user account
user: name={{ user }} state=present
- name: Make user SSH config dir
file: path=/home/{{ user }}/.ssh owner={{ user }} group={{ user
}} mode=0600 state=directory
- name: Copy in public key
copy: src=keys/{{ user }}.pub dest=/home/{{ user
}}/.ssh/author
我们预计变量名{{user}}会被传递给我们,他们的公钥在keys目录中。用户建立之后,ssh config文件夹就被创建,然后我们复制公钥文件进去。包含这个任务最简单的办法就是使用第三章介绍的with_items关键字
代码如下:
---
- hosts: ansibletest
user: root
tasks:
- include: usersetup.yml user={{ item }}
with_items:
- mal
- dan
- kate
Handler includes
When writing Ansible playbooks, you will constantly find yourself reusing the same
handlers multiple times. For instance, a handler used to restart MySQL is going to
look the same everywhere. To make this easier, Ansible allows you to include other
files in the handlers section. Handler includes look the same as task includes. You
should make sure to include a name on each of your handlers; otherwise you will not
be able to refer to them easily in your tasks. A handler include file looks similar to
the following code:
---
- name: config sendmail
command: make -C /etc/mail
notify: reload sendmail
- name: config aliases
command: newaliases
notify: reload sendmail
- name: reload sendmail
service: name=sendmail state=reloaded
- name: restart sendmail
service: name=sendmail state=restarted
This file provides several common tasks that you would want to handle after
configuring sendmail . By including the following handlers in their own files, you
can easily reuse them whenever you need to change the sendmail configuration:
· The first handler regenerates the sendmail database's config file and
triggers a reload file of sendmail later
· The second handler initializes the aliases database, and also schedules a
reload file of sendmail
The third handler reloads sendmail ; it may be triggered by the previous two
jobs, or it may be triggered directly from a task
· The fourth handler restarts sendmail when triggered; this is useful if you
upgrade sendmail to a new version
Handlers can trigger other handlers provided that they only trigger
the ones specified later, instead of the triggered ones. This means, you
can set up a series of cascading handlers that call each other. This saves
you from having long lists of handlers in the notify section of tasks.
Using the preceding handler file is easy now. We simply need to remember that if we
change a sendmail configuration file, then we should trigger config sendmail , and
if we change the aliases file, we should trigger config aliases . The following
code shows us an example of this:
---
hosts: mailers
#1
tasks:
#2
- name: update sendmail
#3
yum: name=sendmail state=latest
notify: restart sendmail
#5
#4
- name: configure sendmail
#6
template: src=templates/sendmail.mc.j2
dest=/etc/mail/sendmail.mc
#7
notify: config sendmail
#8
handlers:
#9
- include: sendmailhandlers.yml
#10
This playbook makes sure sendmail is installed. If it isn't installed or if it isn't
running the latest version, then it installs it. After it is updated, it schedules a
restart so that we can be confident that the latest version will be running once the
playbook is done. In the next step, we replace the sendmail configuration file with
our template. If the config file was changed by the template then the sendmail
configuration files will be regenerated, and finally sendmail will be reloaded.
Handler 处理程序包含
当我们编写playbooks时,Handler也是经常被重用的。比如,重启MYSQL的handler到处可以见。我们可以在Handler选项中包含他们,和任务包含一样,你要确定包含了每一个你需要的Handler的名字,否则在引用的时候就不那么方便了。Handler包含的文件类似如下代码:
---
- name: config sendmail
command: make -C /etc/mail
notify: reload sendmail
- name: config aliases
command: newaliases
notify: reload sendmail
- name: reload sendmail
service: name=sendmail state=reloaded
- name: restart sendmail
service: name=sendmail state=restarted
这个文件包含了许多在配置完sendmail之后需要的做的handler操作,如果我们在任务文件本身包含他们,在你需要改变sendmail配置的时候将很容易被重用。
- 第一个handler在重新生成配置文件之后,重新加载了配置文件
- 第二个handler在配置玩aliases之后,重新加载了配置文件
- 第三个handler重新加载配置文件,它可以是被前面2个任务触发,也可以在包含他的任务中直接调用他们
- 第四个handler重启了sendmail服务,如果你升级了sendmail版本,你可能就要用到了
注意:Handlers 也可以被其他的Handlers触发,其中会有重复的Handlers,但是只有最后一个被指定的Handlers会被执行。这样在你的任务中的notify选项就不需要一串长长的Handlers列表了。
使用这个Handlers文件很简单,我们只要记住:如果我们改变了配置文件,我们就触发config sendmai,如果我们该了aliases,我们就触发config aliases,代码如下:
---
hosts: mailers
tasks:
- name: update sendmail
yum: name=sendmail state=latest
notify: restart sendmail
- name: configure sendmail
template: src=templates/sendmail.mc.j2
dest=/etc/mail/sendmail.mc
notify: config sendmail
handlers:
- include: sendmailhandlers.yml
如果sendmail没安装或者不是最新版本,这个palybook会安装并更新它,之后需要重启;使用模板文件之后,还需要重新生成sendmail配置文件,而这2个处理程序都被包含在sendmailhandlers.yml文件中。
Playbook includes
Playbook includes should be used when you want to include a whole set of tasks
designated for a set of machines. For example, you may have a play that gathers
the host keys of several machines and builds a known_hosts file to copy to all the
machines.
While task includes allows you to include tasks, playbook includes allows you to
include whole plays. This allows you to select the hosts you wish to run on, and
provide handlers for notify events. Because you are including whole playbook files,
you can also include multiple plays.
Playbook includes allows you to embed fully self-contained files. It is for this reason
that you should provide any variables that it requires. If they depend on any particular
set of hosts or groups, this should be noted in a comment at the top of the file.
This is handy when you wish to run multiple different actions at once. For example,
let's say we have a playbook that switches to our DR site, named drfailover.
yml , another named upgradeapp.yml that upgrades the app, another named
drfailback.yml that fails back, and finally drupgrade.yml . All these playbooks
might be valid to use separately, but when performing a site upgrade, you will
probably want to perform them all at once. You can do this as shown in the
following code:
---
- include "drfailover.yml"
- include "upgradeapp.yml"
- include "drfailback.yml"
#1
#2
#3
- name: Notify management
#4
hosts: local
#5
tasks:
#6
- local_action: mail to="mgmt-team@example.com" msg='The
application has been upgraded and is now live'
#7
- include "drupgrade.yml"
#8
As you can see, you can put full plays in the playbooks that you are including other
playbooks into.
Playbook 包含
当你需要为一批机器设计一系列任务的时候,你可以使用playbooks包含。比如,你可能想要收集一批机器的host key合并到known_hosts中,然后分发给所有机器。
playbook包含允许你选择运行的主机、handler处理程序。另外,除了包含一个playbook,你还可以包含多个playbook。
playbook包含允许您嵌入完全自包含的文件,因此你应该提供任何需要的变量。如果它依赖某些特殊的主机或组,那你应该在文件顶部中做好注释。当你要一次性运行多个actions操作的时候,使用playbook包含非常方便。
比如:我们有一个文件叫drfailover.yml用来切换我们的dr(dr是负载均衡配置的名词,一般有一主一备2个dr,这里不多做解释啦,同学们可以百度之),一个叫upgradeapp.yml的文件用来更新应用程序,一个叫drfailback.yml的文件用来切换回原来的dr,还有一个drupgrade.yml用来升级dr。这些文件都是独立的,当我们想升级应用程序的时候,我们可以一次性使用它们。代码如下:
---
- include "drfailover.yml"
- include "upgradeapp.yml"
- include "drfailback.yml"
- name: Notify management
hosts: local
tasks:
- local_action: mail to="mgmt-team@example.com" msg='The
application has been upgraded and is now live'
- include "drupgrade.yml"
使用playbook之后,你可以把所有操作都放在一个playbook中了! |
|