- 环境准备
- 环境说明
- 考试技巧
- RHCE核心知识总结
- 真题练习
- 然后可以在其他主机上查看文件验证是否完成任务
- 14. 编写剧本为受管机批量创建用户,要求使用保险库中的密码
- 15. 重设保险库密码
- 新增练习
- vim /home/alice/ansible/jihuarenwu.yml
环境准备
rht-vmctl reset control
rht-vmctl reset node1
rht-vmctl reset node2
rht-vmctl reset node3
rht-vmctl reset node4
rht-vmctl reset node5
然后ssh control主机,如果可以yum -y install ansible 就不用下列操作
如果ssh control主机之后yum不能用,要按下列操作还原环境
真实主机:
mount /iso/rhel-8.2-x86_64-dvd.iso /var/ftp/rhel
ln -s /var/ftp/rhel /var/www/html/rhel8.2
ln -s /var/ftp/rhel /var/www/html/rhel8
scp /linux-soft/2/ansible_soft.tar.gz con: //拷贝ansible软件包control主机管理员家目录
control主机:
yum repolist -v //查看下yum,应该就可以用了
cd
yum -y install tar
tar -xf ansible_soft.tar.gz
cd ansible_soft
yum -y install *.rpm //安装ansible
另外
ls /var/www/html/materials # 要有 hardware.empty name_list.yml newhosts.j2 topsec.yml 这个几个文件
ls /var/www/html/roles # 要有 haproxy.tar myphp.tar 这几个文件,如果上述文件没有,去网盘里找ce素材.zip
——————————————————————————————————————————-
ansible的控制主机和被控主机都可以选择不同的用户,考试时
很可能是第二种,也就是用普通用户指挥远程主机时也用普通用户
控制主机root —————————> 被控主机root
控制主机alice ————————-> 被控主机alice
——————————————————————————————————————————-
环境说明
真机(RHEL8.2)
server1.lab0.example.com 172.25.0.254/24
# 预设 root 口令为 tedu
# 提供 RHEL8 软件源 http://server1.lab0.example.com/rhel8/BaseOS
# 提供 RHEL8 软件源 http://server1.lab0.example.com/rhel8/AppStream
# 提供 DNS 服务,为区域 lab0.example.com 中相关站点提供解析
# 提供 NTP 网络时间服务;提供 NFS 文件服务,共享/rhome/ldapuser0 目录
虚拟机 control(RHEL8.2) —— 控制机
control.lab0.example.com 172.25.254.100/24
# 可从 server1 免密 SSH 登录到 root 用户,已预设授权 sudo 用户 alice
# 预设 IP 地址 172.25.254.100/24,已做好主机名映射
虚拟机 node1~node5(RHEL8.2) —— 受管机:
node[1-5].lab0.example.com 172.25.254.10[1-5]/24
# 预设授权 sudo 用户 alice,可从控制机 control 免密 SSH 登录
# 预设 IP 地址 172.25.254.101~105/24,已做好主机名映射
其他信息:
除非另有指定,否则所有工作都需要归属在控制机的 /home/alice/ansible/ 目录下
考试技巧
ansible-doc -l | grep 关键字 # 可以查询模块名
ansible-doc 模块名 搜索/EXAM # 可以查询模块的使用模板
多利用查询和复制功能,避免手敲命令出错
RHCE核心知识总结
- Ansible是一款简洁、高效的运维自动化工具。
- 将ansible安装在主控机器上,就可以通过SSH协议实现针对大量受管服务器的批量化、剧本化的管理。
- ansible 使用 ssh 命令远程管理目标主机,必须确保管理主机能够免密登录目标主机(或在配置文件中提供root密码)
ansible.cfg 加载顺序:
- ANSIBLE_CONFIG 环境变量
- 当前目录下 ansible.cfg
- /etc/ansible/ansible.cfg
ansible运行的 2 种方式:
- 1、adhoc 命令行: ansible 组名称,主机 -m 模块名称 -a 模块的参数
- 2、playbook方式: ansible-playbook 你编写的文件.yaml
yaml 核心语法:
- 以空格缩进表示层级结构,同级别的参数要缩进对齐
- 键值对使用 “: “ 作为分隔符,数组使用 “- “ 作为分隔符(注意:冒号和减号后面都有空格)
ansible 调用角色就是调用编写好的 playbook,一般一个角色就是一个 目录,创建角色目录使用 ansible-galaxy init 目录名称
查询系统facts变量的方法有:
ansible node1 -m setup
ansible localhost -m debug -a ‘var=hostvars[“localhost”]’
- ansible 判断使用 when 语法
- ansible 循环使用 loop 语法
- ignore_errors: True 用来忽略错误继续执行
- block 要执行的若干语句 要执行的若干语句 rescue 当上面的 块 执行失败的时候,执行这里的语句 当上面的 块 执行失败的时候,执行这里的语句 always 总会被执行,不管上面执行失败还是正确
真题练习
01. 安装和配置 ansible 环境
1)安装所需软件包
2)在/home/alice/ansible/inventory 文件中设置主机清单,要求:
node1 属于 test01 主机组
node2 属于 test02 主机组
node3 和 node4 属于 web 主机组
node5 属于 test05 主机组
web 组属于 webtest 主机组
3)在/home/alice/ansible 目录中创建 ansible.cfg,满足以下需求:
主机清单文件为 /home/alice/ansible/inventory
playbook 中角色位置为 /home/alice/ansible/roles
解题思路
1)安装软件包可以使用 yum ,在control主机安装ansible即可,但考试时候给的是普通用户,可以使用 sudo 提权
2)按照题目要求创建自定义目录,并且配置 ansible.cfg 文件
- /etc/ansible/ansible.cfg //从默认配置文件,复制配置,多使用关键字查询
- defaults:remote_user(使用哪个用户控制);inventory;roles_path;host_key_checking
- privilege_escalation(找到直接粘贴即可):become;become_method;become_user;become_ask_pass
3)创建主机清单,注意[webtest:children]拼写
ansible.cfg 加载顺序
1,ANSIBLE_CONFIG 环境变量 2,当前目录下 3,/etc/ansible/ansible.cfg
解题参考
[alice@control ~]$ sudo yum install -y ansible
... ...
Installed:
ansible-2.8.5-2.el8.noarch python3-babel-2.5.1-5.el8.noarch
python3-jinja2-2.10.1-2.el8_0.noarch python3-jmespath-0.9.0-11.el8.noarch
python3-markupsafe-0.23-19.el8.x86_64 python3-pytz-2017.2-9.el8.noarch
python3-pyyaml-3.12-12.el8.x86_64 python3-setuptools-39.2.0-5.el8.noarch
sshpass-1.06-9.el8.x86_64
Complete!
[alice@control ~]$ mkdir ansible
[alice@control ~]$ vim ansible/ansible.cfg # 该配置文件中的所有配置参数都可以在 /etc/ansible/ansible.cfg 中找到
[defaults]
inventory = /home/alice/ansible/inventory # 主机分组配置列表
roles_path = /home/alice/ansible/roles # 角色目录
host_key_checking = False # 关闭sshkey检查,防止第一次输入 yes 时候卡住
remote_user = alice # 管理远程主机使用的用户
[privilege_escalation] # 普通用户提权配置
become = True # 执行操作前先自动提权
become_method = sudo # 提权使用的命令
become_user = root # 提权的目标用户
become_ask_pass = False # 是否需要输入密码,False无需输入密码
[alice@control ~]$ vim ansible/inventory
[test01]
node1
[test02]
node2
[web]
node3
node4
[test05]
node5
[webtest:children]
web
[alice@control ~]$ mkdir ansible/roles
验证方案
[alice@control ~]$ id
uid=1000(alice) gid=1000(alice) groups=1000(alice)
[alice@control ~]$ cd ~/ansible/
[alice@control ansible]$ ansible localhost -m debug -a 'var=groups'
localhost | SUCCESS => {
"groups": {
"all": [
"node1",
"node2",
"node5",
"node3",
"node4"
],
"test01": [
"node1"
],
"test02": [
"node2"
],
"test05": [
"node5"
],
"ungrouped": [],
"web": [
"node3",
"node4"
],
"webtest": [
"node3",
"node4"
]
}
}
[alice@control ansible]$ ansible all -m ping
node5 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
node3 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
node4 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
node2 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
02. 创建和运行 Ansible 临时命令
编写脚本 /home/alice/ansible/adhoc.sh,用来为所有受管机配置 2 个 yum 仓库。
仓库 1:
- 名称为 BASE,描述为 software base
- URL 为 http://study.lab0.example.com/rhel8/BaseOS
- GPG 签名启用,GPG 秘钥 URL 为 http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release
- 仓库为启用状态
仓库 2:
- 名称为 STREAM,描述为 software stream
- URL 为 http://study.lab0.example.com/rhel8/AppStream
- GPG 签名启用,GPG 秘钥 URL 为 http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release
- 仓库为启用状态
解题思路
- 在adhoc.sh脚本中为多个机器配置服务需要使用 ansible 命令
- yum 仓库的配置模块为 yum_repository
模块的名称可以通过命令 ansible-doc -l |grep yum 进行查找
- 使用 ansible-doc yum_repository 查看帮助案例完成编写命令
模块选项使用 ansible-doc 模块名查找(name;description;baseurl;gpgcheck;gpgkey;enabled)
解题参考
[alice@control ansible]$ vim adhoc.sh
#!/bin/bash
ansible all -m yum_repository -a 'name=BASE description="software base" baseurl=http://study.lab0.example.com/rhel8/BaseOS gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release enabled=yes'
ansible all -m yum_repository -a 'name=STREAM description="software stream" baseurl=http://study.lab0.example.com/rhel8/AppStream gpgcheck=yes gpgkey=http://study.lab0.example.com/rhel8/RPM-GPG-KEY-redhat-release enabled=yes'
[alice@control ansible]$ chmod +x adhoc.sh
[alice@control ansible]$ ./adhoc.sh
验证方案
执行的结果全部为绿色成功
可以使用 yum repolist 验证
- ansible all -m shell -a “ yum repolist -v | tail -1 “
在node1~node5可以看见Total packages:7040 yum包源数量
03. 编写剧本远程安装软件
创建名为/home/alice/ansible/tools.yml 的 playbook,能够实现以下目的:
1)将 php 和 tftp 软件包安装到 test01、test02 和 web 主机组中的主机上
2)将 RPM Development Tools 软件包组安装到 test01 主机组中的主机上
3)将 test01 主机组中的主机上所有软件包升级到最新版本
解题思路
- 题目要求在不同的分组中安装不同的软件包,需要书写多个 play
- 安装升级软件包需要使用 yum 模块(使用 ansible-doc yum 查看案例)
解题参考
```shell [alice@control ansible]$ vim tools.yml - hosts: test01, test02, web
tasks:
- yum: pkg=”php,tftp” state=present //安装 php 和 tftp 软件包
hosts: test01 tasks:
剧本跑完后, 所有执行结果中 failed=0
到node1~5等主机上检查
[root@node1 ~]# rpm -q php //剧本跑完后到node1等主机上检查 [root@node1 ~]# rpm -q tftp [root@node1 ~]# yum grouplist //查包组 Installed Groups: //已经安装的包 RPM Development Tools
04. 安装并使用系统角色
安装 RHEL 角色软件包,并创建剧本 /home/alice/ansible/timesync.yml,满足以下要求:
1)在所有受管理节点运行
2)使用 timesync 角色
3)配置该角色,使用时间服务器 172.25.254.250,并启用 iburst 参数解题思路
- 需使用yum安装rhel-system-roles软件包,会生成/usr/share/ansible/roles/rhel-system-roles.timesync,将其拷贝到已建好的roles目录下
- 忘记包名的话 yum list | grep roles # 查询一下roles是有关的包
- 角色目录下会有README.md帮助文档,找到Example处,可作参考
- 除了(timesync)时间同步角色,rhel系统中selinux角色也要重点练习
vim roles/rhel-system-roles.timesync/README.md //查看帮助文件,大概 # 在76行,然后将下面这些内容复制到题目要求的剧本中稍加改编即可 vars: timesync_ntp_servers: - hostname: foo.example.com iburst: yes
解题参考
```shell [alice@control ~]$ cd ~alice/ansible [alice@control ansible]$ sudo yum list|grep roles # 查找角色软件包 rhel-system-roles.noarch 1.0-10.el8_1 appstream [alice@control ansible]$ sudo yum install -y rhel-system-roles.noarch # 安装软件包 [alice@control ansible]$ rpm -ql rhel-system-roles.noarch # 查找系统角色的安装路径,并拷贝到 ansible\roles 目录下 /usr/share/ansible /usr/share/ansible/roles … … [alice@control ansible]$ cp -a /usr/share/ansible/roles/rhel-system-roles.timesync ~/alice/ansible/roles/ [alice@control ansible]$ cat roles/rhel-system-roles.timesync/README.md # 通过帮助文件查询使用方法 [alice@control ansible]$ vim timesync.yml
hosts: all vars: timesync_ntp_servers: # 设置 NTD 服务器变量
- hostname: 172.25.254.250 iburst: yes
roles:
该题的playbook运行时会有报错,但是会忽略,属于正常现象
然后去node1~node5检查/etc/chrony.conf 可以看到server 172.25.254.250 iburst,使用 chronyc sources -v 来验证时间是否同步成功,使用命令ansible all -m shell -a “chronyc sources -v”
05. 通过 galaxy 安装角色
创建剧本 /home/alice/ansible/roles/down.yml,用来从以下 URL 下载角色,并安装到 /home/alice/ansible/roles 目录下:
http://study.lab0.example.com/roles/haproxy.tar 此角色名为 haproxy
http://study.lab0.example.com/roles/myphp.tar 此角色名为 myphp
解题思路
角色的本质就是一个目录,安装角色就是下载别人写好的 playbook 存放到指定的位置
知识拓展
ansible-galaxy
- 连接galaxy.ansible.com下载相应的roles(角色)
roles(角色):就是一堆playbook的集合
- 连接galaxy.ansible.com下载相应的roles(角色)
ansible-galaxy list会查看三个地方的role文件:
- ./roles
- /usr/share/ansible/role
- /etc/ansible/roles
- 创建角色
ansible-galaxy install下载安装角色
- -r 指定导入的角色列表的文件
- -p 指定角色的目录路径,默认问ansible.cfg中配置的路径
解题参考
[alice@control ansible]$ vim /home/alice/ansible/roles/down.yml //配置角色导入信息
- name: haproxy
src: http://study.lab0.example.com/roles/haproxy.tar
- name: myphp
src: http://study.lab0.example.com/roles/myphp.tar
[alice@control ansible]$ ansible-galaxy install -r roles/down.yml //导入角色
验证方案
查看到 successfully 以后可以查看是否有目录创建
[alice@control ansible]$ ls roles/
down.yml haproxy myphp rhel-system-roles.timesync
06. 创建及使用自定义角色
根据下列要求,在/home/alice/ansible/roles 中创建名为 httpd 的角色:
- 1)安装 httpd 软件,并能够开机自动运行
- 2)开启防火墙,并允许 httpd 通过
- 3)使用模板 index.html.j2,用来创建/var/www/html/index.html 网页,内容如下(其 中,HOSTNAME 是受管理节点的完全域名,IPADDRESS 是 IP 地址): Welcome to HOSTNAME on IPADDRESS
然后创建剧本 /home/alice/ansible/myrole.yml,为 webtest 主机组启用 httpd 角色。
解题思路
这道题考的知识点较多:
- 自定义角色,可以使用 ansible-galaxy init 角色名称来创建
- 在角色中定义任务,本质和定义tasks一样,使用 ansible-doc 查找帮助信息,编写 tasks/main.yml 这道题中用到的模块有 yum、template 、service(记得重启服务)、firewalld
- 题目要求使用变量替换,查询系统facts变量的方法有: ansible node1 -m setup / ansible localhost -m debug -a ‘var=hostvars[“localhost”]’
- 变量采用 json 格式显示,不同层级的变量使用 . 作为分隔符,例如ansible_eth0.ipv4.address
解题参考
```shell [alice@control ansible]$ ansible-galaxy init roles/httpd //为新角色创建初始目录结构 [alice@control ansible]$ vim roles/httpd/templates/index.html.j2 //编写角色模板(网页) Welcome to {{ ansible_fqdn }} on {{ ansible_eth0.ipv4.address }} [alice@control ansible]$ vim roles/httpd/tasks/main.yml //编写角色主任务
- yum: pkg=httpd state=present //装 httpd 包
- template: src=index.html.j2 dest=/var/www/html/index.html //配置网页
- service: name=httpd state=restarted enabled=yes //起 httpd 服务
- firewalld: service=http state=enabled permanent=yes immediate=yes //配置防火墙,允许访问 web 端口 [alice@control ansible]$ vim myrole.yml //编写启动脚本
hosts: webtest roles:
- httpd
[alice@control ansible]$ ansible-playbook myrole.yml //验证剧本
<a name="l1IIq"></a> ### 验证方案 执行结果 failed=0,使用 curl 访问 webtest 组的主机,查看返回结果 ```shell [alice@control ansible]$ curl http://node3/ Welcome to node3.lab0.example.com on 172.25.254.103 [alice@control ansible]$ curl http://node4/ Welcome to node4.lab0.example.com on 172.25.254.104
07. 使用之前通过 galaxy 下载的角色
创建剧本 /home/alice/ansible/web.yml,满足下列需求:
- httpd
[alice@control ansible]$ ansible-playbook myrole.yml //验证剧本
1)该剧本中包含一个 play,可以在 test05 主机组运行 haproxy 角色(此角色已经配置 好网站的负载均衡服务)
- 2)多次访问 http://node5.lab0.example.com 可以输出不同主机的欢迎页面
- 3)该剧本中包含另一个 play,可以在 webtest 主机组运行 myphp 角色(此角色已经配置 好网站的 php 页面)
4)多次访问 http://node5.lab0.example.com/index.php 也输出不同主机的欢页面
解题思路
一个典型的web负载均衡集群
- webtest web网页静态页面已经在 06 题目配置完成(06 没有做对的,这道题会有问题)
- 本题需要配置一个负载均衡 test05,还需要在 webtest 主机中安装PHP页面支持
- 本题隐藏内容:webtest上题已配置firewalld,test05未配置
- i本题所使用到的ansible模块有 firewalld
解题参考
```shell [alice@control ansible]$ vim web.yml - name: use role B //先部署 web 节点(node3、node4)
hosts: webtest
roles:
- myphp
name: use role A hosts: test05 //再配置负载均衡器(node5) roles:
- haproxy tasks:
- firewalld: service=http state=enabled permanent=yes immediate=yes //配置防火墙,允许访问负载均衡器的 web 端口
[alice@control ansible]$ ansible-playbook web.yml //验证剧本
<a name="nM5YL"></a> ### 验证方案 返回结果中 failed=0,使用 curl 访问负载均衡查看结果 ```shell [alice@control ansible]$ curl http://node5.lab0.example.com Welcome to node3.lab0.example.com on 172.25.254.103 [alice@control ansible]$ curl http://node5.lab0.example.com Welcome to node4.lab0.example.com on 172.25.254.104 [alice@control ansible]$ curl http://node5.lab0.example.com/index.php hello php world from node3.lab0.example.com [alice@control ansible]$ curl http://node5.lab0.example.com/index.php hello php world from node4.lab0.example.com
08. 编写剧本远程管理逻辑卷
创建剧本 /home/alice/ansible/lvm.yml,用来为所有受管机完成以下部署:
1)在卷组 search 中创建名为 mylv 的逻辑卷,大小为 1000MiB
- 2)使用 ext4 文件系统格式化该逻辑卷
- 3)如果无法创建要求的大小,应显示错误信息 insufficient free space,并改为 500MiB
- 4)如果卷组 search 不存在,应显示错误信息 VG not found
- 5)不需要挂载逻辑卷
解题思路
根据题目检查所有结点的磁盘空间剩余情况 ```shell [alice@control ansible]$ ansible all -m shell -a ‘vgs’ node2 | CHANGED | rc=0 >> VG #PV #LV #SN Attr VSize VFree
rhel 1 2 0 wz—n- <49.00g 0 search 1 0 0 wz—n- 664.00m 664.00m
node4 | CHANGED | rc=0 >> VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz—n- <49.00g 0
node1 | CHANGED | rc=0 >> VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz—n- <49.00g 0
node5 | CHANGED | rc=0 >> VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz—n- <49.00g 0 search 1 0 0 wz—n- <1.86g <1.86g
node3 | CHANGED | rc=0 >> VG #PV #LV #SN Attr VSize VFree rhel 1 2 0 wz—n- <49.00g 0
可以总结为三种情况:
1. 有search卷组 够1000M
1. 有search卷组 不够1000M
1. 没有search卷组
首先找出没有search卷组的主机,输出错误信息" VG not found ",使用fail模块(与debug模块相似),输出信息并停止后续任务。<br />然后判断卷组够不够1000M,使用block任务块,创建1000M逻辑卷;如果失败执行救援任务rescue,输出信息" insufficient free space ",划分500M逻辑卷;执行永久任务always,格式化该逻辑卷。
<a name="HXc0L"></a>
### 解题参考
```shell
[alice@control ansible]$ vim lvm.yml
- name: manager volume
hosts: all
tasks:
- name: 1. failed when VG not found
fail: msg="VG not found" # 目标 VG 不存在时报错 ,停止后续任务
when: "'search' not in ansible_lvm.vgs"
- name: 2. lvcreate
block: # 配置指令块
- lvol: lv=mylv size=1000M vg=search force=yes
rescue: # 若块操作失败,则执行补救
- debug: msg="insufficient free space"
- lvol: lv=mylv size=500M vg=search force=yes
always: # 始终需要执行的任务
- filesystem: dev=/dev/search/mylv fstype=ext4 force=yes
[alice@control ansible]$ ansible-playbook lvm.yml # 验证剧本
验证方案
验证结果,这次执行后是有错误的,但根据题目要求,这些错误可以忽略,我们只验证正确的结果即可
[alice@control ansible]$ ansible all -m shell -a 'blkid |grep mylv'
node3 | FAILED | rc=1 >>
non-zero return code
node5 | CHANGED | rc=0 >>
/dev/mapper/search-mylv: UUID="b815ece4-0dc8-4a27-b5aa-c1740a8ea897" TYPE="ext4"
node1 | FAILED | rc=1 >>
non-zero return code
node2 | CHANGED | rc=0 >>
/dev/mapper/search-mylv: UUID="aaf7539f-a6c8-4ce5-a53d-4aeba59aa0ae" TYPE="ext4"
node4 | FAILED | rc=1 >>
non-zero return code
习题拓展
磁盘挂载练习:mount模块
- path: /mnt/dvd
- src: /dev/sr0
- fstype: iso9660,ext4,xfs
- state: present,mounted,unmount
09. 根据模板部署主机文件
1)从 http://study.lab0.example.com/materials/newhosts.j2 下载模板文件
2)完成该模板,用来生成新主机清单(主机的显示顺序没有要求),结构如下
- 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
- ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
- 172.25.254.101 node1.lab0.example.com node1
- 172.25.254.102 node2.lab0.example.com node2
- 172.25.254.103 node3.lab0.example.com node3
- 172.25.254.104 node4.lab0.example.com node4
- 172.25.254.105 node5.lab0.example.com node5
3)创建剧本 /home/alice/ansible/newhosts.yml,它将使用上述模板在 test01 主机组的主 机上生成文件/etc/newhosts
注意事项
只在test01上执行任务无法收集其他主机的hostvars变量,需要先收集所有主机的hostvars变量。
解题思路
- 下载模板查看后发现需要补齐的数据是 node1 … … node5
- 根据模板的扩展名可以知道这个是一个 jinja2 的模板,可以使用 jinja2 循环语法实现
- ansible中特殊变量的使用
- 常见魔法变量:hostvars、groups、group_names、inventory_hostname
- 如果想要输出json数据的某一字典项,则应该用"key.dict"或"key['dict']"的方式引用,例如hostvars['node1']或hostvars.node1或hostvars[item](item为变量)
- 使用filter可以筛选指定的facts信息,ansible localhost -m setup -a "filter=*ipv4"
- jinja2基本语法介绍
- when判断语法
- 条件判断
{% if daxin.safe %}
daxin is safe.
{% elif daxin.dead %}
daxin is dead
{% else %}
daxin is okay
{% endif %}
- 循环结构
{% for file in filenames %}
# 取值
{{ file }}
{% endfor %}
- 我们可以通过循环 inventory 文件配置模板
- 为了能够让模板顺利执行,拷贝模板使用 template 模块
解题参考
[alice@control ansible]$ sudo yum -y install wget [alice@control ansible]$ wget http://study.lab0.example.com/materials/newhosts.j2 [alice@control ansible]$ vim newhosts.j2 # 制作 J2 动态模板文件 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 {% for id in groups.all %} {{hostvars[id].ansible_eth0.ipv4.address}} {{hostvars[id].ansible_fqdn}} {{hostvars[id].ansible_hostname}} {% endfor %} [alice@control ansible]$ vim newhosts.yml - hosts: all //搜集所有主机的信息 - hosts: test01 //只为 xx 主机组部署 tasks: - template: src=newhosts.j2 dest=/etc/newhosts force=yes # 通过模板部署文件 [alice@control ansible]$ ansible-playbook newhosts.yml # 验证剧本 # 然后可以在node1主机上查看文件验证是否完成任务
验证方案
返回状态 failed=0,到目标主机查看文件即可[alice@control ansible]$ ssh node1 Last login: Sat Jun 19 01:28:23 2021 from 172.25.254.100 [alice@node1 ~]$ sudo cat /etc/newhosts 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 172.25.254.101 node1.lab0.example.com node1 172.25.254.102 node2.lab0.example.com node2 172.25.254.105 node5.lab0.example.com node5 172.25.254.103 node3.lab0.example.com node3 172.25.254.104 node4.lab0.example.com node4
习题拓展
魔法变量:group.all、hostvars(所有变量)10. 编写剧本修改远程文件内容
创建剧本 /home/alice/ansible/newissue.yml,满足下列要求:
1)在所有清单主机上运行,替换/etc/issue 的内容
2)对于 test01 主机组中的主机,/etc/issue 文件内容为 test01
3)对于 test02 主机组中的主机,/etc/issue 文件内容为 test02
4)对于 web 主机组中的主机,/etc/issue 文件内容为 Webserver解题思路
- 在所有主机上运行,不同主机写入不同的数据,这里考察的是 判断 语法的使用
- 在主机上运行应该判断当前主机所在的组可以通过 主机名称 in groups.组名称判断
- 本题只用到了 copy 模块
解题参考
```shell [alice@control ansible]$ vim newissue.yml - name: deploy /etc/issue
hosts: all
tasks:
- copy: content=”test01” dest=/etc/issue force=yes when: (‘test01’ in group_names) //如果所在组包括 test01
- copy: content=”test02” dest=/etc/issue force=yes when: (‘test02’ in group_names) //如果所在组包括 test02
- copy: content=”Webserver” dest=/etc/issue force=yes
when: (‘web’ in group_names) //如果所在组包括 web
[alice@control ansible]$ ansible-playbook newissue.yml //验证剧本
**方法二:**
shell [alice@control ansible]$ vim newissue.yml
- name: 修改issue文件
hosts: all
tasks:
- name: 修改配置文件
copy:
content: |
dest: /etc/issue when: ‘group_names | intersect([“test01”,”test02”,”web”])’{% if "web" in group_names %} Webserver {% elif "test01" in group_names %} test01 {% elif "test02" in group_names %} test02 {% endif %}
**方法三:**
shell [alice@control ansible]$ vim newissue.yml
- name: 修改配置文件
copy:
content: |
- name: deploy /etc/issue
hosts: all
tasks:
- template: src=newissue.j2 dest=/etc/issue force=yes # 根据模板部署远程文件
[alice@control ansible]$ vim newissue.j2 # 编写模板内容
{% if “test01” in group_names %} //如果所在组包括 test01
test01
{% elif “test02” in group_names %} //如果所在组包括 test02
test02
{% elif “web” in group_names %} //如果所在组包括 web
Webserver
{% endif %}
[alice@control ansible]$ ansible-playbook newissue.yml //验证剧本
```
验证方案
failed=0 没有报错,到目标结点查看 issue 的文件内容 ```shell [alice@control ansible]$ ansible all -m shell -a ‘cat /etc/issue’ node2 | CHANGED | rc=0 >> test02
- template: src=newissue.j2 dest=/etc/issue force=yes # 根据模板部署远程文件
[alice@control ansible]$ vim newissue.j2 # 编写模板内容
{% if “test01” in group_names %} //如果所在组包括 test01
test01
{% elif “test02” in group_names %} //如果所在组包括 test02
test02
{% elif “web” in group_names %} //如果所在组包括 web
Webserver
{% endif %}
[alice@control ansible]$ ansible-playbook newissue.yml //验证剧本
```
node5 | CHANGED | rc=0 >> \S Kernel \r on an \m
node4 | CHANGED | rc=0 >> Webserver
node3 | CHANGED | rc=0 >> Webserver
node1 | CHANGED | rc=0 >> test01
<a name="s11F6"></a>
## 11. 编写剧本部署远程 Web 目录
创建剧本 /home/alice/ansible/webdev.yml,满足下列要求:
- 1)在 test01 主机组运行
- 2)创建目录/webdev,属于 webdev 组,常规权限为 rwxrwxr-x,具有 SetGID 特殊权限
- 3)使用符号链接/var/www/html/webdev 链接到/webdev 目录
- 4)创建文件/webdev/index.html,内容是 It's works!
- 5)查看 test01 主机组的 web 页面 http://node1/webdev/ 将显示 It's works!
<a name="nZlTP"></a>
### 解题思路
- 创建文件、目录、链接使用 file 模块完成
- 注意隐藏需求:
- 创建webdev组、安装http软件包、http服务开机自启、防火墙和selinux(注意之前的题目要求是否要求selinux开启)
- 如果要求selinux开启:
- 因为网页文件使用软连接,所以selinx任务不安全,需进行修改
- - shell: chcon -R -t httpd_sys_content_t /webdev
- chcon命令的-R参数是递归全部子目录和文件
- chcon命令的-t参数是添加一个类型
- 使selinux认为该文件为httpd的文件
- 用到的模块 group、file、copy、service、firewalld、shell
- 设置权限时因为涉及特殊权限,所以开头不为0,
- 1代表 Sticky bit
- 2代表 SetGID
- 4代表 SetUid
- 6代表 同时设置 SetUid 和SetGID
<a name="GegvI"></a>
### 解题参考:
```shell
[alice@control ansible]$ vim webdev.yml
- name: Prepare Web Directory
hosts: test01
tasks:
- yum: name=httpd state=present //装 httpd 包
- group: name=webdev state=present //配置组账号
- file: name=/webdev group=webdev mode=2775 state=directory //配置目录
- file: src=/webdev name=/var/www/html/webdev state=link force=yes //配置链接
- copy: content="It's works!" dest=/webdev/index.html force=yes //配置网页
- firewalld: service=http state=enabled permanent=yes immediate=yes //配置防火墙
- service: name=httpd state=restarted enabled=yes //起 httpd 服务
- command: setenforce 0 //取消 SELinux 限制
- command: sed -i '/^SELINUX=/cSELINUX=Permissive' /etc/selinux/config //永久取消
[alice@control ansible]$ ansible-playbook webdev.yml //验证剧本
验证方案
安装正常 failed=0,访问 node1 查看页面
[alice@control ansible]$ curl http://node1/webdev/
It's works!
12. 编写剧本为受管机生成硬件报告
创建名为/home/alice/ansible/hardware.yml 的 playbook,满足下列要求:
1)使所有受管理节点从以下 URL 下载文件:
http://study.lab0.example.com/materials/hardware.empty
2)并用来生成以下硬件报告信息,存储在各自的/root/hardware.txt 文件中
- 清单主机名称
- 以 MB 表示的总内存大小
- BIOS 版本
- 硬盘 vda 的大小
- 硬盘 vdb 的大小
其中,文件的每一行含有一个 key=value 对,如果项目不存在,则显示 NONE。
解题思路
- 远程下载文件使用 get_url ,修改文件使用 replace ,该题主要考察 facts 变量值的获取,可以使用循环简化文件
- 该题目用到的知识 loop 循环,get_url、replace 模块
- 判断变量是否存在可用 {{ 变量 if ‘变量关键字’ in 变量 else ‘输出文本’ }} 或者 {{ 变量 if 变量 is defined else ‘输出文本’ }}/
解题参考
```shell [alice@control ansible]$ vim hardware.yml - name: hardware report
hosts: all
vars:
- host: “{{inventory_hostname}}” //提取清单主机名
- mem: “{{ansible_memtotal_mb}}” //提取总内存大小(MB)
- bios: “{{ansible_bios_version}}” //提取 BIOS 版本
- vdasize: “{{ansible_devices.vda.size}}” //提取磁盘 vda 大小
- vdbsize: “{{ansible_devices.vdb.size if ansible_devices.vdb.size is defined else ‘NONE’ }}” //提取磁盘 vdb 大小,或 NONE tasks: //制作硬件报告
- get_url: url=http://study.lab0.example.com/materials/hardware.empty dest=/root/hardware.txt force=yes
- replace: path=/root/hardware.txt regexp=inventoryhostname replace={{host}}
- replace: path=/root/hardware.txt regexp=memory_in_MB replace={{mem}}
- replace: path=/root/hardware.txt regexp=BIOS_version replace={{bios}}
- replace: path=/root/hardware.txt regexp=disk_vda_size replace={{vdasize}}
- replace: path=/root/hardware.txt regexp=disk_vdb_size replace={{vdbsize}}
[alice@control ansible]$ ansible-playbook hardware.yml //验证剧本
然后可以在其他主机上查看文件验证是否完成任务
**方法二:**
shell [alice@control ansible]$ vim hardware.yml
- name: 在远程下载模板文件
hosts: all
tasks:
- name: 下载文件hardware.empty get_url: url: http://study.lab0.example.com/materials/hardware.empty dest: /root/hardware.txt
- name: 修改模板文件中参数的值
replace:
path: /root/hardware.txt
regexp: “{{ item.k }}”
replace: “{{ item.v }}”
loop:
- k: inventoryhostname v: “{{ inventory_hostname }}”
- k: memory_in_MB v: “{{ ansible_memtotal_mb | string }}”
- k: BIOS_version v: “{{ ansible_bios_version }}”
- k: disk_vda_size v: “{{ ansible_devices.vda.size if ‘vda’ in ansible_devices else ‘NONE’ }}”
- k: disk_vdb_size
v: “{{ ansible_devices.vdb.size if ‘vdb’ in ansible_devices else ‘NONE’ }}”
```
验证方案
结果正常 failed=0,查看生成的文件 ```shell [alice@control ansible]$ ansible all -m shell -a ‘cat /root/hardware.txt’ node3 | CHANGED | rc=0 >> hostname=node3 mem=979 bios=1.11.1-4.module+el8.1.0+4066+0f1aadab vdasize=50.00 GB vdbsize=NONE
node1 | CHANGED | rc=0 >> hostname=node1 mem=979 bios=1.11.1-4.module+el8.1.0+4066+0f1aadab vdasize=50.00 GB vdbsize=NONE
node4 | CHANGED | rc=0 >> hostname=node4 mem=979 bios=1.11.1-4.module+el8.1.0+4066+0f1aadab vdasize=50.00 GB vdbsize=2.00 GB
node2 | CHANGED | rc=0 >> hostname=node2 mem=979 bios=1.11.1-4.module+el8.1.0+4066+0f1aadab vdasize=50.00 GB vdbsize=1.00 GB
node5 | CHANGED | rc=0 >> hostname=node5 mem=979 bios=1.11.1-4.module+el8.1.0+4066+0f1aadab vdasize=50.00 GB vdbsize=5.00 GB
<a name="ujZ3W"></a>
## 13. 创建保险库文件
1)创建 ansible 保险库 /home/alice/ansible/passdb.yml,其中有 2 个变量:
- pw_dev,值为 ab1234
- pw_man,值为 cd5678
2) 加密和解密该库的密码是 pwd@1234 ,密码在/home/alice/ansible/secret.txt 中
<a name="RGvtE"></a>
### 解题思路
- ansilbe加密使用 ansible-vault 命令
<a name="GA78E"></a>
### 解题参考
```shell
[alice@control ansible]$ vim passdb.yml
---
pw_dev: ab1234
pw_man: cd5678
[alice@control ansible]$ echo 'pwd@1234' >secret.txt
[alice@control ansible]$ chmod 0600 secret.txt
[alice@control ansible]$ ansible-vault encrypt --vault-id=secret.txt passdb.yml
Encryption successful
方法二:
[alice@control ansible]$ echo 'pwd@1234' > secret.txt //创建保险库钥匙文件
[alice@control ansible]$ ansible-vault create passdb.yml --vault-password-file=secret.txt
pw_dev: ab1234 //创建保险库文件
pw_man: cd5678
验证方案
查看文件已经被加密了
[alice@control ansible]$ cat passdb.yml
$ANSIBLE_VAULT;1.1;AES256
.......
14. 编写剧本为受管机批量创建用户,要求使用保险库中的密码
从以下 URL 下载用户列表,保存到/home/alice/ansible 目录下:
创建剧本 /home/alice/ansible/users.yml 的 playbook,满足下列要求:
- 1)使用之前题目中的 passdb.yml 保险库文件
- 2)职位描述为 dev 的用户应在 test01、test02 主机组的受管机上创建,从 pw_dev 变量 分配密码,是补充组 devops 的成员
- 3)职位描述为 man 的用户应在 web 主机组的受管机上创建,从 pw_man 变量分配密码,是 补充组 opsmgr 的成员
4)该 playbook 可以使用之前题目创建的 secret.txt 密码文件运行
解题思路
这道题的逻辑关系较强,需要我们明确逻辑关系,伪代码如下:
if (职位描述 == dev) and (主机组 == test01 or 主机组 == test02) { 创建用户,使用 pw_dev 作为密码 } if (职位描述 == man) and (主机组 == web) { 创建用户,使用 pw_man 作为密码 }
本题用到的模块有 group、user、使用了过滤器 password_hash
- loop循环使用变量时{{}}要用双引号括起来
解题参考
```shell [alice@control ansible]$ curl -sO http://study.lab0.example.com/materials/name_list.yml [alice@control ansible]$ vim users.yml
- name: 添加用户
hosts: web,test01,test02
vars_files:
- passdb.yml
- name_list.yml tasks:
- name: # 创建附加组
group:
name: “{{ item }}”
state: present
loop:
- devops
- opsmgr
- name: # 添加用户 user: name: “{{ item.name }}” password: “{{ pw_dev | password_hash(‘sha512’) }}” groups: devops when: ‘(“dev” == item.job) and (“web” not in group_names)’ loop: “{{ users }}”
- name: # 添加用户
user:
name: “{{ item.name }}”
password: “{{ pw_man | password_hash(‘sha512’) }}”
groups: opsmgr
when: ‘(“man” == item.job) and (“web” in group_names)’
loop: “{{ users }}”
[alice@control ansible]$ ansible-playbook users.yml —vault-password-file =/home/alice/ansible/secret.txt //验证剧本
**方法二:**
shell [alice@control ansible]$ wget http://study.lab0.example.com/materials/name_list.yml //获取用户列表文件 [alice@control ansible]$ cat name_list.yml //确认列表内容 users:- name: tom job: dev //用户岗位 a
- name: jerry job: man //用户岗位 b [alice@control ansible]$ vim users.yml
name: batch users hosts: test01,test02,web vars_files:
- passdb.yml //加载密码变量
- name_list.yml //加载用户名变量
tasks:
- group: name=devops //确保补充组 1 在指定主机已存在
- group: name=opsmgr //确保补充组 2 在指定主机已存在
- user: name={{item.name}} password={{pw_dev|password_hash(‘sha512’)}} groups=devops when: (item.job == ‘dev’) and (‘test01’ in group_names or ‘test02’ in group_names) loop: “{{users}}” //按条件添加 a 岗用户
- user: name={{item.name}} password={{pw_man|password_hash(‘sha512’)}} groups=opsmgr
when: (item.job == ‘man’) and (‘web’ in group_names)
loop: “{{users}}” //按条件添加 b 岗用户
[alice@control ansible]$ ansible-playbook users.yml —vault-password-file =/home/alice/ansible/secret.txt //验证剧本
<a name="ZhwMF"></a> ### 验证方案 failed=0,使用新添加的用户登录即可,密码在13题文件中 ```shell [alice@control ansible]$ ansible all -m shell -a "cat /etc/passwd | tail -2" # 查看用户是否添加正确 [alice@control ansible]$ ssh -l tom node1 # tom@node1's password: [alice@control ansible]$ ssh -l tom node2 # tom@node2's password: [alice@control ansible]$ ssh -l jerry node3 # jerry@node3's password: [alice@control ansible]$ ssh -l jerry node4 # jerry@node4's password:
15. 重设保险库密码
1)从以下 URL 下载保险库文件到/home/alice/ansible 目录:
http://study.lab0.example.com/materials/topsec.yml
2)当前的库密码是 banana,新密码是 big_banana,请更新该库密码知识点拓展
下载文件可以使用wget或者curl命令
- curl -sO http://study.lab0.example.com/materials/topsec.yml
- wget http://study.lab0.example.com/materials/topsec.yml
- 修改ansible文件密码使用ansible-vault rekey命令
解题参考
[alice@control ansible]$ wget http://study.lab0.example.com/materials/topsec.yml //下载指定保险库文件 [alice@control ansible]$ ansible-vault rekey topsec.yml //为保险库设置新的密码 Vault password: 输入当前的库密码 New Vault password: 输入新的库密码 confirm New Vault password: 再次输入新的库密码确认 Rekey successful
验证方案
用新密码查看文件[alice@control ansible]$ ansible-vault view topsec.yml Vault password: dachui: banana
新增练习
补充1:
安装系统角色,创建playbook /home/alice/ansible/selinux.yml,
要求满足如下条件:
- 在所有被管理主机运行
- 使用selinux角色
- 使用角色配置强制状态运行SElinux
cp -r /usr/share/ansible/roles/rhel-system-roles.selinux/ ~/ansible/roles/selinux cat ~/ansible/roles/selinux/README.md ## Usage The general usage is demonstrated in [selinux-playbook.yml](selinux-playbook.yml) playbook. ### selinux role This role can be configured using variables as it is described below. ```yaml vars: [ see below ] roles: - role: rhel-system-roles.selinux become: true
对于设置SELinux配置而言,有两个变量,最终得出结论答案: ```shell vim ~/ansible/selinux.yml这里说明了使用selinux角色的用法是先写变量vars,具体变量看下面的内容【see below】 然后再通过roles调用角色,后面是角色的名称 ```shell #### set SELinux policy type and mode ```yaml selinux_policy: targeted selinux_state: enforcing ```. Allowed values for `selinux_state` are `disabled`, `enforcing` and `permissive`.
- hosts: all vars: selinux_policy: targeted selinux_state: enforcing roles: