Ansible之Playbook的任务控制

这篇具有很好参考价值的文章主要介绍了Ansible之Playbook的任务控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

⼀、 Ansible 任务控制基本介绍

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

  • Nginx启动逻辑⽋缺考虑。若Nginx的配置⽂件语法错误则会导致启动Nginx失败,以⾄于PlayBook执⾏失败。
  • 批量创建⽤户,通过指令的罗列过于死板。如果再创建若⼲个⽤户,将难以收场。

代码如下:

---
- name: task control playbook example
 hosts: webservers
 tasks:
 - name: create tomcat user
   user: name=tomcat state=present
 
 - name: create www user
   user: name=www 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=nginx.conf dest=/etc/nginx/
 
 - name: add virtualhost config
   copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
 
 - name: start nginx server
   service: name=nginx state=started

准备工作:

cat nginx.conf

user www;
worker_processes 2;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
 worker_connections 1024;
}
http {
 include /etc/nginx/mime.types;
 default_type application/octet-stream;
log_format main '$remote_addr - $remote_user
[$time_local] "$request" '
 '$status $body_bytes_sent
"$http_referer" '
 '"$http_user_agent"
"$http_x_forwarded_for"';
 sendfile on;
 tcp_nopush on;
 keepalive_timeout 0;
 gzip on;
 gzip_min_length 1k;
 gzip_buffers 8 64k;
 gzip_http_version 1.0;
 gzip_comp_level 5;
 gzip_types text/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;
}
cat www.qfedu.com.conf

server {
 listen 80;
 server_name www.qfedu.com;
 root /usr/share/nginx/html;
 access_log /var/log/nginx/www.qfedu.comaccess_log main;
error_log /var/log/nginx/www.qfedu.comerror_log;
 add_header Access-Control-Allow-Origin *;
 location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ {
 expires 1d;
 }
 location ~ .*\.(js|css)?$ {
 expires 1d;
 }
}
⼆、条件判断
解决第⼀个问题

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

Nginx 语法校验
- name: check nginx syntax
 shell: /usr/sbin/nginx -t

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

获取Task任务结果
- name: check nginx syntax
 shell: /usr/sbin/nginx -t
 register: nginxsyntax
通过debug模块去确认返回结果的数据结构

此时有可能还有疑问,我获取到任务结果,但是结果⾥⾯的内容是个什么样⼦, 我如何根据内容在后续的PlayBook中使⽤呢?

- name: print nginx syntax result
 debug: var=nginxsyntax

通过debug 模块,打印出来的返回结果。 当nginxsyntax.rc 为 0时语法校验正确。

"nginxsyntax": {
 "changed": true,
 "cmd": "/usr/sbin/nginx -t",
 "delta": "0:00:00.012045",
 "end": "2017-08-12 20:19:04.650718",
 "rc": 0,
 "start": "2017-08-12 20:19:04.638673",
 "stderr": "nginx: the configuration file
/etc/nginx/nginx.conf syntax is ok\nnginx:
configuration file /etc/nginx/nginx.conf test is
successful",
"stderr_lines": [
 "nginx: the configuration file
/etc/nginx/nginx.conf syntax is ok",
 "nginx: configuration file
/etc/nginx/nginx.conf test is successful"
 ],
 "stdout": "",
 "stdout_lines": []
 }
通过条件判断(when) 指令去使⽤语法校验的结果
- 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
改进后的PlayBook
---
- name: task control playbook example
 hosts: webservers
 gather_facts: no
 tasks:
  - name: create tomcat user
    user: name=tomcat state=present
  
  - name: create www user
    user: name=www 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=nginx.conf dest=/etc/nginx/
  
  - name: add virtualhost config
    copy: src=www.qfedu.com.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
总结

以上的逻辑,只要语法检查通过都会去执⾏ "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`
do
 useradd $i
done

那么如果PlayBook中也存在这样的循环控制,我们也可以像写shell⼀样简单的去完成多⽤户创建⼯作。
在PlayBook中使⽤with_items 去实现循环控制,且循环时的中间变量(上⾯shell循环中的 $i 变量)只能是关键字 item ,⽽不能随意⾃定义。

在上⾯的基础上,改进的PlayBook

在这⾥使⽤定义了剧本变量 createuser(⼀个列表) ,然后通过with_items 循环遍历变量这个变量来达到创建⽤户的⽬的。

- name: variable playbook example
 hosts: webservers
 gather_facts: no
 vars:
   createuser:
    - tomcat
    - www
    - 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=nginx.conf dest=/etc/nginx/
 
   - name: add virtualhost config
     copy: src=www.qfedu.com.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

解决了以上问题,整个PlayBook已经有了很⼤的改进。

新版本循环
- name: loop item
  hosts: all
  gather_facts: no
  vars:
    some_list:
     - "a"
     - "b"
     - "c"
    num_list:
     - 1
     - 2
     - 3
     - 5
 tasks:
 - name: show item
   debug:
     var: "{{ item }}"
   loop: "{{ some_list }}"
 
- name: show item when item > 3
  debug:
   var: "{{ item }}"
  loop: "{{ num_list }}"
  when: item > 3

考虑这样⼀个情况:
若更新了Nginx 的配置⽂件后,我们需要通过PlayBook将新的配置发布到⽣产服务器上,然后再重新加载我们的Nginx 服务。但以现在的PlayBook来说,每次更改Nginx 配置⽂件后虽然可以通过它发布到⽣产,但整个PlayBook都要执⾏⼀次,这样⽆形中扩⼤了变更范围和变更⻛险。
下⾯的 Tags 属性就可以解决这个问题。

四、Tags属性

我们可以通过Play中的tags 属性,去解决⽬前PlayBook变更⽽导致的扩⼤变更范围和变更⻛险的问题。
在改进的PlayBook中,针对⽂件发布TASK 任务
“update nginx main confifig” 和 “add virtualhost confifig”
新增了属性 tags ,属性值为updateconfifig。
另外我们新增"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

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

改进PlayBook
- name: tags playbook example
  hosts: webservers
  gather_facts: no
  vars:
   createuser:
     - tomcat
     - www
     - 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=nginx.conf dest=/etc/nginx/
       tags: updateconfig
 
     - name: add virtualhost config
       copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
       tags: updateconfig
 
     - name: check nginx syntax
       shell: /usr/sbin/nginx -t
       register: nginxsyntax
       tags: updateconfig
 
     - name: check nginx running
       stat: path=/var/run/nginx.pid
       register: nginxrunning
       tags: updateconfig
 
     - name: print nginx syntax
       debug: var=nginxsyntax
 
     - name: print nginx syntax
       debug: var=nginxrunning
 
     - name: reload nginx server
       service: name=nginx state=started
       when: nginxsyntax.rc == 0 and
             nginxrunning.stat.exists == true
      tags: updateconfig
 
    - name: start nginx server
      service: name=nginx state=started
      when:
        - nginxsyntax.rc == 0
        - nginxrunning.stat.exists == false
      tags: updateconfig
指定tags 去执⾏PlayBook

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

ansible-playbook -i hosts site.yml -t updateconfig
五**、 Handlers 属性**

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

改进PlayBook
 - name: handlers playbook example
   hosts: webservers
   gather_facts: no
   vars:
     createuser:
        - tomcat
        - www
        - 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=nginx.conf dest=/etc/nginx/
       tags: updateconfig
       notify: reload nginx server
 
    - name: add virtualhost config
      copy: src=www.qfedu.com.conf dest=/etc/nginx/conf.d/
      tags: updateconfig
      notify: reload nginx server
 
   - name: check nginx syntax
     shell: /usr/sbin/nginx -t
     register: nginxsyntax
     tags: updateconfig
  
   - name: check nginx running
     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:
   - name: reload nginx server
    service: name=nginx state=reloaded
    when:
      - nginxsyntax.rc == 0
      - nginxrunning.stat.exists == true

在改进的PlayBook中,我们针对⽂件发布TASK 任务 “update nginx main confifig” 和 “add virtualhost confifig” 增加了新属性 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任务文章来源地址https://www.toymoban.com/news/detail-498878.html

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

到了这里,关于Ansible之Playbook的任务控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Ansible Playbook 常用变量

    以下是 Ansible Playbook 常用变量 ansible_connection : 指定连接类型(如 ssh、winrm) ansible_user : 指定远程用户 ansible_ssh_pass : 指定远程用户密码 ansible_become : 指定是否切换为超级用户 ansible_become_user : 指定切换到的用户 ansible_become_pass : 指定超级用户密码 ansible_host : 指定远程主机的

    2024年02月11日
    浏览(41)
  • 使用Ansible中的playbook

    目录 1.Playbook的功能 2.YAML 3.YAML列表 4.YAML的字典 5.playbook执行命令 6.playbook的核心组件 7.vim 设定技巧 示例 playbook 是由一个或多个play组成的列表 Playboot 文件使用YAML来写的 #简介# 是一种表达资料序列的格式,类似XML #特点# 1、可读性好 2、和脚本语言交互性号 3、易于实现 4、适用

    2024年02月06日
    浏览(33)
  • Ansible之playbook剧本

    playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。playbook 就像 Ansible 控制器给被控节点列出的的一系列 to-do-list ,而被控节点必须要完成。也可以这么理解,playbook 字面意思,即剧

    2024年02月09日
    浏览(38)
  • ansible的playbook剧本

    (1)Tasks:任务,即通过 task 调用 ansible 的模块将多个操作组织在一个 playbook 中运行 (2)Variables:变量 (3)Templates:模板 (4)Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作 (5)Roles:角色 ==Ansible在执行完某个任务之后并不会立即去执行对应的han

    2024年02月12日
    浏览(39)
  • Ansible playbook编写

    Tasks :任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 Variables :变量 Templates :模板 Handlers :处理器,当changed状态条件满足时,(notify)触发执行的操作 Roles :角色

    2024年02月14日
    浏览(33)
  • [ansible] playbook运用

        2.1 基础变量的定义与引用 在yaml文件中,我们可以在初始配置的模块中用var去定义变量的存在,变量的格式为key:value,以此来确定该变量在剧本中的存在   2.2 引用fact信息中的变量   首先我们知道  使用 ansible 组  -m setup   可以收集该组中所有的节点信息 , 所以setup中

    2024年02月20日
    浏览(36)
  • Ansible之Playbook

    1.简介 Playbook 也通常被⼤家翻译成剧本。 可以认为它是Ansible ⾃定义的⼀⻔语⾔(可以将 Playbook ⽐作Linux 中的 shell,⽽ Ansible 中的 Module 可以⽐作为 Linux 中的各种命令。) 2.Play的定义 PlayBook遵循YAML 的语法格式。 由于Playbook 是由⼀个或者多个Play组成,那么如果我们熟悉Play的写

    2024年02月11日
    浏览(37)
  • [ansible] playbook角色

    Roles又称为角色,playbook被称为剧本。Roles角色是自1.2版本之后引入的新特性,用于层次性、结构化的组织剧本   roles能够根据层次型结构自动装载变量文件、任务集、以及触发的动作等,要使用roles只需要在剧本中使用include命令引入即可 简单的来说,roles就是分别将变量、文

    2024年02月21日
    浏览(42)
  • Ansible playbook ----- 剧本

    playbooks 本身由以下各部分组成 (1)Tasks:任务,即通过 task 调用 ansible 的模板将多个操作组织在一个 playbook 中运行 (2)Variables:变量 (3)Templates:模板 (4)Handlers:处理器,当changed状态条件满足时,(notify)触发执行的操作 (5)Roles:角色 //示例: vim test1.yaml ---    

    2024年02月10日
    浏览(43)
  • 优化ansible执行playbook速度

    ansible对应版本信息 # ansible --version ansible 2.9.27   config file = /root/ansible/ansible.cfg   configured module search path = [\\\'/root/.ansible/plugins/modules\\\', \\\'/usr/share/ansible/plugins/modules\\\']   ansible python module location = /usr/lib/python3.11/site-packages/ansible   executable location = /usr/bin/ansible   python version = 3.1

    2024年01月19日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包