Ansible-playbook技巧

获取执行命令的输出 --Register


在刚开始使用 ansible-playbook 做应用程序部署的时候,因为在部署的过程中有使用到 command 或 shell 模块执行一些自定义的脚本,而且这些脚本都会有输出,用来表示是否执行正常或失败。如果像之前自己写脚本做应用程序部署的,这很好实现。但现在是用 Ansible 做,那么要怎么样做可以获取到 ansible playbook 中 command 模块的输出呢? Ansible 也提供的解决办法,这时我们就可以通过使用 register 关键字来实现,register 关键字可以存储指定命令的输出结果到一个自定义的变量中,我们通过访问这个自定义变量就可以获取到命令的输出结果。Register 的使用很方便,只需要在 task 声明 register 关键字,并自定义一个变量名就可以。如下:

- name: echo date 
  command: date 
  register: date_output 

- name: echo date_output 
  command: echo "30"
  when: date_output.stdout.split(' ')[2] == "30"

这里第 1 个 task 是执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行。这里要重点说下的,因为 register 获取到的输出内容都是字符串,而 ansible 又是 python 写的,你可以使用 python 字符串的方法对其做处理,比如本文中使用的 split,还可以使用 find 方法。个人觉得,真是非常灵活方便。

register 执行结果 1

这里由于条件匹配,两个 task 都执行了。然后把第 2 个 task 中的条件改动了下,使其不匹配,执行结果如下:

register 执行结果 2

这里第 2 个 task 条件不匹配,skipping 了。

Delegate_to( 任务委派功能 )


场景介绍:在对一组服务器 server_group1 执行操作过程中,需要在另外一台机器 A 上执行一个操作,比如在 A 服务器上添加一条 hosts 记录,这些操作必须要在一个 playbook 联动完成。也就是是说 A 服务器这个操作与 server_group1 组上的服务器有依赖关系。Ansible 默认只会在定义好的一组服务器上执行相同的操作,这个特性对于执行批处理是非常有用的。但如果在这过程中需要同时对另外 1 台机器执行操作时,就需要用到 Ansible 的任务委派功能(delegate_to)。使用 delegate_to 关键字可以委派任务到指定的机器上运行。在 playbook 的操作如下:

- name: add host record 
  shell: 'echo "192.168.1.100 test.xyz.com" >> /etc/hosts'

 - name: add host record to center server 
   shell: 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
   delegate_to: 192.168.1.1

任务委派功能还可以用于以下场景:

  • 在部署之前将一个主机从一个负载均衡集群中删除。
  • 当你要对一个主机做改变之前去掉相应 dns 的记录
  • 当在一个存储设备上创建 iscsi 卷的时候
  • 当使用外的主机来检测网络出口是否正常的时候

本地操作功能 --local_action


Ansible 默认只会对控制机器执行操作,但如果在这个过程中需要在 Ansible 本机执行操作呢?细心的读者可能已经想到了,可以使用 delegate_to( 任务委派 ) 功能呀。没错,是可以使用任务委派功能实现。不过除了任务委派之外,还可以使用另外一外功能实现,这就是 local_action 关键字。

- name: add host record to center server 
  local_action: shell 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'

当然您也可以使用 connection:local 方法,如下:

- name: add host record to center server 
  shell: 'echo "192.168.1.100 test.xyz.com " >> /etc/hosts'
  connection: local

这两个操作结果是一样的。

Check 模式


当以— check 参数来运行 ansible-playbook 时,将不会对远程的系统作出任何修改。相对的,任何带有检测功能的模块只要支持‘检测模式’将会报告它们会做出什么改变而不是直接进行改变。其他不支持检测模式的模块将即不响应也不提出相应的报告(事实上几乎所有主要核心模块都是支持‘检测模式’)。检测模式只是一种模拟。如果你的 playbook 是以先前命令的执行结果作为条件的话,那它可能作用就不明显了。但是在正式运行前,使用 check 模式做个语法检查也是不错的。

选择性执行 task-- Tag(标签)

您可能因为某些原因,会创建一个很大型的 playbook,但是你可能只想想运行其中特定部分的配置而无需要运行整个 playbook 。那么这时你可能需要用到 tag 功能。示例如下:

- name: yun install package 
  yum: name={{ item }} state=installed 
  with_items: 
    - httpd 
    - memcached 
  tags: 
    - packages 

 - name: configuration modity 
   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 “configuration”
tag 特性是一个不错的功能,但如果真的是要维护一个大型的 playbook,还是建议将 playbook 按功能或应用拆分成多个 playbook,然后再在主 playbook include 其他子 playbook,这样即既利于维护也方便管理

错误处理


Ansible 默认会检查命令和模块的返回状态,并进行相应的错误处理,默认是遇到错误就中断 playbook 的执行,这些默认行为都是可以改变的。

忽略错误

command 和 shell 模块执行的命令如果返回非零状态码则 ansible 判定这 2 个模块执行失败,可以通过 ignore_errors 忽略返回状态码(前提是要确定这 command 与 shell 执行错误不会影响后面 task 的执行)。如下:

- name: this will not be counted as a failure 
  command: /bin/false 
  ignore_errors: yes
自定义错误判定条件

命令不依赖返回状态码来判定是否执行失败,而是要查看命令返回内容来决定,比如返回内容中包括 failed 字符串,则判定为失败。示例如下:

- 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"

ansible 会自动判断模块执行状态,command、shell 及其它模块如果修改了远程主机状态则被判定为 change 状态,不过也可以自己决定达到 changed 状态的条件,示例如下:

- name: copy in nginx conf 
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf 

- name: validate nginx conf 
  shell: "/data/app/nginx/sbin/nginx -t"
  register: command_result 
  changed_when: command_result.stdout.find('successful')

命令返回中有“successful”字符串,则为 changed 状态,下面这个设定将永远也不会达到 changed 状态。

- name: validate nginx conf 
  shell: "/data/app/nginx/sbin/nginx -t"
  changed_when: false
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容