跳到主要内容

RHCE9练习题 (EX294)

· 阅读需 24 分钟

Lab环境

FQDNDescriptionIP AddressesRoles
control.lab.example.comcontrol172.25.250.254ansible control node
classroom.lab.example.comclassroom172.25.250.254materials
content.lab.example.comcontent172.25.250.254YUM repo
node1.lab.example.comnode1172.25.250.9ansible managed node
node2.lab.example.comnode2172.25.250.10ansible managed node
node3.lab.example.comnode3172.25.250.11ansible managed node
node4.lab.example.comnode4172.25.250.12ansible managed node
node5.lab.example.comnode5172.25.250.13ansible managed node
utility.lab.example.comutilit172.25.250.220utility

1. 安装和配置 Ansible

在控制节点 control 上安装并配置 Ansible,要求如下:

  1. 安装所需软件包。
  2. 创建一个静态清单文件 /home/greg/ansible/inventory,满足以下条件:
    • node1dev 主机组的成员。
    • node2test 主机组的成员。
    • node3node4prod 主机组的成员。
    • node5balancers 主机组的成员。
    • prod 组是 webservers 主机组的成员。
  3. 创建配置文件 /home/greg/ansible/ansible.cfg,满足以下要求:
    • 主机清单文件路径为 /home/greg/ansible/inventory
    • playbook中角色的位置包括 /home/greg/ansible/roles
    • 自定义collection目录为 /home/greg/ansible/mycollection
ssh greg@control
# 安装软件包
sudo yum -y install ansible-core ansible-navigator

# 创建所需文件目录
mkdir -p /home/greg/ansible/roles
mkdir /home/greg/ansible/mycollection
cd ansible/

# 生成配置文件
ansible-config init --disabled > /home/greg/ansible/ansible.cfg
vim ansible.cfg

[defaults]
inventory = /home/greg/ansible/inventory
remote_user = greg
host_key_checking = False
roles_path = /home/greg/ansible/roles:/usr/share/ansible/roles
collections_path = ./mycollection/:.ansible/collections:/usr/share/ansible/collections
[privilege_escalation]
become=True

# 确认配置文件
ansible --version
ansible-galaxy list

# 创建清单文件
vim /home/greg/ansible/inventory

[dev]
node1
[test]
node2
[prod]
node3
node4
[balancers]
node5
[webservers:children]
prod

# 确认清单文件的正确性
ansible-inventory --graph
# ping测试
ansible all -m ping

考试过程可以使用ansible-navigator,如要用ansible-navigator先登陆podman并验证一下。

podman login utility.lab.example.com -u admin -p redhat
ansible-navigator images
ansible-navigator collections

2. 配置系统以使用默认存储库

作为系统管理员,您需要在受管节点上安装软件。

请按照正⽂所述,创建一个名为 /home/greg/ansible/yum_repo.yml 的剧本,在各个受管节点上安装 yum 存储库。

# 查找模块名
ansible-doc -l | grep yum
# doc
ansible-doc yum_repository

# 编写playbook
vim /home/greg/ansible/yum_repo.yml

---
- name: Configure YUM repositories
hosts: all
tasks:
- name: Configure EX294_BASE repository
yum_repository:
file: EX294_BASE
name: EX294_BASE
description: "EX294 base software"
baseurl: http://content/rhel9.0/x86_64/dvd/BaseOS
gpgcheck: yes
gpgkey: http://content/rhel9.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
enabled: yes

- name: Configure EX294_STREAM repository
yum_repository:
file: EX294_STREAM
name: EX294_STREAM
description: "EX294 stream software"
baseurl: http://content/rhel9.0/x86_64/dvd/AppStream
gpgcheck: yes
gpgkey: http://content/rhel9.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
enabled: yes
# 执行playbook
ansible-navigator run yum_repo.yml -m stdout

# 验证配置
ansible all -a 'yum repoinfo'
ansible all -a 'yum -y install ftp'
ansible all -a 'rpm -q ftp'

3.安装软件包

创建一个名为 /home/greg/ansible/packages.yml 的playbook,并按以下要求在受管节点上安装软件包:

  1. phpmariadb 软件包安装到 devtestprod 主机组中的主机上。
  2. RPM Development Tools 软件包组安装到 dev 主机组中的主机上。
  3. dev 主机组中主机的所有软件包更新到最新版本。
# doc
ansible-doc yum
# 编写playbook
vim /home/greg/ansible/packages.yml
---
- name: Install php and mariadb
hosts: dev,test,prod
tasks:
- name: Install required packages
yum:
name:
- php
- mariadb
state: present

- name: Install RPM Development Tools and upgrade packages
hosts: dev
tasks:
- name: Install RPM Development Tools group
yum:
name: "@RPM Development Tools"
state: present

- name: Upgrade all packages to the latest version
yum:
name: "*"
state: latest
# 执行playbook
ansible-navigator run packages.yml -m stdout

# 验证
ansible dev,test,prod -a 'rpm -q php mariadb'
ansible dev -a 'yum grouplist'
ansible dev -a 'yum update'

4.使用 RHEL 系统角色

创建一个名为 /home/greg/ansible/selinux.yml 的playbook,满足以下要求:

  1. 所有受管节点 上运行。
  2. 使用 RHEL 提供的 selinux 系统角色。
  3. 将受管节点的 SELinux 配置为 enforcing 模式。
# 查询系统角色包名
yum search role
# 安装
sudo yum -y install rhel-system-roles
# 查看当前可用的system roles
ansible-galaxy list

cp /usr/share/doc/rhel-system-roles/selinux/example-selinux-playbook.yml /home/greg/ansible/selinux.yml
vim selinux.yml
# 显示行号,并删除不需要的内容(不同版本,行号可能有些差异,自己看着删除不需要要的内容)
:set nu
:43,51d
:11,39d

最终内容:

---
- hosts: all
become: true
become_method: sudo
become_user: root
vars:
# Use "targeted" SELinux policy type
selinux_policy: targeted
# Set "enforcing" mode
selinux_state: enforcing

# Prepare the prerequisites required for this playbook
tasks:
- name: execute the role and catch errors
block:
- name: Include selinux role
include_role:
name: rhel-system-roles.selinux
rescue:
# Fail if failed for a different reason than selinux_reboot_required.
- name: handle errors
fail:
msg: "role failed"
when: not selinux_reboot_required

- name: restart managed host
reboot:

- name: wait for managed host to come back
wait_for_connection:
delay: 10
timeout: 300

- name: reapply the role
include_role:
name: rhel-system-roles.selinux
# 执行playbook
# 通过rpm包安装的role,用ansible-playbook执行,通过collection安装的角色用ansible-navigator执行
ansible-playbook selinux.yml
# 验证
ansible all -m shell -a 'grep ^SELINUX= /etc/selinux/config; getenforce'

node3 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node2 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node5 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node1 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing
node4 | CHANGED | rc=0 >>
SELINUX=enforcing
Enforcing

5.配置 Collection

  • http://classroom/materials
    • redhat-insights-1.0.7.tar.gz
    • community-general-5.5.0.tar.gz
    • redhat-rhel_system_roles-1.19.3.tar.gz
  • 上⾯3个collection安装到 /home/greg/ansible/mycollection ⽬录中
vim requirements.yml
---
collections:
- name: http://classroom/materials/redhat-insights-1.0.7.tar.gz
- name: http://classroom/materials/community-general-5.5.0.tar.gz
- name: http://classroom/materials/redhat-rhel_system_roles-1.19.3.tar.gz
# install
ansible-galaxy collection install -r requirements.yml -p /home/greg/ansible/mycollection

# 验证
ansible-navigator collections
ansible-navigator doc community.general.filesystem -m stdout

6.使用Ansible Galaxy 安装角色

使用 Ansible Galaxy 和要求文件(/home/greg/ansible/roles/requirements.yml)。从以下 URL 下载角色并安装到目录 /home/greg/ansible/roles

vim /home/greg/ansible/roles/requirements.yml
---
- src: http://classroom/materials/haproxy.tar
name: balancer
- src: http://classroom/materials/phpinfo.tar
name: phpinfo
# install
ansible-galaxy install -r /home/greg/ansible/roles/requirements.yml
# 验证
ansible-galaxy list

7.创建和使用角色

根据以下要求,在目录 /home/greg/ansible/roles 中创建一个名为 apache 的角色,并满足以下条件:

  • httpd 软件包已安装,设为在 系统启动时启⽤启动
  • 防⽕墙 已启⽤并正在运⾏,并使⽤允许访问 Web 服务器的规则
  • 模板⽂件 index.html.j2 已存在,⽤于创建具有以下输出的⽂件
    • /var/www/html/index.html
      Welcome to HOSTNAME on IPADDRESS
      其中,HOSTNAME 是受管节点的 完全限定域名 , IPADDRESS 则是受管节点的 IP 地址。

创建⼀个名为 /home/greg/ansible/apache.yml 的 playbook:

  • 该 play 在 webservers 主机组中的主机上运⾏并将使⽤ apache ⻆⾊
# 创建角色apache
ansible-galaxy role init --init-path /home/greg/ansible/roles apache
# 编写task
vim /home/greg/ansible/roles/apache/tasks/main.yml
---
- name: Install Apache
yum:
name: httpd
state: latest

- name: Start and enable Apache service
systemd:
name: httpd
state: started
enabled: yes

- name: Start and enable firewalld
systemd:
name: firewalld
state: started
enabled: yes

- name: Configure firewalld to allow HTTP
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes

- name: Deploy index.html template
template:
src: index.html.j2
dest: /var/www/html/index.html
vim /home/greg/ansible/roles/apache/templates/index.html.j2
Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4.address }}

# 编写playbook
vim /home/greg/ansible/apache.yml
---
- name: Deploy Apache role
hosts: webservers
roles:
- apache
# 执行playbook
ansible-navigator run apache.yml -m stdout

# 验证
ansible webservers -a 'systemctl status httpd'
ansible webservers -a 'firewall-cmd --list-all'
ansible webservers --list-hosts
curl http://node3
curl http://node4

8.从 Ansible Galaxy 使用角色

根据下列要求,创建一个名为 /home/greg/ansible/roles.yml 的 playbook:

  • playbook 中包含一个 play,该play在 balancers 主机组中的主机上运行并将使用 balancer 角色。

    • 此角色配置一项服务,以在 webservers 主机组中的主机之间平衡 Web 服务器请求的负载。
    • 浏览到 balancers 主机组中的主机(例如 http://172.25.250.13) 将生成以下输出: Welcome to node3.lab.example.com on 172.25.250.11
    • 重新加载浏览器将从另一 Web 服务器生成输出:
      Welcome to node4.lab.example.com on 172.25.250.12
  • playbook 中包含一个play,该play在 webservers 主机组中的主机上运行并将使用 phpinfo 角色。

    • 请通过 URL /hello.php 浏览到 webservers 主机组中的主机,将生成以下输出:
      Hello PHP World from FQDN
    • 其中 FQDN 是主机的完全限定名称。
    • 示例输出: Hello PHP World from node3.lab.example.com
      另外还有 PHP 配置的各种详细信息,如安装的 PHP 版本等。
  • 同样,浏览到 http://172.25.250.12/hello.php 会生成以下输出:
    Hello PHP World from node4.lab.example.com
    另外还有 PHP 配置的各种详细信息,如安装的 PHP 版本等。

vim /home/greg/ansible/roles.yml
---
- name: Use phpinfo role
hosts: webservers
roles:
- phpinfo

- name: Use balancer role
hosts: balancers
roles:
- balancer
ansible-navigator run /home/greg/ansible/roles.yml -m stdout

# 验证
curl http://172.25.250.13
curl http://node3/hello.php
curl http://node4/hello.php

9.创建和使用逻辑卷

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

  • 创建符合以下要求的逻辑卷:
    • 逻辑卷创建在 research 卷组中。
    • 逻辑卷名称为 data
    • 逻辑卷大小为 1500 MiB
  • 使用 ext4 文件系统格式化逻辑卷。
  • 如果无法创建请求的逻辑卷大小,应显示错误信息,并且应改为使用大小 800 MiB
    Could not create logical volume of that size
  • 如果卷组 research 不存在,应显⽰错误信息
    Volume group done not exist
  • 不要以任何⽅式挂载逻辑卷
# doc
ansible-doc community.general.lvol
ansible-doc community.general.filesystem
ansible-doc debug
ansible-doc stat

vim /home/greg/ansible/lv.yml
---
- name: Create LVM
hosts: all
tasks:
- block:
- name: lv 1500M
community.general.lvol:
vg: research
lv: data
size: 1500
- name: Create ext4
community.general.filesystem:
fstype: ext4
dev: /dev/research/data
rescue:
- name: Could not create lvm
ansible.builtin.debug:
msg: Could not create logical volume of that size
- name: lv 800M
community.general.lvol:
vg: research
lv: data
size: 800
- name: Create ext4
community.general.filesystem:
fstype: ext4
dev: /dev/research/data
when: ansible_lvm.vgs.research is defined
- debug:
msg: Volume group done not exist
when: ansible_lvm.vgs.research is not defined
# 执行playbook
ansible-navigator run /home/greg/ansible/lv.yml -m stdout

# 确认执行过程是否符合预期
PLAY [Create LVM] ***************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node3]
ok: [node5]
ok: [node4]
ok: [node2]
ok: [node1]

TASK [lv 1500M] *****************************************************************************************************************************************************************************************************************************************************************
skipping: [node1]
fatal: [node3]: FAILED! => {"changed": false, "err": " Volume group \"research\" has insufficient free space (31 extents): 47 required.\n", "msg": "Creating logical volume 'data' failed", "rc": 5}
changed: [node2]
changed: [node5]
changed: [node4]

TASK [Create ext4] **************************************************************************************************************************************************************************************************************************************************************
skipping: [node1]
changed: [node5]
changed: [node4]
changed: [node2]

TASK [Could not create lvm] *****************************************************************************************************************************************************************************************************************************************************
ok: [node3] => {
"msg": "Could not create logical volume of that size"
}

TASK [lv 800M] ******************************************************************************************************************************************************************************************************************************************************************
changed: [node3]

TASK [Create ext4] **************************************************************************************************************************************************************************************************************************************************************
changed: [node3]

TASK [debug] ********************************************************************************************************************************************************************************************************************************************************************
skipping: [node2]
skipping: [node5]
ok: [node1] => {
"msg": "Volume group done not exist"
}
skipping: [node3]
skipping: [node4]

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************************************
node1 : ok=2 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
node2 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node3 : ok=4 changed=2 unreachable=0 failed=0 skipped=1 rescued=1 ignored=0
node4 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
node5 : ok=3 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0

# 查看LVS
# - node3, 因为VG空间不足,LV只分配了800M
# - node1, 因为VG不存在,LV创建失败
ansible all -m shell -a 'lvs'

node3 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- 800.00m
node5 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node2 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node4 | CHANGED | rc=0 >>
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
data research -wi-a----- <1.47g
node1 | CHANGED | rc=0 >>

# 确认文件系统是否正确
ansible all -m shell -a 'blkid /dev/research/data'

node2 | CHANGED | rc=0 >>
/dev/research/data: UUID="83229b4c-dcba-4dcb-aab3-fe8601d3c75a" BLOCK_SIZE="4096" TYPE="ext4"
node3 | CHANGED | rc=0 >>
/dev/research/data: UUID="cdd60647-19a7-48e7-969f-9bd685fcc718" BLOCK_SIZE="4096" TYPE="ext4"
node5 | CHANGED | rc=0 >>
/dev/research/data: UUID="1ee8f698-7b79-410f-bc48-0a1ab781a542" BLOCK_SIZE="4096" TYPE="ext4"
node4 | CHANGED | rc=0 >>
/dev/research/data: UUID="71b9cf21-efae-4926-aef2-80ef3c74b8d2" BLOCK_SIZE="4096" TYPE="ext4"
node1 | FAILED | rc=2 >>
non-zero return code

10.生成主机文件

  • 将⼀个初始模板⽂件从 http://classroom/materials/hosts.j2 下载到***/home/greg/ansible***
  • 完成该模板,以便⽤它⽣成以下⽂件:针对每个清单主机包含⼀⾏内容,其格式与***/etc/hosts*** 相同
  • 将⼀个剧本从 http://classroom/materials/hosts.yml 下载到 /home/greg/ansible,它将使 ⽤此模板在 dev 主机组中的主机上⽣成⽂件 /etc/myhosts

该 playbook 运⾏后, dev 主机组中主机上的⽂件 /etc/myhosts 应针对每个受管主机包含⼀⾏内容:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.9 node1.lab.example.com node1
172.25.250.10 node2.lab.example.com node2
172.25.250.11 node3.lab.example.com node3
172.25.250.12 node4.lab.example.com node4
172.25.250.13 node5.lab.example.com node5

注:清单主机名称的显⽰顺序不重要。

# 下载模板
wget http://classroom/materials/hosts.j2
# 编辑模板文件
vim hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for i in groups.all %}
{{ hostvars[i].ansible_facts.default_ipv4.address }} {{ hostvars[i].ansible_facts.fqdn }} {{ i }}
{% endfor %}
# 执行playbook
ansible-navigator run hosts.yml -m stdout
# 验证
ansible dev -m shell -a 'cat /etc/myhosts'

node1 | CHANGED | rc=0 >>
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.9 node1.lab.example.com node1
172.25.250.10 node2.lab.example.com node2
172.25.250.13 node5.lab.example.com node5
172.25.250.11 node3.lab.example.com node3
172.25.250.12 node4.lab.example.com node4

11.修改文件内容

按照下⽅所述,创建⼀个名为 /home/greg/ansible/issue.yml 的 playbook :

  • 该 playbook 将在 所有清单主机 上运⾏
  • 该 playbook 会将 /etc/issue 的内容替换为下⽅所⽰的⼀⾏⽂本:
    • dev 主机组中的主机上,这⾏⽂本显⽰ 为: Development
    • test 主机组中的主机上,这⾏⽂本显⽰ 为: Test
    • prod 主机组中的主机上,这⾏⽂本显⽰:Production
# doc
ansible-doc copy
ansible-doc stat
# 编写playbook
vim /home/greg/ansible/issue.yml
---
- name: Modify /etc/issue file content
hosts: all
tasks:
- name: Update content for dev
ansible.builtin.copy:
content: 'Development'
dest: /etc/issue
when: inventory_hostname in groups.dev

- name: Update content for test
ansible.builtin.copy:
content: 'Test'
dest: /etc/issue
when: inventory_hostname in groups.test

- name: Update content for prod
ansible.builtin.copy:
content: 'Production'
dest: /etc/issue
when: inventory_hostname in groups.prod
ansible-navigator run issue.yml -m stdout

# 验证
ansible dev -a 'cat /etc/issue'
ansible test -a 'cat /etc/issue'
ansible prod -a 'cat /etc/issue'

12.创建 Web 内容目录

按照下列要求,创建一个名为 /home/greg/ansible/webcontent.yml 的 playbook:

  1. 该 playbook 在 dev 主机组中的受管节点上运行;
  2. 创建符合下列要求的目录 /webdev
    • 所有者为 webdev 组;
    • 具有以下常规权限:
      • owner=read+write+execute
      • group=read+write+execute
      • other=read+execute
    • 具有特殊权限:设置组 ID;
  3. 用符号链接将 /var/www/html/webdev 链接到 /webdev
  4. 创建文件 /webdev/index.html,其中包含如下所示的单行文件内容:
    Development
  5. 在 dev 主机组中主机上浏览此⽬录(例如 http://172.25.250.9/webdev/ )将⽣成以下输出:
    Development
# doc
ansible-doc file
ansible-doc copy
# 查看file context
ansible dev -a 'ls -ldZ /var/www/html'
# 编辑playbook
vim /home/greg/ansible/webcontent.yml
---
- name: Create Web Content Directory
hosts: dev
tasks:
- name: Create /webdev directory
ansible.builtin.file:
path: /webdev
state: directory
group: webdev
mode: '2775'

- name: Create symbolic link for /webdev
ansible.builtin.file:
src: /webdev
dest: /var/www/html/webdev
state: link

- name: Create /webdev/index.html file
ansible.builtin.copy:
content: |
Development
dest: /webdev/index.html
setype: httpd_sys_content_t
# 执行playbook
ansible-navigator run webcontent.yml -m stdout
# 验证
curl http://172.25.250.9/webdev/

13.生成硬件报告

创建⼀个名为 /home/greg/ansible/hwreport.yml 的 playbook ,它将在所有受管节点上⽣成含有以下 信息的输出⽂件 /root/hwreport.txt :

  • 清单主机名称
  • 总内存⼤⼩(MB)
  • BIOS 版本;
  • 磁盘设备 vda 的大小;
  • 磁盘设备 vdb 的大小;
  • 输出文件中的每一行包含一个 key=value 对;

您的 playbook 应当:

  • http://classroom/materials/hwreport.empty 下载⽂件,并将它保存为***/root/hwreport.txt***
  • 使⽤ 正确的值 改为 /root/hwreport.txt
  • 如果硬件项不存在,相关的值应设为 NONE
# 先确认后面打印需要用到的项目名称
ansible all -m setup | grep mem
ansible all -m setup | grep bios
ansible all -m setup -a 'filter=*device*'

# 查看文件内容
curl http://materials/hwreport.empty
# 编写playbook
vim /home/greg/ansible/hwreport.yml
---
- name: Generate hardware report
hosts: all
tasks:
- name: Download empty report template
ansible.builtin.get_url:
url: http://materials/hwreport.empty
dest: /root/hwreport.txt

- name: Add hostname to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^HOST='
line: "HOST={{ inventory_hostname }}"

- name: Add memory size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^MEMORY='
line: "MEMORY={{ ansible_memtotal_mb | default('NONE', true) }}"

- name: Add BIOS version to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^BIOS='
line: "BIOS={{ ansible_bios_version | default('NONE', true) }}"

- name: Add vda disk size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDA='
line: "DISK_SIZE_VDA={{ ansible_devices.vda.size | default('NONE', true) }}"

- name: Add vdb disk size to the report
ansible.builtin.lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDB='
line: "DISK_SIZE_VDB={{ ansible_devices.vdb.size | default('NONE', true) }}"
# 执行playbook
ansible-navigator run hwreport.yml -m stdout
# 验证
ansible all -a 'cat /root/hwreport.txt'

node4 | CHANGED | rc=0 >>
# Hardware report
HOST=node4
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node2 | CHANGED | rc=0 >>
# Hardware report
HOST=node2
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node5 | CHANGED | rc=0 >>
# Hardware report
HOST=node5
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node3 | CHANGED | rc=0 >>
# Hardware report
HOST=node3
MEMORY=960
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=1.00 GB
node1 | CHANGED | rc=0 >>
# Hardware report
HOST=node1
MEMORY=5668
BIOS=1.15.0-1.el9
DISK_SIZE_VDA=20.00 GB
DISK_SIZE_VDB=NONE

14.创建密码库

按照下⽅所述,创建⼀个 Ansible 库来存储⽤⼾密码:

  • 库名称为 /home/greg/ansible/locker.yml
  • 库中含有两个变量,名称如下:
    • pw_developer ,值为 Imadev
    • pw_manager ,值为 Imamgr
  • ⽤于加密和解密该库的密码为 whenyouwishuponastar
  • 密码存储在⽂件 /home/greg/ansible/secret.txt
# 创建密码文件
echo "whenyouwishuponastar" > /home/greg/ansible/secret.txt

# 指定密码文件
vim ansible.cfg
vault_password_file=/home/greg/ansible/secret.txt

# 创建vault
ansible-vault create /home/greg/ansible/locker.yml
---
pw_developer: Imadev
pw_manager: Imamgr

# 验证
cat /home/greg/ansible/locker.yml

$ANSIBLE_VAULT;1.1;AES256
32316462663839316261653164376664376432313863333238383462396230663138323362363132
3361363734323065373531343431303234616232333135380a396530626436383566356337633966
64393365623237303333373037366461646638376164376130613637646434383537383636336265
3061666131656238320a303337366163633337313533376632646631316434323765326135396562
32393031383338386533643865653965366264653034633132396666666331663064626337333734
6136653065306631643466356531393031666339346165316637

15.创建⽤⼾帐⼾

创建⽤⼾帐⼾

  • http://classroom/materials/user_list.yml 下载要创建的⽤⼾的列表,并将它保存到 /home/greg/ansible
  • 在本次练习中使⽤在其他位置创建的密码库 /home/greg/ansible/locker.yml 。创建名为 /home/greg/ansible/users.yml 的playbook ,从⽽按以下所述创建⽤⼾帐⼾:
    • 职位描述为 developer 的⽤⼾应当:
      • devtest 主机组中的受管节点上创建
      • pw_developer 变量分配密码
      • 密码最⼤有效期 30
      • 是补充组 devops 的成员
    • 职位描述为 manager 的⽤⼾应当:
      • prod 主机组中的受管节点上创建
      • pw_manager 变量分配密码
      • 密码最⼤有效期 30
      • 是补充组 opsmgr 的成员
  • 密码采⽤ sha512 哈希格式。
  • 您的playbook应能够在本次练习中使⽤在其他位置创建的库密码⽂件***/home/greg/ansible/secret.txt*** 正常运⾏。
# 下载用户列表文件
wget http://classroom/materials/user_list.yml
# 确认文件内容格式
cat user_list.yml
# 编写playbook
vim /home/greg/ansible/users.yml
---
- name: Create User1
hosts: dev,test
vars_files:
- /home/greg/ansible/locker.yml
- /home/greg/ansible/user_list.yml
tasks:
- name: Add group1
group:
name: devops
state: present

- name: Add user1
user:
name: "{{ item.name }}"
groups: devops
password: "{{ pw_developer | password_hash('sha512') }}"
password_expire_max: "{{ item.password_expire_max }}"
loop: "{{ users }}"
when: item.job == 'developer'

- name: Create User2
hosts: prod
vars_files:
- /home/greg/ansible/locker.yml
- /home/greg/ansible/user_list.yml
tasks:
- name: Add group2
group:
name: opsmgr
state: present

- name: Add user2
user:
name: "{{ item.name }}"
groups: opsmgr
password: "{{ pw_manager | password_hash('sha512') }}"
password_expire_max: "{{ item.password_expire_max }}"
loop: "{{ users }}"
when: item.job == 'manager'
# 执行playbook
ansible-navigator run users.yml -m stdout

PLAY [Create User1] *************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node2]
ok: [node1]

TASK [Add group1] ***************************************************************************************************************************************************************************************************************************************************************
ok: [node2]
ok: [node1]

TASK [Add user1] ****************************************************************************************************************************************************************************************************************************************************************
changed: [node2] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node2] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
changed: [node1] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node1] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
changed: [node2] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})
changed: [node1] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})

PLAY [Create User2] *************************************************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] **********************************************************************************************************************************************************************************************************************************************************
ok: [node3]
ok: [node4]

TASK [Add group2] ***************************************************************************************************************************************************************************************************************************************************************
changed: [node3]
changed: [node4]

TASK [Add user2] ****************************************************************************************************************************************************************************************************************************************************************
skipping: [node3] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
skipping: [node4] => (item={'name': 'bob', 'job': 'developer', 'password_expire_max': 10, 'uid': 3000})
changed: [node4] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
skipping: [node4] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})
changed: [node3] => (item={'name': 'sally', 'job': 'manager', 'password_expire_max': 20, 'uid': 3001})
skipping: [node3] => (item={'name': 'fred', 'job': 'developer', 'password_expire_max': 30, 'uid': 3002})

PLAY RECAP **********************************************************************************************************************************************************************************************************************************************************************
node1 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node2 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node3 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
node4 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 验证
ansible dev,test -m shell -a 'id bob; id fred'
ansible prod -m shell -a 'id sally'
ssh bob@node1
bob@node1\'s password: Imadev
ssh sally@node3
sally@node3\'s password: Imamgr

16.更新 Ansible 库的密钥

按照下⽅所述,更新现有 Ansible 库的密钥:

  • http://classroom/materials/salaries.yml 下载 Ansible 库到***/home/greg/ansible***
  • 当前的库密码为 insecure8sure
  • 新的库密码为 bbs2you9527
  • 库使⽤ 新密码 保持加密状态
# 下载库文件
wget http://classroom/materials/salaries.yml
# 更新库密码
ansible-vault rekey --ask-vault-pass /home/greg/ansible/salaries.yml

Vault password: insecure8sure
New Vault password: bbs2you9527
Confirm New Vault password: bbs2you9527
Rekey successful

# 验证
ansible-vault view --ask-vault-pass salaries.yml

Vault password: bbs2you9527
haha

17.配置 cron 作业

创建⼀个名为 /home/greg/ansible/cron.yml 的 playbook :

  • 该 playbook 在 test 主机组中的受管节点上运⾏
  • 配置 cron 作业,该作业 每隔 2 分钟 运⾏并执⾏以下命令: logger "EX200 in progress" ,以⽤⼾ natasha ⾝份运⾏
# doc
ansible-doc cron

vim /home/greg/ansible/cron.yml
---
- name: cron
hosts: test
tasks:
- name: cron job
cron:
name: "cron job1"
minute: "*/2"
job: 'logger "EX200 in progress"'
user: natasha
ansible-navigator run cron.yml -m stdout
# 验证
ansible test -a 'crontab -l -u natasha'