VPS测评 VPS推荐 VPS优惠
Linux运维

Ansible block的用法详解

Blocks (块)创建了逻辑上的任务集合,并且为处理任务错误提供了解决方法,功能类似于很多编程语言中的 “异常处理”。


把任务组成block

一个块中的所有任务都会继承和块同一级别的指令。当多个任务都需要满足同一个条件时,使用块来设置指令会更加方便。指令不会影响块本身,而是仅仅被块中包含的任务所继承了。例如:when条件判断语句只对块中的任务有效,对于块本身不起作用。

block例子

 tasks:
   - name: Install, configure, and start Apache
     block:
       - name: Install httpd and memcached
         ansible.builtin.yum:
           name:
           - httpd
           - memcached
           state: present

       - name: Apply the foo config template
         ansible.builtin.template:
           src: templates/src.j2
           dest: /etc/foo.conf

       - name: Start service bar and enable it
         ansible.builtin.service:
           name: bar
           state: started
           enabled: True
     when: ansible_facts['distribution'] == 'CentOS'
     become: true
     become_user: root
     ignore_errors: yes

block中一共有三个task,在执行这三个任务之前,ansible会先判断when后面的条件是否满足。因此如果主机不是centos,这三个任务都不会被执行。并且这三个任务都会以root的身份去执行。ignore_errors:yes 确保了即使block中有某个任务失败了,playbook仍然可以不受影响继续往下运行。


rescue和always

一般来说,playbook中的某个任务失败,接下来的任务就无法运行。但实际情况是,一个playbook可能会用于很多台主机,同样的任务可能有些主机成功,有些主机会失败,除了加上when条件判断,还可以使用block配合rescue和always来处理errors。

rescue:当block中的一个任务返回失败就执行rescue下面的任务,只要rescue后面的任务执行成功,后续其他任务就不会受影响,类似于纠正错误的意思

EXAMPLE

---
- hosts: webservers
  tasks:
    - name: Handle the error
      block:
        - name: Print a message
          ansible.builtin.debug:
            msg: 'I execute normally'

        - name: Force a failure
          command: /bin/false

        - name: Never print this
          ansible.builtin.debug:
            msg: 'I never execute, due to the above task failing, :-('
      rescue:
        - name: Print when errors
          ansible.builtin.debug:
            msg: 'I caught an error, can do stuff here to fix it, :-)'
    - name: wall hahaha
      shell: wall hahaha

以上例子,block中有三个task,第二个task返回错误,那么第三个task不会被执行,并且同时触发了rescue后面的信息。所以结果只会打印两句话

"msg": "I execute normally"
"msg": "I caught an error, can do stuff here to fix it, :-)"

并且因为rescue中的任务执行成功,后面任务继续执行,主机上能看到wall广播。

always: 无论之前blcok中的任务是成功还是失败,always下的任务都会执行,即使接下来always中的任务执行成功,后面的其他任务也不会被执行

EXAMPLE

---
- hosts: webservers
  tasks:
     - name: Always do X
       block:
         - name: Print a message
           ansible.builtin.debug:
             msg: 'I execute normally'

         - name: Force a failure
           command: /bin/false

         - name: Never print this
           ansible.builtin.debug:
             msg: 'I never execute :-('
       always:
         - name: Always do this
           ansible.builtin.debug:
             msg: "This always executes, :-)"
     - name: wall hahaha
       command: wall hahaha

以上例子,block中的第二个任务失败了,所以第三个任务不会继续执行下去。只执行always下面的任务。除了always中的任务,后续的任务不会继续执行,看不到wall广播。

"msg": "I execute normally"
"msg": "This always executes, :-)"

RHCE考题

创建一个名为 /home/student/ansible/lv.yml 的 playbook,它将在所有受管节点上运行以执行下列任务:

创建符合以下要求的逻辑卷:

• 逻辑卷创建在 research 卷组中
• 逻辑卷名称为 data
• 逻辑卷大小为 1500MiB
• 使用 ext4 文件系统格式化逻辑卷
• 如果无法创建请求的逻辑卷大小,应显示错误消息Could not create logical volume of that size并且应改为使用大小 800MiB

• 如果卷组 research 不存在 ,应显示错误消息Volume group does not exist
• 不要以任何方式挂载逻辑卷

我的解题思路

首先,先判断被控端有没有卷组,如果没有直接跳过显示卷组不存在。如果存在,先创建1500M的逻辑卷,如果遇到空间不够提示创建失败再创建800M的逻辑卷。并且无论空间够不够1500M都格式化成ext4。这题需要用到block配合rescue、always来写playbook。

参考答案

lv.yml

---
- hosts: all
  tasks: 
    - name:
      block:
        - name: 
          lvol:
            vg: research
            lv: data
            size: 1500m 
      rescue:
        - name:
          debug:
            msg: Could not create logical volume of that size
        - name:
          lvol:
            vg: research
            lv: data
          size: 800m
      always:  
        - name: 
          filesystem: 
            fstype: ext4
            dev: /dev/research/data
      when: "'research' in ansible_lvm.vgs"
    - name: 
      debug:
        msg: Volume group does not exist
      when: "'research' not in ansible_lvm.vgs"

模拟环境执行结果

未经允许不得转载:青蛙主机 » Ansible block的用法详解

VPS相关常用工具

PING测试工具自用毛子接码站