Ansible之Playbook的任务控制

news/发布时间2024/7/21 4:22:05

一)Ansible 任务控制基本介绍

这⾥主要来介绍PlayBook中的任务控制。
任务控制类似于编程语⾔中的if … 、for … 等逻辑控制语句。
这⾥我们给出⼀个实际场景应⽤案例去说明在PlayBook中,任务控制如何应⽤。
在下⾯的PlayBook中,我们创建了 tomcat、www 和 mysql 三个⽤户。 安装了Nginx 软件包、并同时更新了 Nginx 主配置⽂件和虚拟主机配置⽂件,最后让Nginx 服务处于启动状态。
整个PlayBook从语法上没有任何问题,但从逻辑和写法上仍然有⼀些地⽅需要我们去注意及优化:

  1. Nginx启动逻辑⽋缺考虑。若Nginx的配置⽂件语法错误则会导致启动Nginx失败,以⾄于PlayBook执⾏失败。
  2. 批量创建⽤户,通过指令的罗列过于死板。如果再创建若⼲个⽤户,将难以收场。
---
- name: task control playbook examplehosts: webserverstasks:- name: create tomcat useruser: name=tomcat state=presentname: create www useruser: name=www state=present- name: create mysql useruser: name=mysql state=present- name: yum nginx webserveryum: name=nginx state=present- name: update nginx main configcopy: src=nginx.conf dest=/etc/nginx/- name: add virtualhost configcopy: src=www.qfedu.com.confdest=/etc/nginx/conf.d/- name: start nginx serverservice: name=nginx state=started

二)条件判断

解决第一个问题:Nginx启动逻辑⽋缺考虑。 若Nginx的配置⽂件语法错误则会导致启动Nginx失败,以⾄于PlayBook执⾏失败。
如果我们能够在启动之前去对Nginx的配置⽂件语法做正确性的校验,只有当校验通过的时候我们才去启动或者重启Nginx;否则则跳过启动Nginx的过程。这样就会避免Nginx 配置⽂件语法问题⽽导致的⽆法启动Nginx的⻛险。
nginx语法校验:

- name: check nginx syntaxshell: /usr/sbin/nginx -t

那如何将Nginx语法检查的TASK同Nginx启动的TASK关联起来呢?
如果我们能够获得语法检查的TASK的结果,根据这个结果去判断“启动NGINX的TASK”是否执⾏,这将是⼀个很好的⽅案。 如何和获取到语法检查TASK的结果呢? 此时就可以使⽤之前学到的 Ansible中的注册变量:
获取Task任务结果:

- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntax

此时有可能还有疑问,获取到任务结果后,但是结果⾥⾯的内容是个什么样⼦, 我该根据内容在后续的PlayBook中怎样使用
通过debug模块去确认返回结果的数据结构:

- name: print nginx syntax resultdebug: var=nginxsyntax

通过debug模块,打印出来返回结果。那么在变量nginxsyntax的rc为0时语法校验正确。
通过条件判断(when)指令去使用语法校验的结果:

- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntax
- name: print nginx syntaxdebug: var=nginxsyntax- name: start nginx serverservice: name=nginx state=startedwhen: nginxsyntax.rc == 0

改进后的PlayBook:

---
- name: task control playbook examplehosts: webserversgather_facts: notasks:- name: create tomcat useruser: name=tomcat state=present- name: create www useruser: name=www state=present- name: create mysql useruser: name=mysql state=present- name: yum nginx webserveryum: name=nginx state=present- name: update nginx main configcopy: src=nginx.conf dest=/etc/nginx/- name: add virtualhost configcopy: src=www.qfedu.com.confdest=/etc/nginx/conf.d/- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntax- name: print nginx syntaxdebug: var=nginxsyntax- name: start nginx serverservice: name=nginx state=startedwhen: nginxsyntax.rc == 0

以上的逻辑,只要语法检查通过都会去执⾏ "start nginx server"这个TASK。 在这个问题的解决⾥,我们学习了when 条件判断和注册变量的结合使⽤。学习了when条件判断中是可以⽀持复杂逻辑的。⽐如现在⽤到的逻辑运算符 and。
另外 when ⽀持如下运算符:

==
!=
> >=
< <=
is defined
is not defined
true
false
#⽀持逻辑运算符: 
and or

三)循环控制

解决第二个问题:批量创建⽤户,通过指令的罗列过于死板。如果再创建若⼲个⽤户,将难以收场。
那么如果在创建⽤户时,抛开PlayBook的实现不说, 单纯的使⽤shell去批量的创建⼀些⽤户。通常会怎么写呢?

#! /bin/bash
createuser="tomcat mysql www"
for i in `echo $createuser`
douseradd $i
done

那么如果PlayBook中也存在这样的循环控制,我们也可以像写shell⼀样简单的去完成多⽤户创建⼯作。
在PlayBook中使⽤with_items 去实现循环控制,且循环时的中间变量(上⾯shell循环中的 $i 变量)只能是关键字 item ,⽽不能随意⾃定义。
在上⾯的基础上,改进的PlayBook
在这⾥使⽤定义了剧本变量 createuser(⼀个列表) ,然后通过with_items 循环遍历变量这个变量来达到创建⽤户的⽬的。

- name: variable playbook examplehosts: webserversgather_facts: novars:createuser:- tomcat- www- mysqltasks:- name: create useruser: name={{ item }} state=presentwith_items: "{{ createuser }}"- name: yum nginx webserveryum: name=nginx state=present- name: update nginx main configcopy: src=nginx.conf dest=/etc/nginx/- name: add virtualhost configcopy: src=www.qfedu.com.confdest=/etc/nginx/conf.d/- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntax- name: print nginx syntaxdebug: var=nginxsyntax- name: start nginx serverservice: name=nginx state=startedwhen: nginxsyntax.rc == 0

解决了以上问题,整个PlayBook已经有了很⼤的改进。
在这里给大家一个关于遍历的新版本的循环playbook实验:

- name: loop itemhosts: allgather_facts: novars:some_list:- "a"- "b"- "c"num_list:- 1- 2- 3- 5tasks:- name: show itemdebug:var: "{{ item }}"loop: "{{ some_list }}"
- name: show item when item > 3debug:var: "{{ item }}"loop: "{{ num_list }}"when: item > 3

image.png

四)Tags属性

考虑这样⼀个情况:
若更新了Nginx 的配置⽂件后,我们需要通过PlayBook将新的配置发布到⽣产服务器上,然后再重新加载我们的Nginx 服务。但以现在的PlayBook来说,每次更改Nginx 配置⽂件后虽然可以通过它发布到⽣产,但整个PlayBook都要执⾏⼀次,这样⽆形中扩⼤了变更范围和
变更⻛险。
Tags 属性就可以解决这个问题。
我们可以通过Play中的tags 属性,去解决⽬前PlayBook变更⽽导致的扩⼤变更范围和变更⻛险的问题。
在改进的PlayBook中,针对⽂件发布TASK 任务:
“update nginx main config" 和 “add virtualhost config”。
新增了属性 tags ,属性值为updateconfig。
新增"reload nginx server" TASK任务。当配置⽂件更新后,去reload Nginx 服务。
判断⼀个⽂件是否存在使⽤ stat 模块:

- name: check nginx runningstat: path=/var/run/nginx.pidregister: nginxrunning

观察结果,会发现 nginxrunning.stat.exists 的值是 true 就表示启动状态,是 false 就是关闭状态。
接下来下来就可以依据这个结果,来决定是否重新加载 Nginx 服务。
改进后的Playbook:

- name: tags playbook examplehosts: webserversgather_facts: novars:createuser:- tomcat- www- mysqltasks:- name: create useruser: name={{ item }} state=presentwith_items: "{{ createuser }}"- name: yum nginx webserveryum: name=nginx state=present- name: update nginx main configcopy: src=nginx.conf dest=/etc/nginx/tags: updateconfig- name: add virtualhost configcopy: src=www.qfedu.com.confdest=/etc/nginx/conf.d/tags: updateconfig- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntaxtags: updateconfig- name: check nginx runningstat: path=/var/run/nginx.pidregister: nginxrunningtags: updateconfig- name: print nginx syntaxdebug: var=nginxsyntax- name: print nginx syntaxdebug: var=nginxrunning- name: reload nginx serverservice: name=nginx state=startedwhen: nginxsyntax.rc == 0 andnginxrunning.stat.exists == truetags: updateconfig- name: start nginx serverservice: name=nginx state=startedwhen:- nginxsyntax.rc == 0- nginxrunning.stat.exists == falsetags: updateconfig

执⾏时⼀定要指定tags,这样在执⾏的过程中只会执⾏task 任务上打上tag 标记为 updateconfig 的任务

ansible-playbook -i hosts site.yml -t updateconfig

五)Handlers属性

观察当前的 Playbook,不能发现,当我的配置⽂件没有发⽣变化时,每次依然都会去触发TASK “reload nginx server”。
如何能做到只有配置⽂件发⽣变化的时候才去触发TASK “reload nginx server”,这样的处理才是最完美的实现。此时可以使⽤handlers 属性。
改进的Playbook:

- name: handlers playbook examplehosts: webserversgather_facts: novars:createuser:- tomcat- www- mysqltasks:- name: create useruser: name={{ item }} state=presentwith_items: "{{ createuser }}"- name: yum nginx webserveryum: name=nginx state=present- name: update nginx main configcopy: src=nginx.conf dest=/etc/nginx/tags: updateconfignotify: reload nginx server- name: add virtualhost configcopy: src=www.qfedu.com.confdest=/etc/nginx/conf.d/tags: updateconfignotify: reload nginx server- name: check nginx syntaxshell: /usr/sbin/nginx -tregister: nginxsyntaxtags: updateconfig- name: check nginx runningstat: path=/var/run/nginx.pidregister: nginxrunningtags: updateconfig- name: start nginx serverservice: name=nginx state=startedwhen:- nginxsyntax.rc == 0- nginxrunning.stat.exists == falsehandlers:- name: reload nginx serverservice: name=nginx state=reloadedwhen:- nginxsyntax.rc == 0- nginxrunning.stat.exists == true

在改进的PlayBook中,我们针对⽂件发布TASK 任务 “update nginx main config” 和 “add virtualhost config” 增加了新属性 notify, 值为 “reload nginx server”。
它的意思是说,针对这两个⽂件发布的TASK,设置⼀个通知机制,当Ansible 认为⽂件的内容发⽣了变化(⽂件MD5发⽣变化了),它就会发送⼀个通知信号,通知 handlers 中的某⼀个任务。具体发送到handlers中的哪个任务,由notify 的值"reload nginx server"决定。通知发出后handlers 会根据发送的通知,在handlers中相关的任务中寻找名称为"reload nginx server" 的任务。
当发现存在这样名字的TASK,就会执⾏它。若没有找到,则什么也不做。若我们要实现这样的机制,千万要注意notify属性设置的值,⼀定要确保能和handlers中的TASK 名称对应上。
⾸次执⾏,若配置⽂件没有发⽣变化,可以发现根本就没有触发handlers 中TASK任务

ansible-playbook -i hosts site.yml -t updateconfig

⼈为对Nginx 配置⽂件稍作修改,只要MD5校验值发⽣变化即
可。此时再执⾏,发现触发了handlers 中的TASK任务

 ansible-playbook -i hosts site.yml -t updateconfig 1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.shwantai.cn/a/58855278.html

如若内容造成侵权/违法违规/事实不符,请联系万泰站长网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

9.18号作业

完善登录框 点击登录按钮后&#xff0c;判断账号&#xff08;admin&#xff09;和密码&#xff08;123456&#xff09;是否一致&#xff0c;如果匹配失败&#xff0c;则弹出错误对话框&#xff0c;文本内容“账号密码不匹配&#xff0c;是否重新登录”&#xff0c;给定两个按钮…

练习敲代码速度

2023年9月18日&#xff0c;周一晚上 今晚不想学习&#xff0c;但又不想玩游戏&#xff0c;于是找了一些练习敲代码的网站来玩玩&#xff0c;顺便练习一下敲代码的速度 目录 参考资料个人推荐第一个 第二个第三个 参考资料 电脑打字慢&#xff0c;有哪些比较好的练打字软件&a…

基于虚拟仿真技术的汽车燃油泵控制

在当前激烈的竞争环境下&#xff0c;汽车行业正在加速产业和技术更迭&#xff0c;整车厂对大型ECU嵌入式控制系统和软件的需求迫在眉睫。 然而&#xff0c;复杂而庞大的汽车系统往往由多个物理系统组成&#xff0c;系统所对应的模型都需要在不同的领域实现&#xff1a;发动机、…

【C++】构造函数初始化列表 ③ ( 构造函数 的 初始化列表 中 为 const 成员变量初始化 )

文章目录 一、构造函数 的 初始化列表 中 为 const 成员变量初始化1、初始化 const 常量成员2、错误代码示例 - 没有初始化常量成员3、正确代码示例 - 在初始化列表中初始化常量成员4、完整代码示例 构造函数初始化列表 总结 : 初始化列表 可以 为 类的 成员变量 提供初始值 ;…

http概念

概念&#xff1a;HTTP&#xff0c;hyper text transfer protocol&#xff0c;超文本传输协议&#xff0c;规定了浏览器和服务器之间数据传输的规则。 特点&#xff1a; 1.基于TCP协议&#xff1a;面向连接&#xff0c;安全。 2.基于请求-响应模型的&#xff1a;一次请求对应一…

laravel框架 - 事件与监听器

一&#xff0c;绑定事件与监听器 在app\Providers下的EventServiceProvider.php中添加我们定义的事件与监听器 protected $listen [Registered::class > [SendEmailVerificationNotification::class,],App\ebvent\RegisterMessage>[//事件App\listeners\SendMessage//监…