Ansible 系列之 Ansible 任务控制

Ansible 任务控制基本介绍

任务控制类似于编程语言中的 if … 、for … 等逻辑控制语句。
·

Ansible 判断控制

在 Playbook 中,使用 when 进行条件判断控制。
when 支持的运算符如下:

  • ==
  • !=
  • >、 >=
  • < 、<=
  • is defined
  • is not defined
  • true
  • false
  • 支持逻辑运算符: and or
    ·

示例一:Nginx 启动逻辑欠缺考虑

若 Nginx 的配置文件语法错误则会导致启动 Nginx 失败,以至于 Playbook 执行失败。

---
- name: A simple paly example
  hosts: wpf002
  tasks:
    - name: yum install nginx 
      yum: name=nginx state=installed
      
    - name: update nginx config
      copy: src=nginx.conf dest=/etc/nginx/ backup=yes
      
    - name: add nginx virtualhost config
      copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
      
    - name: start nginx 
      systemd: name=nginx state=started

如果我们能够在启动之前去对 Nginx 的配置文件语法做正确性的校验,只有当校验通过的时候我们才去启动或者重启 Nginx;否则则跳过启动 Nginx 的过程。这样就会避免 Nginx 配置文件语法问题而导致的无法启动 Nginx 的风险。

·

使用注册变量和 debug 模块检测 Nginx 语法

1 获取 Nginx 语法检测结果

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax

2 通过 debug 模块,打印出结果

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax
      
    - name: print nginxsyntax
      debug: var=nginxsyntax
[root@wpf ~]# ansible-playbook playbook.yml 
...
TASK [print nginxsyntax] *************************************************************************************************************
ok: [wpf002] => {
    "nginxsyntax": {
        "changed": true, 
        "cmd": "/usr/sbin/nginx -t", 
        "delta": "0:00:00.015091", 
        "end": "2021-02-21 21:05:56.557691", 
        "failed": false, 
        "rc": 0, 
        "start": "2021-02-21 21:05:56.542600", 
        "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": []
    }
}
...

从上面输出内容可以看出,当 nginxsyntax.rc 为 0 时语法校验正确。

3 通过条件判断(when)指令校验 Nginx 的语法

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax
      
    - name: print nginxsyntax
      debug: var=nginxsyntax
      
   - name: start nginx
     systemd: name=nginx state=started
     when: nginxsyntax.rc == 0

·

示例一最终 Playbook

---
- name: A simple paly example
  hosts: wpf002
  tasks:
    - name: yum install nginx 
      yum: name=nginx state=installed
      
    - name: update nginx config
      copy: src=nginx.conf dest=/etc/nginx/ backup=yes
      
    - name: add nginx virtualhost config
      copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
      
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax
      
    - name: start nginx
      systemd: name=nginx state=started
      when: nginxsyntax.rc == 0

·

Ansible 循环控制

在 Playbook 中使用 with_items 去实现循环控制,且循环时的中间变量(比如:for i in中的 $i 变量)只能是关键字 item ,不能随意自定义。

·

示例二:批量创建用户

通过一个个指令的罗列过于死板。如果再创建若干个用户,将难以收场。

---
- name: A simple paly example
  hosts: wpf002
  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

·

示例二最终 Playbook

---
- name: A simple paly example
  hosts: wpf002
  vars: 
    createuser: 
      - tomcat
      - www
      - mysql
  tasks:
    - name: create user
      user: name="{{ item }}" state=present
      with_items: "{{ createuser }}"

·

新版本(loop)循环控制

loop 循环控制 + when 条件判断控制

---
- name: A simple paly example
  hosts: wpf002
  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

·

Tags 属性

tags 属性可以帮助我们去解决目前 Playbook 变更而导致的扩大变更范围和变更风险的问题。

在我们重复使用一个 Playbook 中的某一个或多个 task 任务的时候,就需要 tags 属性。

示例三:新增属性 tags

使用示例一的例子,比如我们需要对 Nginx 的配置文件进行多次修改。

为"update nginx main config" 和 "add virtualhost config"新增属性 tags,属性值为 updateconfig。

另外我们新增 “reload nginx server” task 任务。当配置文件更新后,去 reload Nginx 服务。

reload Nginx 服务,需要依赖于 Nginx 服务是已经启动状态。所以,还需要进一步通过判断 Nngix 的 pid 文件是否存在。判断一个文件出否存在,可以使用 stat 模块。
·
·
使用 stat 模块判断 nginx.pid 是否存在

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      
    - name: print nginx syntax
      debug: var=nginxrunning
[root@wpf ~]# ansible-playbook playbook.yml 
...
ok: [wpf002] => {
    "nginxrunning": {
        "changed": false, 
        "failed": false, 
        "stat": {
 ...
            "executable": false, 
            "exists": true, 
            "gid": 0, 
            "gr_name": "root", 
...
        }
    }
}
...

从上面输出内容可以看出,当 nginxrunning.stat.exists 的值是 true 就表示 /var/run/nginx.pid 存在且为文件,就代表 Nginx 正常运行,反之 false 是未运行。
·

示例三最终 Playbook

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: yum install nginx 
      yum: name=nginx state=installed
      
    - name: update nginx config
      copy: src=nginx.conf dest=/etc/nginx/ backup=yes
      tags: updateconfig
      
    - name: add nginx virtualhost config
      copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
      tags: updateconfig
      
    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      tags: updateconfig
      
    - name: print nginxrunning
      debug: var=nginxrunning.stat.exists
      
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax
      tags: updateconfig
      
    - name: print nginxsyntax
      debug: var=nginxsyntax.rc
      
    - name: reload nginx server
      systemd: name=nginx state=reloaded
      when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true
      tags: updateconfig
      
    - name: start nginx
      systemd: name=nginx state=started
      when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == false
      tags: updateconfig

注意: 使用 stat 模块判断 nginx.pid 是否存在,本身没有问题。但是在这之前,使用了 “/usr/sbin/nginx -t” 来检测 nginx 语法的正确性。当 nginx.pid 不存在时,执行这个命令会生成一个空的 nginx.pid 文件。所以,在后面的 nginxrunning.stat.exists 会一直为 true。所以在判断 nginx.pid 是否存在,应该放在 nginx 语法检测之前。
·

指定 tags 去执行 Playbook

执行时一定要指定 tags,这样再执行的过程中只会执行 task 任务上打上 tags 标记为 updateconfig 的任务

ansible-playbook playbook.yml -t updateconfig

·

Handlers 属性

观察前面的 Playbook,可以发现,当我的配置文件没有发生变化时,每次依然都会去触发 “reload nginx server” 这个任务。如果要实现,只有配置文件发生变化的时候才去触发"reload nginx server" 这个任务,就需要使用 handlers 属性。

在 Playbook 中,使用 notify 调用 Handlers。Handlers 与 task 同级。
·

示例四:Handlers 属性

---
- name: task control playbook example
  hosts: wpf002
  tasks:
    - name: yum install nginx 
      yum: name=nginx state=installed
      
    - name: update nginx config
      copy: src=nginx.conf dest=/etc/nginx/ backup=yes
      tags: updateconfig
      notify: reload nginx server
      
    - name: add nginx virtualhost config
      copy: src=wpf.com.conf dest=/etc/nginx/conf.d/
      tags: updateconfig
      notify: reload nginx server
      
    - name: check nginx running
      stat: path=/var/run/nginx.pid
      register: nginxrunning
      tags: updateconfig
 
    - name: check nginx syntax
      shell: /usr/sbin/nginx -t
      register: nginxsyntax
      tags: updateconfig

    - name: start nginx
      systemd: name=nginx state=started
      when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == false
      tags: updateconfig
 
  handlers:
    - name: reload nginx server
      systemd: name=nginx state=reloaded
      when: nginxsyntax.rc == 0 and nginxrunning.stat.exists == true
      tags: updateconfig

我们针对"update nginx main config" 和 “add virtualhost config” 任务增加了新属性 notify, 值为 “reload nginx server”。

它的意思是说,针对这两个任务,设置一个通知机制,当 Ansible 认为文件的内容发生了变化时(文件MD5发生变化了),它就会发送一个通知信号,通知 handlers ,它会根据发送的通知,在 handlers 中相关的任务中寻找名称为"reload nginx server" 的任务。

注意: notify 属性设置的值,一定要确保能和 handlers 中的 task name 对应上。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值