不要未经书面许可转载
第三章是长,因为,我会分几个部分来翻译。
Advanced Playbooks So far the playbooks that we have looked at are simple and just run a number of modules in order. Ansible allows much more control over the execution of your playbook. Using the following techniques, you should be able to perform even the most complex deployments. Running operations in parallel By default, Ansible will only fork up to five times, so it will only run an operation on five different machines at once. If you have a large number of machines, or you have lowered this maximum fork value, then you may want to launch things asynchronously. Ansible's method for doing this is to launch the task and then poll for it to complete. This allows Ansible to start the job across all the required machines while still using the maximum forks. To run an operation in parallel, use the async and poll keywords. The async keyword triggers Ansible to run the job in parallel, and its value will be the maximum time that Ansible will wait for the command to complete. The value of poll indicates to Ansible how often to poll to check if the command has been completed. If you wanted to run updatedb across an entire cluster of machines, it might look like the following code: - hosts: all tasks: - name: Install mlocate yum: name=mlocate state=installed - name: Run updatedb command: /usr/bin/updatedb async: 300 poll: 10 You will notice that when you run the previous example on more than five machines, the yum module acts differently to the command module. The yum module will run on the first five machines, then the next five, and so on. The command module, however, will run across all the machines and indicate the status once complete. If your command starts a daemon that eventually listens on a port, you can start it without polling so that Ansible does not check for it to complete. You can then carry on with other actions and check for completion later using the wait_for module. To configure Ansible to not wait for the job to complete, set the value of poll to 0 . Finally, if the task that you are running takes an extremely long time to run, you can tell Ansible to wait for the job as long as it takes. To do this, set the value of async to 0 . You will want to use Ansible's polling in the following situations: ? You have a long-running task that may hit the timeout ? You need to run an operation across a large number of machines ? You have an operation for which you don't need to wait to complete There are also a few situations where you should not use async or poll : ? If your job acquires locks that prevent other things from running ? You job only takes a short time to run
高级Palybook
之前我们遇到的playbook都比較简单,仅仅须要执行一些模块就能够了。
可是Ansible同意你在执行playbook的时候有很多其它的控制,让你能够完毕最最复杂的部署任务。
并行执行任务
Ansible默认一次启用5个线程,所以仅仅能一次仅仅能对5台机器进行操作。假设你的机器数量超过5个,或者线程数低于5个,那么你可能会想要用异步来完毕。Ansible的方法是轮询每一个任务直到任务结束,这样Absible就能够在使用5个线程的情况下完毕全部机器(超过5台机器)操作的任务。
启用并行。须要使用async 和poll这2个keyword,asynckeyword启用并行,而它的值是他的最大等待时间。poll则设置Ansible多久检查一次任务是否完毕。
以下的样例,一次性更新一个群集里面全部的数据库,代码例如以下:
- hosts: all
tasks:
- name: Install mlocate
yum: name=mlocate state=installed
- name: Run updatedb
command: /usr/bin/updatedb
async: 300
poll: 10
当你执行这个列子的时候,yum操作是5台机器5台机器的执行,可是updatedb操作是一次性操作全部机器,并立马返回操作状态信息。
假设启用一个daemon程序。并终于会监听一个port,那么你能够不须要使用poll轮询,而用上一章介绍的wait_for模块。这样仅仅须要把poll的值设置为0就能够了。假设你的操作可能要运行非常长非常长的时间。那么我们仅仅须要告诉Ansible一直等待就能够了,这样仅仅须要把asyn设置为0就可以。
轮询适用的场合有:
- 当你的任务须要执行非常长时间。而且可能超时的时候
- 当操作的机器数量非常大的时候
- 当一个任务,你不须要等待他返回结束信号的时候
不适用async 或则 poll 的场合:
- 你的任务有依赖关系的其它任务的时候
- 你的任务花费的时间非常短的时候
Looping Ansible allows you to repeat a module several times with different input, for example, if you had several files that should have similar permissions set. This can save you a lot of repetition and allows you to iterate over facts and variables. To do this, you can use the with_items key on an action and set the value to the list of items that you are going to iterate over. This will create a variable for the module called item , which will be set to each item in turn as your module is iterated over. Some modules such as yum will optimize this so that instead of doing a separate transaction for each package, they will operate on all of them at once. Using with_items looks like this: tasks: - name: Secure config files file: path=/etc/{{ item }} mode=0600 owner=root group=root with_items: - my.cnf - shadow - fstab In addition to looping over fixed items, or a variable, Ansible can also use what are called lookup plugins. These plugins allow you to tell Ansible to fetch the data from somewhere externally. For example, you might want to upload all the files that match a particular pattern, and then upload them. In this example, we upload all the public keys in a directory and then assemble them into an authorized_keys file for the root user. tasks: #1 - name: Make key directory #2 file: path=/root/.sshkeys ensure=directory mode=0700 owner=root group=root #3 - name: Upload public keys #4 copy: src={{ item }} dest=/root/.sshkeys mode=0600 owner=root group=root #5 with_fileglob: #6 - keys/*.pub #7 - name: Assemble keys into authorized_keys file #8 assemble: src=/root/.sshkeys dest=/root/.ssh/authorized_keys mode=0600 owner=root group=root #9 Repeating modules can be used in the following situations: ? Repeating a module many times with similar settings ? Iterating over all the values of a fact that is a list ? Used to create many files for later use with the assemble module to combine into one large file ? Used with_fileglob to copy a directory of files using the glob pattern matching
Loop循环
Anisble能够依据不同的输入反复执行一个模块非常多次,比方一些权限集差点儿相同的文件。你能够依据实际情况和变量值来迭代他们。
使用with_itemskeyword来定义一个循环。把你希望的数据插入一个列表作为它的值。
这样会生成一个变量叫item,当你历遍列表的时候,item将被列表中的元素挨个赋值。像yum这种模块还会自己主动优化这种操作,所以你能够使用循环一次性所有完毕。
循环的机构类似以下的代码:
tasks:
- name: Secure config files
file: path=/etc/{{ item }} mode=0600 owner=root group=root
with_items:
- my.cnf
- shadow
- fstab
此外,Anisble还能够使用lookup插件来使用外部数据,比方你想上传全部符合一个表达式规则的文件到目的地。以下的样例中。我们上传公钥文件夹下的全部文件,合并到authorized_keys文件给root用户。
tasks:
- name: Make key directory
file: path=/root/.sshkeys ensure=directory mode=0700
owner=root group=root
- name: Upload public keys
copy: src={{ item }} dest=/root/.sshkeys mode=0600
owner=root group=root
with_fileglob:
- keys/*.pub
- name: Assemble keys into authorized_keys file
assemble: src=/root/.sshkeys dest=/root/.ssh/authorized_keys
mode=0600 owner=root group=root
Repeating模块适用的场景有:
- 反复一个类似配置的模块非常多次的时候
- 历遍列表(依据实际情况fact)中全部的值的时候
- 当要创建非常多文件然后用assemble模块合并到一个大文件的时候
- 使用with_fileglob复制一个文件夹下全部模式匹配的文件的时候
Conditional execution Some modules, such as the copy module, provide mechanisms to configure it to skip the module. You can also configure your own skip conditions that will only execute the module if they resolve to true . This can be handy if your servers use different packaging systems or have different filesystem layouts. It can also be used with the set_fact module to allow you to compute many different things. To skip a module, you can use the when key; this lets you provide a condition. If the condition you set resolves to false , then the module will be skipped. The value that you assign to when is a Python expression. You can use any of the variables or facts available to you at this point. --- - name: Install VIM hosts: all tasks: - name: Install VIM via yum yum: name=vim-enhanced state=installed when: ansible_os_family == "RedHat"<p> - name: Install VIM via apt apt: name=vim state=installed when: ansible_os_family == "Debian"</p> - name: Unexpected OS family debug: msg="OS Family {{ ansible_os_family }} is not supported" fail=yes when: not ansible_os_family == "RedHat" or ansible_os_family == "Debian" This feature can be used to pause at a particular point and wait for the user intervention to continue. Normally when Ansible encounters an error, it will simply stop what it is doing without running any handlers. With this feature, you can add the pause module with a condition on it that triggers in unexpected situations. This way the pause module will be ignored in a normal situation, but in unexpected circumstances it will allow the user to intervene and continue when it is safe to do so. The task would look like this: name: pause for unexpected conditions pause: prompt="Unexpected OS" when: ansible_os_family != "RedHat" There are numerous uses of skipping actions; here are a few suggestions: ? Working around differences in operating systems ? Prompting a user and only then performing actions that they request ? Improving performance by avoiding a module that you know won't change anything but may take a while to do so ? Refusing to alter systems that have a particular file present ? Checking if custom written scripts have already been run
条件运行
有些像copy这种模块提供skip忽略机制,你也能够配置你自己的条件来跳过某些模块的运行。
当你的server使用不同的操作系统、文件类型的时候特别实用。
你能够依据set_fact模块的值来做不同的事情。
跳过一个模块的运行,使用when这个keyword来提供一个条件,假设条件为假,跳过运行,使用python表达式作为它的值,在这里你能够使用不论什么变量或则不论什么可能的fact。
以下的样例就是依据操作系统确定是使用apt还是yum来运行安装操作,当os信息无法确定的时候,就打印一个消息。
---
- name: Install VIM
hosts: all
tasks:
- name: Install VIM via yum
yum: name=vim-enhanced state=installed
when: ansible_os_family == "RedHat"
- name: Install VIM via apt
apt: name=vim state=installed
when: ansible_os_family == "Debian"
- name: Unexpected OS family
debug: msg="OS Family {{ ansible_os_family }} is not
supported" fail=yes
when: not ansible_os_family == "RedHat" or ansible_os_family
== "Debian"
依据这个特性,我们还能够加入pause模块来让用户进行确认以继续,在符合我们设定的条件的正常情况下。pause模块不会被运行,仅仅有异常情况下才会被调用并请求用户确认以继续任务,代码例如以下
name: pause for unexpected conditions
pause: prompt="Unexpected OS"
when: ansible_os_family != "RedHat"
条件运行适用的场景和建议:
- 当要在不同的操作系统上进行操作的时候
- 提示用户,然后再运行操作请求
- 当执行一个须要较长时间的查询任务的时候
- 当硬盘空间超过警戒线的时候禁止更新
- 确认自己定义脚本是否已经执行
Task delegation Ansible, by default, runs its tasks all at once on the configured machine. This is great when you have a whole bunch of separate machines to configure, or if each of your machines is responsible for communicating its status to the other remote machines. However, if you need to perform an action on a different host than the one Ansible is operating on, you can use a delegation. Ansible can be configured to run a task on a different host than the one that is being configured using the delegate_to key. The module will still run once for every machine, but instead of running on the target machine, it will run on the delegated host. The facts available will be the ones applicable to the current host. Here, we show a playbook that will use the get_url option to download the configuration from a bunch of web servers. --- - name: Fetch configuration from all webservers hosts: webservers tasks: - name: Get config get_url: dest=configs/{{ ansible_hostname }} force=yes url=http://{{ ansible_hostname }}/diagnostic/config delegate_to: localhost If you are delegating to the localhost , you can use a shortcut when defining the action that automatically uses the local machine. If you define the key of the action line as local_action , then the delegation to localhost is implied. If we were to have used this in the previous example, it would be slightly shorter and look like this: --- - name: Fetch configuration from all webservers hosts: webservers tasks: - name: Get config local_action: get_url dest=configs/{{ ansible_hostname }}.cfg url=http://{{ ansible_hostname }}/diagnostic/config Delegation is not limited to the local machine. You can delegate to any host that is in the inventory. Some other reasons why you might want to delegate are: ? Removing a host from a load balancer before deployment ? Changing DNS to direct traffic away from a server you are about to change ? Creating an iSCSI volume on a storage device ? Using an external server to check that access outside the network works
任务的委派
Ansible默认在配置的机器上执行任务,当你有一大票机器须要配置或则每一个设备都可达的情况下非常实用。
可是。当你须要在另外一个Ansible控制机器上执行任务的时候,就须要用到任务委派了。
使用delegate_tokeyword就能够委派任务到其它机器上执行。同一时候可用的fact也会使用委派机器上的值。以下的样例使用get_url到全部webserver上下载配置:
---
- name: Fetch configuration from all webservers
hosts: webservers
tasks:
- name: Get config
get_url: dest=configs/{{ ansible_hostname }} force=yes
url=http://{{ ansible_hostname }}/diagnostic/config
delegate_to: localhost
当你委派给本机的时候,还能够使用更快捷的方法local_action,代码例如以下:
---
- name: Fetch configuration from all webservers
hosts: webservers
tasks:
- name: Get config
local_action: get_url dest=configs/{{ ansible_hostname
}}.cfg url=http://{{ ansible_hostname
}}/diagnostic/config
你能够委派任务给设备名单上随机机,下面是一些委托的场景任务:
- 在部署一台主机从一个负载平衡群集删除
- 在你做出改变,以一台主机删除相应的dns记录
- 当一个存储设备上创建iscsi当体积
- 当使用外部主机,以检测是否该网络出口正常时间