ansible special topics

一、加速模式运行playbook

accelerate

对于使用ansible 1.5 及以后版本的用户,加速模式只在如下状况下有用处:html

(A) 管理红帽企业版 Linux 6 或者更早的那些依然使用 paramiko 的版本 python

(B) 像在文档中描述的那样:没法在 TTYs 中使用 sudo.web

#只需在你的 play 中添加 accelerate: true 便可使用加速模式: ---

- hosts: all accelerate: true tasks: - name: some task command: echo {{ item }} with_items: - foo - bar - baz #若是你但愿改变 Ansible 用于加速模式的端口,你只需添加 accelerated_port 选项: ---

- hosts: all accelerate: true # default port is 5099 accelerate_port: 10000 #accelerate_port 选项也一样能经过指定环境变量 ACCELERATE_PORT 或者在你的 ansible.cfg 中配置: [accelerate] accelerate_port = 5099

二、异步操做和轮询

async
poll

async_status

默认状况下playbook中的任务执行时会一直保持链接,直到该任务在每一个节点都执行完毕.有时这是没必要要的,好比有些操做运行时间比SSH超时时间还要长.docker

解决该问题最简单的方式是一块儿执行它们,而后轮询直到任务执行完毕.shell

你也能够对执行时间很是长(有可能遭遇超时)的操做使用异步模式.json

为了异步启动一个任务,能够指定其最大超时时间以及轮询其状态的频率.vim

若是你没有为 poll 指定值,那么默认的轮询频率是10秒钟:安全

---

- hosts: all remote_user: root tasks: - name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec command: /bin/sleep 15 async: 45 poll: 5

async 并无默认值,若是你没有指定 async 关键字,那么任务会以同步的方式运行,这是Ansible的默认行为.服务器

另外,若是你不须要等待任务执行完毕,你能够指定 poll 值为0而启用 “启动并忽略”app

---

- hosts: all remote_user: root tasks: - name: simulate long running op, allow to run for 45 sec, fire and forget command: /bin/sleep 15 async: 45 poll: 0

对于要求排它锁的操做,若是你须要在其以后对同一资源执行其它任务,那么你不该该对该操做使用”启动并忽略”.好比yum事务.

--forks 参数值过大会更快的触发异步任务.也会加快轮询的效率.

 

当你想对 “启动并忽略” 作个变种,改成”启动并忽略,稍后再检查”,你可使用如下方式执行任务:

--- # Requires ansible 1.8+
- name: 'YUM - fire and forget task'
  yum: name=docker-io state=installed async: 1000 poll: 0 register: yum_sleeper - name: 'YUM - check on fire and forget task' async_status: jid={{ yum_sleeper.ansible_job_id }} register: job_result until: job_result.finished retries: 30

若是 async: 值过小,可能会致使 “稍后检查” 任务执行失败,由于 async_status:: 的临时状态文件还未被写入信息,而”稍后检查”任务就试图读取此文件.

三、检查模式运行playbook(dry run)

--check 
--diff
--limit

当以 --check 参数来运行 ansible-playbook 时,将不会对远程的系统做出任何更改.

相对的,任何带有检测功能的模块(这几乎包含了全部的主要核心模块,但这不要求全部的模块都需支持.) 只要支持 ‘检测模式’ 将会报告它们会作出什么改变而不是直接进行改变.其余不支持检测模式的模块将既不响应也不提出相应的报告.

检测模式只是一种模拟.若是你的playbook是以先前命令的执行结果做为条件的话,那它可能对你就没有什么大用处了. 可是对于基于一次一节点的基础配置管理的使用情形来讲是颇有用.

Example: ansible-playbook foo.yml --check

 

有时候你甚至会想在检测模式中执行一个任务.为了达到这样的效果, 你须要在相应的任务上使用 always_run 子句.跟 when 子句同样,它的值是一个 Jinja2 表达式. 在一个简单的例子中,布尔值也会表达为一个适当的 YAML 值.

Example: tasks: - name: this task is run even in check mode command: /something/to/run --even-in-check-mode always_run: yes

 

友情提示,带有 when 子句的任务会返回false,该任务将会被跳过,即便它还被添加了会返回true的 always_run 子句.

对 ansible-playbook 来讲 --diff 选项与 --check (详情参下)配合使用效果奇佳,不过它也能够单独使用.当提供了相应的标识后,当远程系统上任何模板文件的变化时,ansible-playbook CLI 将会报告文件上任何文本的变化 (或者,若是使用了 --check 参数,将报告会发生的变化.).由于 diff 特性会产生大量的输出结果,因此它在一次检测一个主机时使用为佳,如:

ansible-playbook foo.yml --check --diff --limit foo.example.com

四、滚动更新

serial

因为设计初衷是做为多用户,Anisible很擅长在某一个主机上表明另外一个作事,或者参考远程主机作一些本地工做.

这个特性对于架设连续实现某些设施或者无缝滚动升级,这里你可能会提到负载均衡或者监控系统.

更多的特性容许调试事情完成的顺序,和设置一批窗口,来肯定多少机器在一次中滚动更新.

默认来讲,Anisble 能够试图参考某一个play来并行操做全部主机.对于滚动更新案例,你可使用’‘serial’’ 关键词来定义Ansible在一个特定时间同时控制多少主机:

- name: test play hosts: webservers serial: 3

在上面的例子,若是咱们有100台主机,3 台主机定义在组’webservers’ 能够在下面3个主机开始以前彻底完成

这个’‘serial’’ 关键词在Ansible 1.8 之后能够被定义为百分数,用来定义每一次操做一个play中百分之多少主机:

- name: test play hosts: websevers serial: "30%"

若是主机数不能被passes数量整除,最后的pass将会包含提醒信息,无论多小的百分比,每一个pass的主机数必定会大于等于1.

默认来讲,Ansible 会持续执行,只要在一个组中还有主机没有宕机.

在有些状况下,例如以前提到的滚动更新,也许理想的状况是当一个失败数上限达到时,主动宕掉这个play.

为了达到这个目的,在 1.3版本中,你能够设置最大失败半分比:

- hosts: webservers max_fail_percentage: 30 serial: 10

在上面的例子中,若是在10个服务器中若是多余3个,其它的play就会主动宕掉.这个百分比必须被超过,不只仅是相等.

例如若是serial值呗设置为4,而且你但愿任务主动在2个系统失败时候放弃.那么这个百分比应该设置为49而不是50.

五、委任

delegate_to

local_action

若是你想参考其它主机来在一个主机上执行一个任务,咱们就可使用’delegate_to’关键词在你要执行的任务上.

这个对于把节点放在一个负载均衡池里面活着从里面移除很是理想. 这个选项也对处理窗口中断很是有用. 使用’serial’关键词来控制必定数量的主机也是一个好想法:

---

- hosts: webservers serial: 5 tasks: - name: take out of load balancer pool command: /usr/bin/take_out_of_pool {{ inventory_hostname }} delegate_to: 127.0.0.1

  - name: actual steps would go here yum: name=acme-web-stack state=latest - name: add back to load balancer pool command: /usr/bin/add_back_to_pool {{ inventory_hostname }} delegate_to: 127.0.0.1
--- # ... tasks: name: take out of load balancer pool local_action: command /usr/bin/take_out_of_pool {{ inventory_hostname }} # ... name: add back to load balancer pool local_action: command /usr/bin/add_back_to_pool {{ inventory_hostname }}

A common pattern is to use a local action to call ‘rsync’ to recursively copy files to the managed servers. Here is an example:

--- # ... tasks: - name: recursively copy files from management server to target local_action: command rsync -a /path/to/files {{ inventory_hostname }}:/path/to/target/

 

六、本地执行playbook

connection

在本地使用playbook有时候比ssh远程使用更加有用.能够经过把playbook放在crontab中,来确保一个系统的配置,能够颇有用.

在OS installer 中运行一个playbook也颇有用.例如Anaconda kickstart.

要想在本地运行一个play,能够直接设置”host:” 与 “hosts:127.0.0.1”, 而后使用下面的命令运行:

ansible-playbook playbook.yml --connection=local

或者,一个本地链接也能够做为一个单独的playbook play应用在playbook中, 即使playbook中其余的plays使用默认远程 链接以下:

- hosts: 127.0.0.1 connection: local

七、只运行一次任务

run_once

有时候你有这样的需求,在一个主机上面只执行一次一个任务.这样的配置能够配置”run_once”来实现:

--- # ... tasks: # ... - command: /opt/application/upgrade_db.py run_once: true # ...

这样能够添加在”delegat_to”选项对中来定义要执行的主机:

- command: /opt/application/upgrade_db.py run_once: true delegate_to: web01.example.org

当”run_once” 没有和”delegate_to”一块儿使用,这个任务将会被清单指定的第一个主机.

在一组被play制定主机.例如 webservers[0], 若是play指定为 “hosts: webservers”.

这个方法也很相似,虽然比使用条件更加简单粗暴,以下事例:

- command: /opt/application/upgrade_db.py when: inventory_hostname == webservers[0]

八、配置环境运行,如代理上网

environment

你彻底有可能遇到一些更新包须要经过proxy才能正常获取,或者甚至一部分包须要经过proxy升级而另一部分包则不须要经过proxy.

或者可能你的某个脚本须要调用某个环境变量才能正常运行.

Ansible 使用 ‘environment’ 关键字对于环境部署的配置很是简单容易,下面是一个使用案例:

- hosts: all remote_user: root tasks: - apt: name=cobbler state=installed environment: http_proxy: http://proxy.example.com:8080

environment 也能够被存储在变量中,像以下方式访问:

- hosts: all remote_user: root # here we make a variable named "proxy_env" that is a dictionary vars: proxy_env: http_proxy: http://proxy.example.com:8080
 tasks: - apt: name=cobbler state=installed environment: proxy_env

虽然上面只展现了 proxy 设置,但其实能够同时其实支持多个设置. 大部分合合乎逻辑的地方来定义一个环境变量均可以成为 group_vars 文件,示例以下:

--- # file: group_vars/boston ntp_server: ntp.bos.example.com backup: bak.bos.example.com proxy_env: http_proxy: http://proxy.bos.example.com:8080
  https_proxy: http://proxy.bos.example.com:8080

九、playbook中错误处理

ignore_errors

failed_when

fail

change_when

Ansible 一般默认会确保检测模块和命令的返回码.

有时一条命令会返回 0 但那不是报错.有时命令不会老是报告它 ‘改变’ 了远程系统.

本节描述了 如何将 Ansible 处理输出结果和错误处理的默认行为改变成你想要的.

一、忽略错误命令

一般状况下, 当出现失败时 Ansible 会中止在宿主机上执行.有时候,你会想要继续执行下去.为此 你须要像这样编写任务:

- name: this will not be counted as a failure command: /bin/false ignore_errors: yes

注意上面的系统仅仅处理那个特定的任务,因此当你在使用一个未定义的变量时, Ansible 仍然会报 错,须要使用者进行处理.

二、控制对失败的定义

假设一条命令的错误码毫无心义,只有它的输出结果能告诉是你什么出了问题,好比说字符串 “FAILED” 出 如今输出结果中.

在 Ansible 1.4及以后的版本中提供了以下的方式来指定这样的特殊行为:

- name: this command prints FAILED when it fails command: /usr/bin/example-command -x -y -z register: command_result failed_when: "'FAILED' in command_result.stderr"

三、覆写返回结果

当一个 shell或命令或其余模块运行时,它们每每都会在它们认为其影响机器状态时报告 “changed” 状态,

有时你能够经过返回码或是输出结果来知道它们其实并无作出任何更改.
你但愿覆写结果的“changed” 状态,使它不会出如今输出的报告或不会触发其余处理程序:
tasks: - shell: /usr/bin/billybass --mode="take me to the river" register: bass_result changed_when: "bass_result.rc != 2" # this will never report 'changed' status - shell: wall 'beep' changed_when: False

十、标签

tags

若是你有一个大型的 playbook,那可以只运行其中特定部分的配置而无需运行整个 playbook 将会颇有用.

plays 和 tasks 都因这个理由而支持 “tags”

tasks: - yum: name={{ item }} state=installed with_items: - httpd - memcached tags: - packages - template: src=templates/src.j2 dest=/etc/foo.conf tags: - configuration

若是你只想运行一个很是大的 playbook 中的 “configuration” 和 “packages”,你能够这样作:

ansible-playbook example.yml --tags "configuration,packages"

另外一方面,若是你只想执行 playbook 中某个特定任务 以外 的全部任务,你能够这样作:

ansible-playbook example.yml --skip-tags "notification"

你一样也能够对 roles 应用 tags:

roles: - { role: webserver, port: 5000, tags: [ 'web', 'foo' ] }

你一样也能够对基本的 include 语句使用 tag:

- include: foo.yml tags=web,foo

十一、从指定任务开始运行playbook,分步运行playbook

--start-at

--step

若是你想从指定的任务开始执行playbook,可使用``–start-at``选项:

ansible-playbook playbook.yml --start-at="install packages"

以上命令就会在名为”install packages”的任务开始执行你的playbook.

咱们也能够经过``–step``选项来交互式的执行playbook:

ansible-playbook playbook.yml --step

这样ansible在每一个任务前会自动中止,并询问是否应该执行该任务.

好比你有个名为``configure ssh``的任务,playbook执行到这里会中止并询问:

Perform task: configure ssh (y/n/c):

“y”回答会执行该任务,”n”回答会跳过该任务,而”c”回答则会继续执行剩余的全部任务而再也不询问你.

十二、vault加密文件

ansible-vault

--ask-vault-pass

--vault-password-file

Ansible 1.5的新版本中, “Vault” 做为 ansible 的一项新功能可将例如passwords,keys等敏感数据文件进行加密,

而非存放在明文的 playbooks 或 roles 中. 这些 vault 文件能够分散存放,也能够集中存放.

经过`ansible-vault` 来编辑文件,常常用到的命令如 –ask-vault-pass , –vault-password-file .

你能够在 ansible.cfg 中定义密码文件所在位置,这个选项就不须要在命令行中指定标志了.

Vault能够加密些什么

vault 能够加密任何 Ansible 使用的结构化数据文件. 甚至能够包括:

“group_vars/” 或 “host_vars/” inventory 变量,

“include_vars” 或 “vars_files” 加载的变量,

经过 ansible-playbook 命令行使用 “-e @file.yml” 或 “-e @file.json” 命令传输的变量文件,

role变量,

全部默认的变量均可以被 vault 加密.

由于 Ansible tasks, handlers等都是数据文件, 全部的这些都可以被 vault 加密. 若是你不喜欢你使用的变量被泄漏,你能够将整个 task 文件部分加密.

不过,这个工做量比较大并且可能给你的同事带来不便哦 !

建立加密文件

执行以下命令,建立加密文件:

ansible-vault create foo.yml

首先你将被提示输出密码, 通过Vault加密过的文件如需查看需同时输入密码后才能进行.

提供密码后, 工具将加载你定义的 $EDITOR 的编辑工具默认是 vim, 一旦你关闭了编辑会话框,生成后的文件将会是加密文件.

默认加密方式是 AES (基于共享密钥)

编辑加密文件

编辑加密文件,使用 ansible-vault edit . 该命令会先加密文件为临时文件并容许你编辑这个文件,当完成编辑后会保存回你所命名的文件并删除临时文件:

ansible-vault edit foo.yml

密钥更新

若是你但愿变动密码,使用以下 命令:

ansible-vault rekey foo.yml bar.yml baz.yml

如上命令能够同时批量修改多个文件的组织密码并从新设置新密码.

加密普通文件

若是你但愿加密一个已经存在的文件,使用 ansible-vault encrypt . 该命令也可同时批量操做多个文件:

ansible-vault encrypt foo.yml bar.yml baz.yml=

解密已加密文件

若是不但愿继续加密一个已经加密过的文件,经过 ansible-vault decrypt 你能够永久解密. 命令将解密并保存到硬盘上,这样你不用再使用 ansible-vault edit 来编辑文件了:

ansible-vault decrypt foo.yml bar.yml baz.yml

查阅已加密文件

Available since Ansible 1.8

若是你不但愿经过编辑的方式来查看文件, ansible-vault view 能够知足你的须要:

ansible-vault view foo.yml bar.yml baz.yml

在Vault下运行Playbook

执行 vault 加密后的playbook文件,最少须要提交以下两个标志之一. 交互式的指定 vault 的密码文件:

ansible-playbook site.yml --ask-vault-pass

该提示被用来解密(仅在内存中)任何 vault 加密访问过的文件. 目前这些文件中全部的指令请求将被使用相同的密码加密.

另外,密码也能够定义在一个文件或者一个脚本中,可是须要 Ansible 1.7 以上的版本才能支持.

当使用该功能时,必定要确认密码文件的权限是安全的,以确保没有人能够随意访问或者变动密码文件:

ansible-playbook site.yml --vault-password-file ~/.vault_pass.txt ansible-playbook site.yml --vault-password-file ~/.vault_pass.py

密码存储一行一个

若是你使用的是脚本而不是普通文件,确保脚本是可执行的,这样密码能够输出至标准设备.若是你的脚本须要提示输入数据,那提示能够被发送到标准错误.

若是你是从持续集成系统(例如Jenkins)中使用 Ansible 的话上面的这种状况你会用的到.

(–vault-password-file 参数能够在 Ansible-Pull(拉取配置而非推送配置) 命令中被使用,尽管这将须要分发keys到对应的节点上,

因此 ,了解这些隐性问题后 – vault 更倾向使用 push 方式)

相关文章
相关标签/搜索