自动化运维工具Ansible任务控制

大道之行,天下为公。这篇文章主要讲述自动化运维工具Ansible任务控制相关的知识,希望能为你提供帮助。
一、 Ansible 任务控制基本介绍准备配置文件

[root@localhost home]# vim www.webservers.conf

server
listen 80;
server_name www.webservers.com;
root /usr/share/nginx/html;
access_log /var/log/nginx/www.webservers-access_log main;
error_log/var/log/nginx/www.webservers.com-error_log;

add_header Access-Control-Allow-Origin *;

location ~ .*\\.(gif|jpg|jpeg|png|bmp|swf)$
expires1d;


location ~ .*\\.(js|css)?$
expires1d;


[root@localhost home]# vim nginx.conf
userwww;
worker_processes 2;

error_log/var/log/nginx/error.log;
pid/var/run/nginx.pid;

events
worker_connections1024;


http
include/etc/nginx/mime.types;
default_typeapplication/octet-stream;

log_formatmain$remote_addr - $remote_user [$time_local] "$request"
$status $body_bytes_sent "$http_referer"
"$http_user_agent" "$http_x_forwarded_for";

sendfileon;
tcp_nopushon;

keepalive_timeout0;

gzip on;
gzip_min_length1k;
gzip_buffers8 64k;
gzip_http_version 1.0;
gzip_comp_level 5;
gzip_typestext/plain application/x-javascript text/css application/json application/xml application/x-shockwave-flash application/javascript image/svg+xml image/x-icon;
gzip_vary on;

include /etc/nginx/conf.d/*.conf;



  • 任务控制类似于编程语言中的if ... 、for ... 等逻辑控制语句。
  • 在下面的PlayBook中,我们创建了 tomcat、www 和 mysql 三个用户。
  • 安装了Nginx 软件包、并同时更新了 Nginx 主配置文件和虚拟主机配置文件,最后让Nginx 服务处于启动状态。
[root@localhost home]# vim myplaybook5.yml

---
- name: task control playbook example
hosts: webservers
gather_facts: no
remote_user: root
tasks:
- name: create tomcat user
user: name=tomacat state=present
- name: create mysql user
user: name=mysql state=present
- name: yum nginx webserver
yum: name=nginx state=present
- name: update nginx main config
copy: src=https://www.songbingjia.com/android/nginx.conf dest=/etc/nginx/nginx.conf
- name: add virtualhost config
copy: src=https://www.songbingjia.com/android/www.webservers.conf dest=/etc/nginx/conf.d/
- name: start nginx server
service: name=nginx state=started
...

不足:
1. Nginx启动逻辑欠缺考虑。若Nginx的配置文件语法错误则会导致启动Nginx失败,以至于PlayBook执行失败。
2. 批量创建用户,通过指令的罗列过于死板。如果再创建若干个用户,将难以收场。


  二、条件判断解决第一个问题
Nginx启动逻辑欠缺考虑。
若Nginx的配置文件语法错误则会导致启动Nginx失败,以至于PlayBook执行失败。
如果我们能够在启动之前去对Nginx的配置文件语法做正确性的校验,只有当校验通过的时候我们才去启动或者重启Nginx;否则则跳过启动Nginx的过程。这样就会避免Nginx 配置文件语法问题而导致的无法启动Nginx的风险。 
Nginx 语法校验
- name: check nginx syntax
shell: /usr/sbin/nginx -t

获取Task任务结果
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax

通过debug模块去确认返回结果的数据结构
通过debug 模块,打印出来的返回结果。 当nginxsyntax.rc 为 0 时语法校验正确。
- name: print nginx syntax result
debug: var=nginxsyntax

改进后的PlayBook
---
- name: task control playbook example
hosts: webservers
gather_facts: no
remote_user: root
tasks:
- name: create tomcat user
user: name=tomacat state=present
- name: create mysql user
user: name=mysql state=present
- name: yum nginx webserver
yum: name=nginx state=present
- name: update nginx main config
copy: src=https://www.songbingjia.com/android/nginx.conf dest=/etc/nginx/nginx.conf
- name: add virtualhost config
copy: src=https://www.songbingjia.com/android/www.webservers.conf dest=/etc/nginx/conf.d/
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
- name: print nginx syntax
debug: var=nginxsyntax
- name: start nginx server
service: name=nginx state=started
when: nginxsyntax.rc == 0
...

rc == 0 判断是否成功
另外 `when` 支持如下运算符:
==
!=
> > =
< < =
is defined
is not defined
true
false
支持逻辑运算符: and or



三、循环控制解决第二个问题
批量创建用户,通过指令的罗列过于死板。如果再创建若干个用户,将难以收场
如果在创建用户时,抛开PlayBook的实现不说, 单纯的使用shell去批量的创建一些用户写法
#! /bin/bash
createuser="tomcat mysql www"
for i in `echo $createuser`
do
useradd $i
done

在PlayBook中使用`with_items` 去实现循环控制,且循环时的中间变量(上面shell循环中的 `$i` 变量)只能是关键字 `item` ,而不能随意自定义。
[root@localhost home]# vim myplaybook5.yml

---
- name: task control playbook example
hosts: webservers
gather_facts: no
remote_user: root
vars:
createuser:
- www
- tomcat
- mysql
tasks:
- name: create user
user: name=item state=present
with_items: " createuser"
- name: yum nginx webserver
yum: name=nginx state=present
- name: update nginx main config
copy: src=https://www.songbingjia.com/android/nginx.conf dest=/etc/nginx/nginx.conf
- name: add virtualhost config
copy: src=https://www.songbingjia.com/android/www.webservers.conf dest=/etc/nginx/conf.d/
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
- name: print nginx syntax
debug: var=nginxsyntax
- name: start nginx server
service: name=nginx state=started
when: nginxsyntax.rc == 0
...



四、Tags属性
  • 我们可以通过Play中的tags 属性,去解决目前PlayBook变更而导致的扩大变更范围和变更风险的问题。
  • 在改进的PlayBook中,针对文件发布TASK 任务
  • "update nginx main config" 和 "add virtualhost config"
  • 新增了属性 tags ,属性值为updateconfig。
  • 另外我们新增"reload nginx server" TASK任务。当配置文件更新后,去reload Nginx 服务。
  • 那重新加载需要依赖于 Nginx 服务是已经启动状态。所以,还需要进一步通过判断 Nngix 的 pid 文件存在,才证明 Nginx 服务本身是启动中,启动中才可以 reload Nginx 服务。
  • 判断一个文件是否存在使用 `stat` 模块
- name: check nginx running
stat: path=/var/run/nginx.pid
register: nginxrunning

改进后的PlayBook
[root@localhost home]# vim myplaybook5.yml
---
- name: task control playbook example
hosts: webservers
gather_facts: no
remote_user: root
vars:
createuser:
- www
- tomcat
- mysql
tasks:
- name: create user
user: name=item state=present
with_items: " createuser"
- name: yum nginx webserver
yum: name=nginx state=present
- name: update nginx main config
copy: src=https://www.songbingjia.com/android/nginx.conf dest=/etc/nginx/nginx.conf
tags: updateconfig
- name: add virtualhost config
copy: src=https://www.songbingjia.com/android/www.webservers.conf dest=/etc/nginx/conf.d/
tags: updateconfig
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
tags: updateconfig
- name: check nginxrunning
stat: path=/var/run/nginx.pid//运行时会产生pid文件
register: nginxrunning
tags: updateconfig
- name: print nginx syntax//输出信息定义变量
debug: var=nginxsyntax
- name: print nginx syntax//输出信息定义变量
debug: var=nginxrunning
- name: reload nginx server//配置文件正确且检测到pid文件不再重启
service: name=nginx state=reloaded
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true
tags: updateconfig
- name: start nginx server//配置文件正确且检测不到pid文件执行启动
service: name=nginx state=started
when:
- nginxsyntax.rc == 0
- nginxrunning.stat.exists == false
tags: updateconfig

修改nginx.conf后

执行了重启



指定tags 去执行PlayBook
执行时一定要指定tags,这样再执行的过程中只会执行task 任务上打上tag 标记为 updateconfig 的任务
ansible-playbook -i hosts site.yml -t updateconfig


五、Handlers 属性观察当前的 Playbook,不能发现,当我的配置文件没有发生变化时,每次依然都会去触发TASK "reload nginx server"。
如何能做到只有配置文件发生变化的时候才去触发TASK "reload nginx server",这样的处理才是最完美的实现。此时可以使用 handlers 属性。
改进后的PlayBook
[root@localhost home]# vim myplaybook5.yml
---
- name: task control playbook example
hosts: webservers
gather_facts: no
remote_user: root
vars:
createuser:
- www
- tomcat
- mysql
tasks:
- name: create user
user: name=item state=present
with_items: " createuser"
- name: yum nginx webserver
yum: name=nginx state=present
- name: update nginx main config
copy: src=https://www.songbingjia.com/android/nginx.conf dest=/etc/nginx/nginx.conf
tags: updateconfig
notify: reload nginx server//文件发生变化调用reload nginx server任务
- name: add virtualhost config
copy: src=https://www.songbingjia.com/android/www.webservers.conf dest=/etc/nginx/conf.d/
tags: updateconfig
notify: reload nginx server//文件发生变化调用reload nginx server任务
- name: check nginx syntax
shell: /usr/sbin/nginx -t
register: nginxsyntax
tags: updateconfig
- name: check nginxrunning
stat: path=/var/run/nginx.pid
register: nginxrunning
tags: updateconfig
- name: start nginx server
service: name=nginx state=started
when:
- nginxsyntax.rc == 0
- nginxrunning.stat.exists == false
handlers://将重启任务加入到handlers中
- name: reload nginx server
service: name=nginx state=reloaded
when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true

【自动化运维工具Ansible任务控制】在改进的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" 的任务。
notify属性设置的值,一定要确保能和handlers中的TASK 名称对应上
验证
首次执行,若配置文件没有发生变化,没有触发handlers 中TASK任务
[root@localhost home]# ansible-playbook -i hosts myplaybook5.yml -t updateconfig

人为对Nginx 配置文件稍作修改,此时再执行,触发了handlers 中的TASK任务
[root@localhost home]# ansible-playbook -i hosts myplaybook5.yml -t updateconfig





    推荐阅读