环境版本说明
- RedHat9 [Red Hat Enterprise Linux release 9.0]
- Ansible [core 2.13.3]
- Python [3.9.10]
- jinja [3.1.2]
1. 利用循环迭代任务
- 通过利用循环,管理员无需编写多个使用同一模块的任务。
- Ansible支持使用loop关键字对一组项目迭代任务,通过配置循环以利用列表中各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。
2. 简单循环
简单循环对一组项目迭代任务。loop关键字添加到任务中,将应对其迭代任务的项目列表为值。循环变量item保存每个迭代过程中使用的值。
查看当前清单文件
cat inventory
针对both组实现,关闭防火墙服务和时钟同步服务,playbook内容如下
---
- name: play1
hosts: both
tasks:
- name: stop firewalld.service and chronyd.service
ansible.builtin.service:
name: "{{ item }}" # 固定格式,表示从loop中提取列表项
state: stopped
loop:
- firewalld # loop循环列表值
- chronyd
3. 循环使用单个变量
将loop循环列表值修改为变量引用,在变量中定义要循环的列表值。
将循环列表值定义在vars字段中
---
- name: play1
hosts: both
vars: # 在变量中定义循环列表值
servers:
- firewalld
- chronyd
tasks:
- name: stop firewalld.service and chronyd.service
ansible.builtin.service:
name: "{{ item }}" # 固定格式,表示从loop中提取列表项
state: stopped
loop: "{{ services }}"
将循环列表值定义在文件中
# 新建vars.yml变量文件
services:
- firewalld
- chronyd
# 新建playbook
---
- name: play1
hosts: both
vars_files: vars.yml
tasks:
- name: stop firewalld.service and chronyd.service
ansible.builtin.service:
name: "{{ item }}"
state: stopped
loop: "{{ services }}"
4. 循环字典列表
将循环列表值定义在vars字段中
---
- name: play1
hosts: serverb
vars:
msg:
- name: Mike
age: 20
- name: Jack
age: 18
tasks:
- name: Print Msg
ansible.builtin.debug:
msg: Print {{ item.name }} and {{ item.age }}
loop: "{{ msg }}"
将循环列表值定义在文件中
# 创建变量文件
vim for4_vars.yml
msg:
- name: Mike
age: 20
- name: Jack
age: 18
# 新建playlook
---
- name: play1
hosts: serverb
vars_files: /home/student/ansible/for4_vars.yml
tasks:
- name: Print Msg
ansible.builtin.debug:
msg: Print {{ item.name }} and {{ item.age }}
loop: "{{ msg }}"
5. 有条件的运行任务
- Ansible可以使用 conditionals 在符合特定条件时运行任务或Play。例:可以使用条件在Ansible安装或配置某个服务之前,确定受管主机上的可用内存。
- 条件语句可以帮助区分不同的受管主机,并根据所符合的条件来分配功能角色。
- Playbook变量、注册的变量和Ansible事实都可以通过条件句来进行测试。
- 可以比较字符串、数字数据和布尔值的运算符
when判断语句
- when判断对象是模块,和模块在同一层次
- when判断当前模块是否执行,而非判断它下级模块是否执行
- when中引用变量、facts,不需要添加
{{}}
- 用于测试条件中相等的
==
运算符不可与变量赋值=
运算符混淆 - 一个when语句可用于评估多个值,通过使用
and
和or
关键字组合,或使用括号分组条件
简单示例
---
- name: play1
hosts: both
tasks:
- name: print msg
ansible.builtin.debug:
msg: Print Message
when: inventory_hostname == 'serverc' # 限定主机名为serverc
条件示例
表达式 | 作用 |
---|---|
inventory_hostname == “serverc” | 等于(值为字符串) |
Mtu == 1500 | 等于(值为数字) |
Mtu < 1500 | 小于 |
Mtu > 1500 | 大于 |
Mtu >= 1500 | 大于等于 |
Mtu <= 1500 | 小于等于 |
Mtu != 1500 | 不等于 |
Min_memory is defined | 变量存在 |
Min_memory is undefined | 变量不存在 |
Min_memory is not defined | 变量不存在 |
inventory_hostname in group.both | 第一个变量存在,且在第二个变量内,类似 Python中的 ‘Mike’ in [‘Mike’,‘Jack’] |
多条件示例:or是或的关系,任意一个条件为真即可
when: ansible_board_name= == "RHEL" and ansible_board_vendor == "Red Hat"
多条件实例:and是与的关系,全部条件都满足为真
# 第一种方式
when: ansible_board_name= == "RHEL" and ansible_board_vendor == "Red Hat"
# 第二种方式
when:
- ansible_board_name= == "RHEL"
- ansible_board_vendor == "Red Hat"
与或嵌套语句书写
when: >
( ansible_board_name= == "RHEL" and
ansible_board_vendor == "Red Hat" )
or
( ansible_board_name= == "RHEL" and
ansible_board_vendor == "CentOS")
6. 综合练习1
案例需求
- 创建一个名为
inventory
的主机清单 - 创建主机组
dev
,包含serverb - 创建主机组
prod
,包含serverc、serverd - 创建一个名为
/home/student/ansible/packages.yml
的palybook - 将 php 和 mariadb 软件包安装到
dev、test、prod
主机组中 - 将
RPM Development Tools
软件包组 安装到dev
主机组中的主机上 - 将
dev
主机组中的主机上的所有软件包更新为最新版本
[Step1]:
创建主机清单
vim inventory
# 写入下列内容
[dev]
serverb
[prod]
serverc
serverd
[Step2]:
验证条件语句:通过查看group_names魔法变量可以看到主机所在的驱主机组
ansible serverb -m debug -a var=group_names
[Step3]:
编写playlook
vim package.yml
# 写入下列内容
---
- name: play1
hosts: dev,prod
tasks:
- name: Install php and mariadb
ansible.builtin.yum:
name: "{{ item }}" # 递归提取loop字段中的值
state: latest
loop:
- php
- mariadb
- name: Install the 'RPM Development tools' package group
ansible.builtin.yum: # 安装软件包组
name: "@RPM Development Tools"
state: present
when: inventory_hostname in groups.dev # 当主机存在dev组中才执行
- name: Upgrade all packages # 更新所有的软件包
ansible.builtin.yum:
name: '*'
state: latest
when: inventory_hostname in groups.dev # 当主机存在dev组中才执行
[Step4]:
校验playlook语法
ansible-navigator run package.yml -m stdout --syntax-check
[Step4]:
运行playlook
ansible-navigator run package.yml -m stdout
7. 综合练习2
修改文件内容
-
按照下方所述,创建一个名为 /home/greg/ansible/issue.yml的 playbook
-
该 playbook 将在所有清单主机上运行,主机清单引用综合练习1清单
-
该 playbook 会将 /etc/issue 的内容替换为下方所示的一行文本:
-
在 dev 主机组中的主机上,这行文本显示 为:Development
-
在 prod 主机组中的主机上,这行文本显示 : Production
[Step1]:
分别在三台主机上创建/etc/issue文件
ssh root@serverb "echo 111 > /etc/issue"
ssh root@serverc "echo 111 > /etc/issue"
ssh root@serverd "echo 111 > /etc/issue"
[Step2]:
编写playbook
vim issue.yml
# 写入下列内容
---
- name: play1
hosts: all
tasks:
- name: Copy Text for dev
ansible.builtin.copy:
content: "Development"
dest: /etc/issue.yml
when: inventory_hostname in groups.dev
- name: Copy Text for prod
ansible.builtin.copy:
content: "Production"
dest: /etc/issue.yml
when: inventory_hostname in groups.prod
[Step4]:
校验playlook语法
ansible-navigator run issue.yml -m stdout --syntax-check
[Step5]:
运行playbook
ansible-navigator run issue.yml -m stdout
[Step6]:
验证:查看所有主机的文件内容
ssh root@serverb "cat /etc/issue.yml"
ssh root@serverc "cat /etc/issue.yml"
ssh root@serverd "cat /etc/issue.yml"