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}}
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 value | value is defined | 变量存在 | is not defined | value is not defined | 变量不存在 | in | value is in value | 变量值为 | not in | value is not in value | 变量值不为 | bool变量 值为true | value | 变量值为true | bool变量 值为false | not 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脚本中,我们通常使用 notify 和handlers来设置触发器,其具体含义如下:
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磁盘的分区设定
|