ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务

Posted 是大姚呀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务相关的知识,希望对你有一定的参考价值。

文章目录

ansible自动化运维详解(六)ansible中的任务执行控制及实例演示:循环、条件判断、触发器、处理失败任务

一、实验环境搭建(一主三从)

这篇博客将对playbook脚本中的任务控制进行主要介绍。任务执行控制类似于编程语言中的if … 、for … 等逻辑控制语句,为了便于大家理解掌握,在这篇博客中我将给出多个实际应用案例来说明在playbook脚本中,任务控制应该如何应用。

在之前的ansible自动化运维详解系列博客的实验演示中,我们使用两台rhel8.2版本虚拟机构建了ansible的一主一从节点,这里为了更好地演示、体现ansible中的任务执行控制,我们需要额外添加两个从节点即构建一主三从的实验环境。

实验步骤:
1、在真实主机的虚拟化存储目录/var/lib/libvirt/images/中,创建westosc、westosd两块新的虚拟机硬盘,即新建两台虚拟机

2、修改westosc主机的域名将其作为受控节点2;配置westosc主机网络互通:编辑其网卡网关配置文件/etc/sysconfig/network-scripts/ifcfg-ens3,设置ip为172.25.33.201,重启网络接口;修改开机启动默认运行级别为multi-user.target,这是因为使用ansible时不需要图形接口,只需要支持用户SSH远程连接,所以运行级别选择 3

修改westosd主机的域名将其作为受控节点3;配置westosd主机网络互通:编辑其网卡网关配置文件/etc/sysconfig/network-scripts/ifcfg-ens3,设置ip为172.25.33.202,重启网络接口;同样地,修改开机启动默认运行级别为multi-user.target

3、在ansible控制主机中,切换到lee用户身份即用户级操作环境,编辑lee用户家目录下ansible目录中的inventory清单文件,在westos组内加入两台新建的受控主机,此时读取清单可以列出所有三台受控主机

4、在控制主机连接管理受控主机的过程中,首先要在ansible控制主机中生成python脚本,然后远程通过sshd服务传输到受控主机上,在传py文件的过程中需要受控主机的认证通过。为了避免每次连接受控主机时都要输入密码进行ssh认证,这里我们需要对三台受控主机做ssh免密认证:在ansible控制主机中,切换到root用户身份提权,使用for循环语句将ssh连接的公钥复制给三台受控主机172.25.33.200、172.25.33.201、172.25.33.202的root用户

5、但由于使用root用户权限在受控主机中操作权限太大,所以一般需要使用普通用户的身份在受控节点执行管理操作,这里我们为受控节点创建普通用户devops并设置用户密码:在ansible控制主机中,使用openssl passwd -6加密用户密码(出于传输的安全性考虑),接着切换回lee用户身份即用户级操作环境,使用ansible命令调用user模块在所有的三台受控主机中创建普通用户devops,并设置用户密码为加密得到的密文字符串

可以看到命令成功执行并对三台受控主机作出改变

6、重新对三台受控主机的devops普通用户做ssh免密认证:在ansible控制主机中,切换到root用户身份提权,使用for循环语句将ssh连接的公钥复制给三台受控主机172.25.33.200、172.25.33.201、172.25.33.202中新创建的普通用户devops

7、此时还无法使用ansible管理受控主机,这是因为当前在受控主机中运行指令时用到的是devops普通用户身份,无权限,我们需要visudo下放权力给devops:在ansible控制主机中,切换回lee用户身份即用户级操作环境,使用ansible命令调用lineinfile模块、以root用户身份在所有三台受控主机的/etc/sudoers中添加指定语句,赋予devops用户所有权限,同时设置devops用户在sudo提权时NOPASSWORD免密

8、在控制主机lee用户家目录下的ansible目录中,使用ansible命令调用shell模块查看显示所有受控主机/etc/sudoers提权配置文件的后三行,可以看到devops用户sudo提权设置成功

最后使用ansible命令调用ping模块测试所有受控主机的连通性,可以看到三台受控主机都能够ping通,至此一主三从的实验环境构建完成

二、循环

2.1、简单循环

在ansible的playbook脚本中,我们通常使用 item(loop迭代循环) 来处理简单的迭代循环任务,其使用方式如下:

方式一:赋值列表,即loop里使用列表定义了多个变量值,此时每个变量前需要加-
loop: 		
  - value1
  - value2
  - ...

方式二:迭代变量名称,即loop里使用变量名称直接引用了在其他文件中定义的多值变量,此时不用加-
	   不加-表示变量代表的是所有值(整体),在变量定义文件中每个变量前已经有-了
loop: 	
  item	##item:迭代循环变量

2.2、循环散列或字典列表

在ansible的playbook脚本中,当需要定义使用多个多值变量时,我们可以使用 循环散列或字典列表 来进行处理,其使用方式示例如下:

---
- name: create file
  hosts: 172.25.0.254
  tasks:
    - name: file module
      service:
        name: " item.name"
        state: " item.state "
      loop:					loop里使用字典列表定义了多个多值变量
        - name: httpd       此时每个变量组字典前需要加-(多个字典并列)
          state: started
        - name: vsftpd
          state: stopped

实例1:在不同受控主机中建立多个用户并指定各自密码

1、编辑控制主机lee用户家目录下ansible目录中的清单文件,分别设置westos、prod、dev、linux四个主机组如下

2、编辑脚本文件user.yml如下:为westos主机组内的所有受控主机创建用户,这里在user模块中直接使用列表方式为指定用户名称的参数name定义了三个值

执行该playbook脚本文件,系统报错执行失败,上述使用列表直接为模块参数赋多个值的方式是错误的,在编译执行时会被ansible识别为一个完整的字符串

3、修改脚本文件user.yml:在loop里使用列表定义多个变量值(注意此时每个变量前需要加-),在指定user模块中用户名称参数name的值时,使用 item(loop迭代循环)的方式循环读取loop赋值列表中的变量值

再次执行该playbook脚本文件,脚本执行成功并对受控主机作出改变,依次在受控主机中创建了多个指定用户

4、在控制主机lee用户家目录下的ansible目录中,编辑变量定义文件user_list.yml,在该文件中使用列表方式为用户名称变量USER定义多个值

修改脚本文件user.yml:指定变量所在文件为当前目录下的user_list.yml,删除之前在westos主机组内所有受控主机中创建的用户,这里在loop里使用变量名称直接引用在其他文件中定义的多值变量USER(此时不用加-,在变量定义文件中每个变量前已经有-了)

执行该playbook脚本文件,脚本执行成功并对受控主机作出改变,依次在受控主机中删除了之前创建的多个指定用户

5、在控制主机中使用openssl password -6 命令输入明文密码生成多个加密字符串作为不同用户的密码(直接指定用户密码为明文不安全)

6、编辑脚本文件user.yml:在loop里使用字典列表定义user、passwd两个多值变量,在指定user模块中用户名称参数name、用户密码参数password的值时,使用 item(loop迭代循环)的方式循环读取loop字典列表中的变量值组,即在受控主机中创建用户并为每个用户指定其各自的用户密码

执行该playbook脚本文件,脚本执行成功并对受控主机作出改变,依次在受控主机中创建了多个指定用户并设置了用户密码

编辑脚本文件user.yml:注意当我们在loop里使用字典列表定义了多个多值变量,在使用 item(loop迭代循环)的方式循环读取loop字典列表中的变量值组时,除了使用item.变量名称的方式外,还可以使用item['变量名称']的方式读取变量值

再次执行该playbook脚本文件,脚本文件可以成功执行

7、测试:在控制主机以创建的任一用户身份ssh远程连接westos组内的受控主机,输入相应的用户密码可以成功登录连接,这意味着使用playbook脚本在不同受控主机中建立多个用户并指定各自密码部署成功

三、条件

3.1、条件使用方法

在ansible的playbook脚本中,我们通常使用 when 来处理条件判断任务,其使用方式和如下:

when:
  条件

3.2、条件判断符号说明

符号/字符串示例含义
==value == “字符串”,value == 数字等于
<value < 数字小于
>value > 数字大于
<=value <= 数字小于等于
>=value >= 数字大于等于
!=value != 数字不等于
is defined valuevalue is defined变量存在
is not definedvalue is not defined变量不存在
invalue is in value变量值为
not invalue is not in value变量值不为
bool变量 值为truevalue变量值为true
bool变量 值为falsenot value变量值为false
value in value2变量值在value2列表中

3.3、多条条件组合

在ansible的playbook脚本中,当需要结合多个条件进行组合判断时,其使用方式示例如下:

1、条件且:需要同时满足多个条件
书写方式一:
when:
  条件1 and 条件2
书写方式二:
when:
  - 条件1
  - 条件2

2、条件或:只需要满足其中任一条件
书写方式一:
when:
  条件1 or 条件2
书写方式二:
when: >
  条件1
  or
  条件2

实验步骤:
1、在控制主机lee用户家目录下的ansible目录中,编辑脚本文件test.yml文件如下:调用shell模块在所有受控主机中检测/mnt/file文件是否存在,设置ignore_errors参数值为yes即忽略任务失败、后续任务继续运行,将命令执行的返回值作为变量值注册到字符串OUTPUT中;最后调用debug模块、使用 when 来进行条件判断,这里变量值中的rc参数表示shell模块的执行结果(成功 rc=0;失败 rc=1),当 rc!=0时输出显示调试信息文件未找到,当 rc=0时输出显示调试信息文件存在

2、在执行该playbook脚本文件前,我们先使用ansible命令调用file模块在其中一台受控主机中创建/mnt/file文件

3、执行该playbook脚本文件,可以看到在其余两台受控主机中任务执行失败(其余两台受控主机未创建相应文件)、忽略失败继续执行,三台受控主机成功输出显示对应调试信息

完成测试后,使用ansible命令调用file模块删除在受控主机中创建的/mnt/file文件

实例2、为受控主机创建逻辑卷lvm

要求: 编写playbook脚本文件,在受控主机使用westos物理卷组建立大小为1500M、名为exam_lvm的lvm:1)如果westos物理卷组不存在请输出“vg westos is not exist”;2)如果westos物理卷组大小不足1500M请输出“ vg westos is less then 1500M”,并建立800M大小的lvm。

1、在为受控主机创建逻辑卷lvm前,我们需要有一个大的硬盘文件作为实验素材,这里可以为虚拟机westosc(172.25.33.201)添加一块新的、大小为10G的硬盘

在控制主机中使用ansible命令、调用shell模块查看受控主机westosc(172.25.33.201)的硬盘及分区信息,可以查看到新添加的硬盘被系统识别为/dev/vdb,此时该新盘未进行任何操作,所以无分区信息

2、在控制主机lee用户家目录下的ansible目录中,编辑测试脚本文件test.yml文件如下:调用debug模块、使用 when 对所有三台受控主机进行条件判断,即使用ansible_facts['事实变量名称']采集受控主机事实变量信息判断受控主机中是否存在/dev/vdb硬盘设备,并输出显示相应调试信息

执行该playbook测试脚本文件,可以看到任务成功执行,从显示输出的调试信息可以看到三台受控主机中只有westosc(172.25.33.201)有/dev/vdb硬盘设备

3、在ansible主机中调用 debug 模块,将魔法变量 hostvars 的值打印输出,列出ansible软件的内部信息,可以看到显示的信息中inventory_hostname参数对应的值为受控主机在清单文件中的主机名称(也是IP)

修改测试脚本文件test.yml文件如下:使用 when 对所有三台受控主机进行多条件判断(条件且),即使用ansible_facts['事实变量名称']采集受控主机事实变量信息判断受控主机中是否存在/dev/vdb硬盘设备、同时使用inventory_hostname参数的值判断受控主机名称是否为172.25.33.201,当上述两个条件都满足时才会输出显示相应的调试信息

执行该playbook测试脚本文件,可以看到任务成功执行,由于是条件且判断,在其余两个受控主机中直接跳过、未显示任何调试信息,只有在受控主机westosc(172.25.33.201)中输出显示存在/dev/vdb硬盘设备

4、修改测试脚本文件test.yml文件如下:使用 when 对所有三台受控主机进行多条件判断(条件或),即使用ansible_facts['事实变量名称']采集受控主机事实变量信息判断受控主机中是否存在/dev/vdb硬盘设备、使用inventory_hostname参数的值判断受控主机名称是否为172.25.33.201,满足上述两个条件中的任一条件时就会输出显示相应的调试信息

使用 when 对所有三台受控主机进行条件或判断的另一种书写方式如下:

执行该playbook测试脚本文件,可以看到任务成功执行,由于是条件或判断,此时会输出显示四条调试信息:其余两个受控主机中输出显示不存在/dev/vdb硬盘设备,受控主机westosc(172.25.33.201)中在满足主机名称一致条件时会输出显示不存在/dev/vdb硬盘设备、在同时满足两个条件时会输出显示存在/dev/vdb硬盘设备

5、fdisk交互式对设备/dev/vdb进行分区,新建主分区,分区表位置为1,分区起始位置使用默认位置,设定分区大小为1500M
显示分区表可以看到建立的分区/dev/vdb1,这里注意保存之前所做的操作后退出,对新建物理设备/dev/vdb1进行pv格式化即创建物理卷pv,接着创建物理卷组vg并命名为westos

6、在控制主机lee用户家目录下的ansible目录中,编辑为受控主机创建逻辑卷lvm的脚本文件lvm.yml文件如下:1)当受控主机中存在名为westos的物理卷组vg时,调用 lvol 模块、使用该物理卷组为其创建名为exam_lvm、大小为1500M的逻辑卷lvm,设置ignore_errors参数值为yes即忽略任务失败、后续任务继续运行,将命令执行的返回值作为变量值注册到字符串OUTPUT中;2)调用debug模块、使用 when 来进行条件判断,这里OUTPUT变量值中的rc参数表示lvol模块的执行结果(成功 rc=0;失败 rc=1),当 rc!=0时输出显示westos物理卷组大小不足1500M;3)接着继续调用 lvol 模块,当受控主机中存在名为westos的物理卷组vg、且rc!=0时,使用westos物理卷组为其创建名为exam_lvm、大小为800M的逻辑卷lvm;4)此外,当受控主机中不存在名为westos的物理卷组vg时,调用debug模块输出显示westos物理卷组不存在。

[lee@westos_ansible ansible]$ cat lvm.yml 

- name: create lvm
  hosts: all
  tasks:
    - name: create 1500M lvm
      lvol:
        lv: exam_lvm
        vg: westos
        size: 1500M
      when: ansible_facts['lvm']['vgs']['westos'] is defined
      ignore_errors: yes
      register: OUTPUT
      
    - name: debug size messages
      debug:
        msg: vg westos is less than 1500M
      when:
        - ansible_facts['lvm']['vgs']['westos'] is defined
        - OUTPUT.rc != 0
        
    - name: create 800M lvm
      lvol:
        lv: exam_lvm
        vg: westos
        size: 800M
      when: 
        - ansible_facts['lvm']['vgs']['westos'] is defined
        - OUTPUT.rc != 0
        
    - name: debug messages
      debug:
        msg: vg westos is not exist
      when: ansible_facts['lvm']['vgs']['westos'] is not defined

执行该playbook脚本文件,可以看到任务成功执行,在其余两个受控主机中直接跳过创建lvm操作、并输出显示westos物理卷组不存在,只有在存在westos物理卷组的受控主机westosc(172.25.33.201)中成功创建大小为800M的逻辑卷lvm


在受控主机westosc(172.25.33.201)中,lvs命令查看lvm的状态及数据目录大小,可以看到大小为800M的exam_lvm逻辑卷成功创建

四、触发器(ansible脚本先执行再检测,shell脚本先判断再执行)

在ansible的playbook脚本中,我们通常使用 notifyhandlers来设置触发器,其具体含义如下:

notify当前play片段执行后,对受控主机作出更改(显示信息为黄色),则触发指定的handlers中的动作,与所在play片段同级
handlers触发器被触发后执行的动作,与当前playbook的tasks、hosts等同级

实例3、为受控主机安装httpd服务,设定当httpd服务开放端口改变时更改火墙策略、重启httpd服务

1、在安装httpd服务前,我们需要先配置好所有受控主机的软件源仓库:在控制主机使用ansible命令调用replace模块,将所有受控主机软件仓库目录下、软件源指向文件中的仓库地址改为当前真实主机(已配置好软件仓库)ip地址(注:地址段其他部分相同,只需要将254替换为33)

2、在控制主机lee用户家目录下的ansible目录中,编辑为受控主机安装httpd服务的脚本文件apache.yml文件如下:1)调用 dnf 模块为所有受控主机安装httpd服务的安装包;2)调用 service 模块在所有受控主机中开启httpd服务、并设置其为开机自启动;3)调用 firewalld 模块配置所有受控主机的防火墙策略,即永久允许httpd服务并使设置立即生效;4)调用 lineinfile 模块修改所有受控主机httpd服务的配置文件,更改httpd服务的开放端口为port变量值,设置在修改时对原文件进行备份,当受控主机httpd服务的端口发生改变时触发同级指定handlers中的动作;5)在handlers中定义两个触发动作,即调用 firewalld 模块设置永久允许修改后的端口通过并使设置立即生效,调用 service 模块重启受控主机的httpd服务。

[lee@westos_ansible ansible]$ cat apache.yml 

- name: install web server
  hosts: all
  tasks:
    - name: install apache
      dnf:
        name: httpd
        state: latest
        
    - name: start service
      service:
        name: httpd
        state: started
        enabled: yes
        
    - name: configure firewalld
      firewalld:
        service: http
        state: enabled
        permanent: yes
        immediate: yes
        
    - name: configure port
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        line: Listen "port"
        regexp: "^Listen"
        backrefs: yes
      notify:
        - firewalld
        - restart apache
        
  handlers:
    - name: firewalld
      firewalld:
        port: "port/tcp"
        state: enabled
        permanent: yes
        immediate: yes
    - name: restart apache
      service:
        name: httpd
        state: restarted

执行该playbook脚本文件,在命令中指定port变量值为80,可以看到脚本成功执行并对所有受控主机作出改变

由于配置修改了httpd服务的开放端口,因此触发了handlers中定义的两个动作,更改了受控主机的火墙策略、重启了httpd服务

再次执行上述命令,可以看到脚本成功执行,但没有对所有受控主机作出改变

由于此次执行没有修改httpd服务的开放端口,因此没有触发handlers中定义的两个动作

再次执行该playbook脚本文件,在命令中指定port变量值为8080,可以看到脚本成功执行并对所有受控主机作出改变

由于配置修改了httpd服务的开放端口为8080,因此成功触发了handlers中定义的两个动作

实例4、vsftpd是否允许匿名用户登陆

1、在控制主机lee用户家目录下的ansible目录中,编辑为受控主机安装vsftpd服务的脚本文件vsftpd.yml文件如下:1)调用 dnf 模块为所有受控主机安装vsftpd服务的安装包,当成功对受控主机作出改变即安装成功后,触发同级指定handlers中的动作;2)调用 lineinfile 模块修改所有受控主机vsftpd服务的配置文件,将以anonymous_enable=开头的一行替换为anonymous_enable=state(匿名用户能否登陆),其中state变量通过命令来指定值,当成功对受控主机作出改变后触发同级指定handlers中的动作,设置ignore_errors参数值为yes即忽略任务失败、后续任务继续运行;3)在handlers中定义两个触发动作,即调用 firewalld 模块设置永久允许vsftpd服务通过并使设置立即生效,调用 service 模块重启受控主机的vsftpd服务并设置其开机自启。

[lee@westos_ansible ansible]$ cat vsftpd.yml 

- name: install ftp server
  hosts: all
  tasks:
    - name: install vsftpd
      dnf:
        name: vsftpd
        state: latest
      notify:
        - restart vsftpd
        - firewalld
        
    - name: configure ftp
      lineinfile:
        path: /etc/vsftpd/vsftpd.conf
        regexp: "^anonymous_enable="
        line: "anonymous_enable=state"
      ignore_errors: yes
      notify:
        restart vsftpd
        
  handlers:
    - name: restart vsftpd
      service:
        name: vsftpd
        state: restarted
        enabled: yes
        
    - name: firewalld
      firewalld:
        service: ftp
        state: enabled
        permanent: yes
        immediate: yes

执行该playbook脚本文件

可以看到修改所有受控主机vsftpd服务的配置文件这一任务失败并跳过,这是因为缺少对state变量的赋值

此时在vsftpd服务已安装完成的任一受控主机中,lftp ip使用匿名用户身份访问ftp服务,不能成功访问(列出默认共享目录下资源)

2、再次执行该playbook脚本文件,在命令中指定state变量值为YES,可以看到脚本成功执行并对所有受控主机作出改变,触发了handlers中定义的重启vsftpd服务动作

此时在受控主机中lftp ip使用匿名用户身份访问ftp服务,可以成功访问,即可以成功列出默认共享目录下资源

五、处理失败任务

在ansible的playbook脚本中,我们可以通过以下五种方式来处理任务失败的情况:

参数含义
ignore_errors
( ignore_errors: yes )
当同级play片段遇到任务失败时会终止,并会忽略任务失败继续运行下面的任务
force_handlers当任务失败后同级play片段被终止,但仍会调用同级触发器进程
changed_when控制任务在何时报告它已进行更改
failed_when当符合条件时,强制使任务失败
block
rescue
always
定义要运行的任务
定义当block句子中出现失败任务后,所要运行的任务
定义最终独立运行的任务

实验步骤:
1、编辑上面编写的脚本文件vsftpd.yml,添加一个错误的play片段,如调用dnf模块安装不存在的软件包

执行该playbook脚本文件,可以看到脚本文件在执行到错误的play片段时执行失败,整个脚本文件结束运行

修改该脚本文件,在错误的play片段同级设置ignore_errors参数值为yes,即忽略任务失败、后续任务继续运行
再次执行该playbook脚本文件,可以看到脚本文件在执行到错误的play片段时忽略任务失败,继续运行下面的任务

2、在控制主机中使用ansible命令调用dnf模块,卸载所有受控主机中的vsftpd服务安装包

编辑脚本文件vsftpd.yml,还原之前错误的play片段

再次执行该playbook脚本文件

可以看到脚本文件在执行到错误的play片段时执行失败,整个脚本文件结束运行,且在其之前成功执行的安装vsftpd任务、所触发的handlers中定义的两个动作没有成功执行(handlers是在错误片段后面书写定义的)

再次使用ansible命令调用dnf模块,卸载所有受控主机中的vsftpd服务安装包

编辑脚本文件vsftpd.yml,在与hosts、tasks同级处(因为handlers与hosts、tasks同级)设置 force_handlers 参数值为yes,即当任务失败后同级play片段被终止,但仍会调用同级触发器进程

再次执行该playbook脚本文件,可以看到脚本文件在执行到错误的play片段时执行失败,整个脚本文件结束运行,但handlers中定义的两个触发动作仍可以成功执行


3、再次执行该playbook脚本文件,可以看到安装vsftpd任务成功运行,但并未对受控主机做出改变,这是因为在上一次执行过程中vsftpd已成功在受控主机中安装

编辑该脚本文件vsftpd.yml,在安装vsftpd服务的play片段同级处,设置 changed_when 参数值为yes,即控制任务报告它已进行更改

再次执行该playbook脚本文件,可以看到安装vsftpd任务成功运行,并显示对受控主机做出改变

在控制主机中使用ansible命令调用dnf模块,卸载所有受控主机中的vsftpd服务安装包

编辑该脚本文件vsftpd.yml,设置 changed_when 参数值为false,即控制任务报告它没有进行更改

再次执行该playbook脚本文件,可以看到安装vsftpd任务成功运行,虽然此时受控主机中重新安装了vsftpd即做出改变,但输出信息显示没有对受控主机做出改变

4、编辑该脚本文件vsftpd.yml,添加一个play片段,如调用shell模块在所有受控主机中输出westos

执行该playbook脚本文件,可以看到shell模块任务成功运行并对受控主机做出改变(输出指定信息)

编辑该脚本文件vsftpd.yml,在shell模块的play片段同级处,设置 failed_when 参数值为true,即当符合条件时强制使任务失败

再次执行该playbook脚本文件,可以看到shell模块任务被强制运行失败

编辑脚本文件vsftpd.yml,还原之前添加的错误play片段,即调用dnf模块安装不存在的软件包,在错误片段的同级处设置 failed_when 参数值为false,即当符合条件时强制显示任务成功

再次执行该playbook脚本文件,可以看到错误play片段的任务显示运行成功(由于不是真的运行成功,所以未对受控主机作出任何改变)

编辑该脚本文件vsftpd.yml,删除错误的play片段,添加一个play片段,如调用shell模块在所有受控主机中输出hello,并将命令执行的返回值作为变量值注册到字符串 INFO 中,在该片段的同级处设置 failed_when 参数值如下,即 INFO 变量的标准输出参数stdout的值中包含有hello时强制使任务失败

再次执行该playbook脚本文件,可以看到 failed_when条件符合、shell模块任务被强制运行失败

编辑该脚本文件vsftpd.yml,将shell模块在所有受控主机中输出显示的字符串改为westos

再次执行该playbook脚本文件,可以看到 failed_when条件不符合,shell模块任务显示运行成功并对受控主机作出改变

5、编写测试脚本文件test.yml,在block中定义在所有受控主机中要运行的任务:调用shell模块检测受控主机中是否存在/mnt/file文件,调用debug模块输出显示“/mnt/file存在”;在rescue中定义当block句子中出现失败任务后,所要运行的任务:调用debug模块输出显示“/mnt/file不存在”;在always中定义最终独立运行的任务:调用debug模块输出显示“bye”

此时三台受控主机中都没有/mnt/file文件,使用ansible命令调用file模块在任一受控主机(这里是172.25.33.201)中建立/mnt/file文件

执行该测试脚本文件test.yml,可以看到shell模块任务在其余两个受控主机中执行失败、在172.25.33.201主机中成功执行并对受控主机作出改变

相应的,在172.25.33.201主机中输出显示调试信息“/mnt/file存在”,在其余两个受控主机中输出显示“/mnt/file不存在”,另外在三个主机中都输出显示了“bye ”

实例5、为受控主机创建设备/dev/vdb1并挂载

要求: 编写playbook脚本文件,在受控主机使用硬盘/dev/vdb建立大小为1500M、名为/dev/vdb1的设备:1)如果硬盘/dev/vdb不存在请输出“/dev/vdb is not exist”;2)如果硬盘/dev/vdb大小不足2G请输出“ /dev/vdb is less then 2G”,并建立800M大小的/dev/vdb1;3)最后将建立好的/dev/vdb1设备挂载到/westos目录上。

1、由于在实例2中,我们在受控主机node2(172.25.33.201)中创建了lvm,为了便于后续实验,这里需要清除之前的实验痕迹:lvs命令查看lvm的状态及数据目录大小,可以看到大小为800M的exam_lvm逻辑卷,移除该逻辑卷,接着移除物理卷组westos

fdisk交互式对设备/dev/vdb进行分区管理,d操作删除之前创建的分区/dev/vdb1

删除设备上之前所有的分区设定,即通过dd if=/dev/zero of=/dev/vdb bs=1M count=1将磁盘设备初始化,即使用空数据覆盖掉磁盘设备中磁盘分区表中的数据,此时可以查看到硬盘/dev/vdb无分区信息

2、之前我们为虚拟机westosc(172.25.33.201)添加了一块大小为10G的硬盘,这里我们可以为虚拟机westosb(172.25.33.200)添加一块新的、大小为1.2G的硬盘用来构建/dev/vdb大小不足2G的实验情况

在控制主机中使用ansible命令、调用shell模块查看所有受控主机的硬盘及分区信息,可以查看到westosb(172.25.33.200)、westosc(172.25.33.201)的硬盘分别被系统识别为大小为1.2G、10G的/dev/vdb,westosd(172.25.33.202)无/dev/vdb

3、在编写脚本文件之前,给大家提示一点:当我们在编写playbook脚本文件时有不清楚应该使用哪个ansible内置模块、或如何使用某一模块时,可以使用ansible-doc -l | grep 模块功能关键字进行查询,找到具体模块后可以使用ansible-doc 模块名称 | less分页查看某一模块的具体使用方法

4、在控制主机lee用户家目录下的ansible目录中,编辑为受控主机创建设备/dev/vdb1并挂载的脚本文件vdb.yml文件如下:1)调用 debug 模块、使用 when 来进行条件判断,当受控主机中不存在设备/dev/vdb时输出显示“/dev/vdb is not exist”;2)在block中定义在所有受控主机中要运行的任务:当受控主机中存在设备/dev/vdb时,调用 parted 模块为/dev/vdb设备划分大小为2G的分区(检测硬盘/dev/vdb大小是否不足2G),当成功对受控主机作出改变后触发同级指定handlers中的4个动作;在rescue中定义当block句子中任务失败(/dev/vdb大小不足2G)后,所要运行的任务:调用 parted 模块为/dev/vdb设备划分大小为800M的分区,当成功对受控主机作出改变后触发同级指定handlers中的2个动作;在always中定义最终独立运行的任务:调用 file 模块创建挂载点目录/westos;3)在handlers中定义4个触发动作:调用 parted 模块删除/dev/vdb设备上划分的大小为2G的测试分区、调用 parted 模块为/dev/vdb设备划分大小为1500M的分区、调用 filesystem 模块格式化/dev/vdb1设备为xfs文件系统(相当与在/dev/vdb1上安装设备管理软件)、调用 mount 模块挂载/dev/vdb1设备到指定目录/westos。

[lee@westos_ansible ansible]$ cat vdb.yml 
---
- name: create vdb1
  hosts: all
  tasks:
    - name: check vdb
      debug:
        msg: /dev/vdb is not exist
      when: ansible_facts['devices']['vdb'] is not defined
    
    - name: create /dev/vdb1
      block:
        - name: check size 2G
          parted:
            device: /dev/vdb
            number: 1
            state: present
            part_end: 2GiB
          when: ansible_facts['devices']['vdb'] is defined
          notify:
            - remove 2G
            - create vdb1
            - create filesystem
            - mount /dev/vdb1
      rescue:
        - name: create 800M
          parted:
            device: /dev/vdb
            number: 1
            state: present
            part_end: 800MiB
          notify:
            - create filesystem
            - mount /dev/vdb1
          when: ansible_facts['devices']['vdb'] is defined   
      always:
        - name: create mount point
          file:
            path: /westos
            state: directory
          
  handlers:
    - name: remove 2G
      parted:
        device: /dev/vdb
        number: 1
        state: absent
    - name: create vdb1
      parted:
        device: /dev/vdb
        number: 1
        state: present
        part_end: 1500MiB
    - name: create filesystem
      filesystem:
        fstype: xfs
        dev: /dev/vdb1
        force: yes
    - name: mount /dev/vdb1
      mount:
        path: /westos
        src: /dev/vdb1
        fstype: xfs
        state: mounted

执行该playbook脚本文件,可以看到任务成功运行,首先检测并输出显示westosd(172.25.33.202)受控主机中不存在/dev/vdb设备

接着成功在westosc(172.25.33.201)受控主机的/dev/vdb中划分2G大小的分区,检测到westosb(172.25.33.200)受控主机的/dev/vdb的大小不足2G、创建800M大小的分区,在三台受控主机中成功创建挂载目录/westos

删除在westosc(172.25.33.201)受控主机/dev/vdb中划分的2G大小的分区、重新创建1500M大小的分区设备/dev/vdb1,分别为westosb(172.25.33.200)、westosc(172.25.33.201)中的设备/dev/vdb1格式化文件系统并挂载到指定目录/westos

5、在node1(172.25.33.200)df查看正在被系统挂载的设备,可以看到设备/dev/vdb1创建成功并挂载,查看设备/dev/vdb1大小为793M(文件系统占了一定空间)

在node2(172.25.33.201)查看正在被系统挂载的设备,可以看到设备/dev/vdb1创建成功并挂载,查看设备/dev/vdb1大小为1.5G

6、当需要永久挂载/dev/vdb1设备,即指定/dev/vdb1设备在开机时自动挂载到相应目录中时,我们可以编写设备挂载策略文件/etc/fstab,在其中添加对应的挂载语句如下(语句中六个参数分别代表设备、挂载点、文件系统类型、挂载参数、是否备份、是否检测)
注意: 此文件在编写完成后不会马上生效,需要mount -a重新读取/etc/fstab文件,此文件内容编写错误会导致系统启动失败

7、实验完成后清除实验痕迹,在控制主机中使用ansible命令调用shell模块从所有受控主机的挂载目录中卸载/dev/vdb1设备、调用parted模块删除所有受控主机/dev/vdb磁盘的分区设定

以上是关于ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务的主要内容,如果未能解决你的问题,请参考以下文章

ansible自动化运维详解ansible中的任务执行控制及实例演示:循环条件判断触发器处理失败任务

自动化运维工具——ansible详解案例分享

ansible自动运维工具之ansible-playbook详解

Ansible自动化运维详解

别让运维太忙,一文详解 Ansible 的自动化运维

自动运维化工具Ansible使用详解(下)| Playbook