EX294题库及分析(RHCE)

考试说明

对应RH294课程

1、下午的考试,考试时长4小时,300分满分,210分及格

2、上午如果提前交卷,问下考官下午考试几点考

3、填写邮箱、用户名,保证和上午考试填写的一样

4、考试也是一台宿主机(物理机),没有root密码的,一共有 6台KVM虚拟机,可以直接使用ssh root用户到各虚拟主机

5、6台主机中,有一台是 ansible 主机,需要使用 ssh 到 greg 用户进行操作

考题

第一题:安装和配置 Ansible

按照下方所述,在控制节点 172.25.250.200,安装和配置 Ansible;

安装所需软件包

创建名为 /home/greg/ansible/inventory 的静态清单文件,以满足以下要求:

  1. 172.25.250.9 是 dev 主机组的成员
  2. 172.25.250.10 是 test 主机组成员
  3. 172.25.250.11 和 172.25.250.12 是 prod 主机组成员
  4. 172.25.250.13 是 balancers 主机组成员
  5. prod组是 webservers 主机组的成员

创建名为 /home/greg/ansible/ansible.cfg 的配置文件,以满足以下要求:

  1. 主机清单文件为 /home/greg/ansible/inventory
  2. playbook 中使用的角色的位置包括 /home/greg/ansible/roles

解答

[tom@host ~]$ ssh root@bastion
[root@bastion ~]# yum install -y ansible
[tom@host ~]$ ssh greg@bastion
[greg@bastion ~]$ mkdir /home/greg/ansible/ && touch /home/greg/ansible/inventory
[greg@bastion ~]$ vim /home/greg/ansible/inventory
[dev]
172.25.250.9

[test]
172.25.250.10

[prod]
172.25.250.11
172.25.250.12

[balancers]
172.25.250.13

[webservers:children]
prod

[greg@bastion ~]$ vim /home/greg/ansible/ansible.cfg
[defaults]
inventory      = /home/greg/ansible/inventory
roles_path    = /home/greg/ansible/roles

[privilege_escalation]
become=True
become_method=sudo
become_user=root

[greg@bastion ~]$ mkdir /home/greg/ansible/roles

第二题:创建和运行 Ansible 临时命令

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

请按照正文所述,创建一个名为 /home/greg/ansible/adhoc.sh 的 shell 脚本,该脚本将使用 Ansible 临时命令在各个受管节点上安装 yum 存储:

存储库1:

  • 存储库的名称为 EX294_BASE
  • 描述为 EX294 base software
  • 基础 URL 为 ftp://host.domain8.example.com/dvd/BaseOS
  • GPG 签名为启用状态
  • GPG 密钥 URL 为 ftp://host.domain8.example.com/dvd/RPM-GPG-KEY-redhat-release
  • 存储库为启用状态

存储库2:

  • 存储库的名称为 EX294_STREAM
  • 描述为 EX294 stream software
  • 基础 URL 为:ftp://host.domain8.example.com/dvd/AppStream
  • GPG 签名为启用状态
  • GPG 密钥 URL 为 ftp://host.domain8.example.com/dvd/RPM-GPG-KEY-redhat-release
  • 存储库为启用状态

解答

[greg@bastion ~]$ cd ansible/
[greg@bastion ansible]$ vim adhoc.sh
#!/bin/bash
ansible all -m yum_repository -a "name=EX294_BASE description='EX294 base software' baseurl=ftp://host.domain8.example.com/dvd/BaseOS enabled=yes gpgcheck=yes gpgkey=ftp://host.domain8.example.com/dvd/RPM-GPG-KEY-redhat-release"
ansible all -m yum_repository -a "name=EX294_STREAM description='EX294 stream software' baseurl=ftp://host.domain8.example.com/dvd/AppStream enabled=yes gpgcheck=yes gpgkey=ftp://host.domain8.example.com/dvd/RPM-GPG-KEY-redhat-release"

[greg@bastion ansible]$ chmod +x adhoc.sh
[greg@bastion ansible]$ ./adhoc.sh

# 考试时候,查询模块,使用
[greg@bastion ansible]$ ansible-doc -l |grep yum
yum                                                    Manages packages with the `yum' package manager               
yum_repository                                         Add or remove YUM repositories
# 查询模块帮助文档
[greg@bastion ansible]$ ansible-doc yum_repository

第三题:安装软件包

创建一个名为 /home/greg/ansible/packages.yaml 的 playbook:

  • 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组的主机上
  • 将 RPM Development Tools 软件包组安装到 dev 主机组中的主机上
  • 将 dev 主机组中主机上的所有软件包更新为最新版本

解答

[greg@bastion ansible]$ vim /home/greg/ansible/packages.yaml
---
- hosts: dev,test,prod
  tasks:
  - name: install php
    yum: name=php,mariadb state=installed

- hosts: dev
  tasks:
  - name: install RPM Development Tools
    yum: name="@RPM Development Tools" state=installed
  - name: update all
    yum: name='*' state=latest
[greg@bastion ansible]$ ansible-playbook packages.yaml

第四题:使用RHEL角色

安装 RHEL 系统角色软件包,并创建符合以下条件的 playbook

/home/greg/ansible/timesync.yml:

  • 在所有受管节点上运行
  • 使用 timesync 角色
  • 配置该角色,以使用当前有效的 NTP 提供商
  • 配置该角色,以使用时间服务器 172.25.250.250
  • 配置该角色,以使用 iburst 参数

解答:

[root@bastion ~]# yum list *rhel*role*
[root@bastion ~]# yum install -y rhel-system-roles.noarch

[greg@bastion ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync/ roles/timesync
# 查看帮助文档中的 NTP 示例
[greg@bastion ansible]$ vim roles/timesync/README.md
timesync_ntp_servers:
  - hostname: foo.example.com   # Hostname or address of the server
    minpoll: 4                  # Minimum polling interval (default 6)
    maxpoll: 8                  # Maximum polling interval (default 10)
    iburst: yes                 # Flag enabling fast initial synchronization
                                # (default no)
    pool: no                    # Flag indicating that each resolved address
                                # of the hostname is a separate NTP server
                                # (default no)

# 编写 yaml
[greg@bastion ansible]$ vim timesync.yaml
---
- hosts: all
  vars:
    timesync_ntp_servers:
    - hostname: 172.25.250.250
      pool: yes
      iburst: yes
  roles:
  - role: timesync

# 运行
[greg@bastion ansible]$ ansible-playbook timesync.yaml

第五题:使用 Ansible Galaxy 安装角色

使用名字为文件 /home/greg/ansible/roles/requirements.yaml 下载并安装 Ansible Glaxy 角色。从下列 URL 下载:

解答:

[greg@bastion ansible]$ vim roles/requirements.yaml
---
- src: http://host.domain8.example.com/ex300/haproxy.tar.gz
  name: balancer
- src: http://host.domain8.example.com/ex300/phpinfo.tar.gz
  name: phpinfo

[greg@bastion ansible]$ ansible-galaxy install -r roles/requirements.yaml -p roles/

第六题:创建和使用角色

根据下列要求,在 /home/greg/ansible/roles 中创建名为 apache 的角色:

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

创建名为 newroles.yaml 的 playbook,使用这个角色,对 webservers 组进行操作。HOSTNAME 是 FQDN 的完整主机名称。

解答

[greg@bastion ansible]$ cd roles/ && ansible-galaxy init apache
- apache was created successfully

## 分析task:1、安装 httpd;2、启动服务;3、启动 firewalld;4、设置防火墙;5、拷贝模板
[greg@bastion roles]$ vim apache/tasks/main.yml
---
# tasks file for apache
- name: install httpd
  yum: name=httpd state=installed
- name: start and set httpd
  service: name=httpd state=started enabled=yes
- name: start firewalld
  service: name=firewalld state=started enabled=yes
- name: set firewalld
  firewalld: service=http immediate=yes permanent=yes state=enabled
- name: copy jinjia2 template
  template: src=index.html.j2 dest=/var/www/html/index.html

# 编写模板
[greg@bastion roles]$ vim apache/templates/index.html.j2
Welcome to {{ansible_fqdn}} on {{ansible_default_ipv4.address}}

# 编写yaml文件,执行 ansible-playbook
[greg@bastion roles]$ cd ~/ansible/
[greg@bastion ansible]$ vim newroles.yaml
- hosts: webservers
  roles:
  - role: apache

[greg@bastion ansible]$ ansible-playbook newroles.yaml

第七题:从 Ansible Galaxy 使用角色

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

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

    重新加载浏览器将从另一个 web 服务器生成输出:Welcome to serverd.domain8.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 serverb.lab.example.com

    另外还有PHP配置的各种详细信息,如安装的 PHP 版本等

    l另外还有 PHP 配置的各种详细信息,如安装的 PHP 版本等。

解答:

[greg@bastion ansible]$ cat role.yml
---
# hosts: all 获取所有主机上的 fects 变量,没有的话会报错
- hosts: all
- hosts: balancers
  roles:
  - role: balancer

- hosts: webservers
  roles:
  - role: phpinfo

第八题: 8-a 创建和使用逻辑卷

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

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

在练习环境里,创建 lvgroup 分组,把 servera 和 serverc 添加过去,对 lvgroup 分组来做

解答:

# 练习环境配置下主机组,因为要做两题关于逻辑卷,对机器做个分配
[greg@bastion ansible]$ cat inventory 
[lvgroup]
172.25.250.9
172.25.250.11

[greg@bastion ansible]$ vim lv.yml
---
- hosts: lvgroup
  tasks:
  - name: if research exist
    shell: "vgdisplay research"
    register: aa
    ignore_errors: yes(这个别忘记写)
  - name: research not exist
    fail: msg="Volume group done not exist"
    when: aa.rc != 0
  - name: lvcreate
    block:
    - name: lvcreate 1500MiB
      lvol: vg=research lv=data size=1500M
    rescue:
    - name: display create error
      debug: msg="Could not create logical volume of that size"
    - name: lvcreate 800MiB
      lvol: vg=research lv=data size=800M
  - name: format lv
    filesystem: dev=/dev/research/data fstype=ext4

[greg@bastion ansible]$ ansible-playbook lv.yml

第八题: 8-b 创建并使用磁盘分区

创建名为 partition.yml 的 playbook,对所有的节点进行操作:

  • 在 vdb 上创建一个主分区,1500MiB
  • 使用 ext4 文件系统进行格式化
  • 将文件系统挂载到 /newpart
  • 如果分区大小不满足,产生报错信息: could not create partation of that size,则创建分区大小变成800MiB
  • 如果磁盘不存在,产生报错信息: disk does not exist

在练习环境里,创建 diskgroup 分组,把serverb 和 serverd 添加过去,对 diskgroup 分组来做

解答:

[greg@bastion ansible]$ cat inventory
[diskgroup]
serverb
serverd

[greg@bastion ansible]$ vim partition.yml
# 最后的挂载,一定要写 mounted
---
- hosts: diskgroup
  tasks:
  - name: if disk exist
    shell: "ls /dev/vdb"
    register: aa
    ignore_errors: yes
  - name: disk not exist
    fail: msg="disk does not exist"
    when: aa.rc != 0
  - name: create partition
    block:
    - name: create 1500MiB
      parted: device=/dev/vdb number=1 state=present part_end=1500MiB
    rescue:
    - name: size not enough
      debug: msg="could not create partation of that size"
    - name: create 800MiB
      parted: device=/dev/vdb number=1 state=present part_end=800MiB
  - name: format partition
    filesystem: dev=/dev/vdb1 fstype=ext4 force=yes
  - name: mount
    mount: src=/dev/vdb1 path=/newpart fstype=ext4 state=mounted

第九题 生成主机文件

将一个初始模板文件从 http://host.domain8.example.com/ex300/hosts.j2 下载到 /home/greg/ansible;

完成该模板,以便用它生成以下文件,针对每个清单主机包含一行内容,其格式与 /etc/hosts 相同;

创建名为 /home/greg/ansible/hosts.yml 的 playbook,它将使用此模板在 dev 主机组中的主机上生成文件 /etc/myhosts;

该 playbook 运行后,dev主机组中主机上的文件 /etc/myhosts 应针对每个收官主机包含一行内容:

127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4

:1 localhost localhost localhost.localdomain localhost6 localhost6.localdomain6

172.25.250.9 workstation.lab.example.com workstation
172.25.250.10 servera.lab.example.com servera
172.25.250.11 serverb.lab.example.com serverb
172.25.250.12 serverc.lab.example.com serverc
172.25.250.13 serverd.lab.example.com serverd

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

解答:

# 下面这个文件内容,考试时候是他妈空的,得自己记住
[greg@bastion ansible]$ cat hosts.j2 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for host in groups['all'] %}
{{ hostvars[host]['ansible_default_ipv4']['address']}} {{ hostvars[host]['ansible_fqdn'] }} {{ hostvars[host]['ansible_hostname'] }}
{% endfor %}

[greg@bastion ansible]$ vim hosts.yml
---
- hosts: all
- hosts: dev
  tasks:
  - name: copy template
    template: src=/home/greg/ansible/hosts.j2 dest=/etc/myhosts

第十题: 修改文件内容

按照下方所属,创建一个名为 /home/greg/ansible/issue.yml 的 playbook:

  • 该 playbook 将在所有清单主机上运行
  • 该 playbook 会将 /etc/issue 的内容替换为下方所示的一行文本
    • 在 dev 主机组中的主机上,这行文本显示为:Development
    • 在 test 主机组中的主机上,这行文本显示为:Test
    • 在 prod 主机组中的主机上,这行文本显示为:Production

解答:

# hosts后面必须跟 all,每个 task 要求在单独的主机上做,一定要使用 inventory_hostname in groups['xxx']
[greg@bastion ansible]$ cat issue.yml 
---
- hosts: all
  tasks:
  - name: dev
    copy: content="Development\n" dest=/etc/issue
    when: inventory_hostname in groups['dev']
  - name: test
    copy: content="Test\n" dest=/etc/issue
    when: inventory_hostname in groups['test']
  - name: prod
    copy: content="Production\n" dest=/etc/issue
    when: inventory_hostname in groups['prod']

第十一题: 创建 web 内容目录

按照下方所述,创建一个名为 /home/greg/ansible/webcontent.yml 的 playbook:

  • 该 playbook 在 dev 主机组中的受管节点上运行
  • 创建符合下列要求的目录 /webdev
    • 所属组为 webdev 组
    • 具有常规权限: owner=read+write+execute,group=read+write+execute,other=read,execute
    • 具有特殊权限:设置组ID
    • 用符号链接将 /var/www/html/webdev 链接到 /webdev
  • 创建文件 /webdev/index.html ,其中包含如下所示的单行文件:Development
  • 在 dev 主机组中主机上浏览此目录(例如: http://172.25.250.9/webdev/)将生成以下输出: Development

解答:

[greg@bastion ansible]$ cat webcontent.yml 
---
- hosts: dev
  roles:
  - role: apache
  tasks:
  - name: add group
    group: name=webdev state=present
  - name: create /webdev dir
    file: path=/webdev group=webdev state=directory mode=2775 setype=httpd_sys_content_t
  - name: create file
    copy: dest=/webdev/index.html content="Development\n" setype=httpd_sys_content_t
  - name: create symbolic link
    file: dest=/var/www/html/webdev src=/webdev state=link

第十二题: 生成硬件报告

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

  • 清单主机名称(这个主机名称是主机清单里的名称,要注意)
  • 以 MB 表示的总内存大小
  • BIOS 版本
  • 磁盘设备 vda 的大小
  • 磁盘设备 vdb 的大小
  • 输出文件中的每一行含有一个 key=value 对

您的 playbook 应当:

  • http://host/ex300/hwreport.empty 下载文件,并将它保存为 /root/hwreport.txt
  • 使用正确的值改为 /root/hwreport.txt
  • 如果硬件项不存在,相关的值设置为 NONE

解答:


# 下面的变量名称,可以通过 ansible 172.25.250.9 -m setup 获取
[greg@bastion ansible]$ cat hwreport.yml 
---
- hosts: all
  tasks:
  - name: rm file
    shell: "rm -rf /root/hwreport.txt"
  - name: download file
    get_url: url=http://host/ex300/hwreport.empty dest=/root/hwreport.txt
  - name: get invenroty hostname
    lineinfile: path=/root/hwreport.txt regexp=^HOST line=HOST={{inventory_hostname}}
  - name: get memory
    lineinfile: path=/root/hwreport.txt regexp=^MEMORY line=MEMORY={{ansible_memtotal_mb}}MB
  - name: get bios version
    lineinfile: path=/root/hwreport.txt regexp=^BIOS line=BIOS={{ansible_bios_version}}
  - name: get vda size
    lineinfile: path=/root/hwreport.txt regexp=^DISK_SIZE_VDA line=DISK_SIZE_VDA={{ansible_devices.vda.size}}
  - name: get vdb size1
    lineinfile: path=/root/hwreport.txt regexp=^DISK_SIZE_VDB line=DISK_SIZE_VDB={{ansible_devices.vdb.size}}
    when: ansible_devices.vdb.size is defined
  - name: get vdb size2
    lineinfile: path=/root/hwreport.txt regexp=^DISK_SIZE_VDB line=DISK_SIZE_VDB=NONE
    when: ansible_devices.vdb.size is undefined

第十三题: 创建密码库

按照下方所属,创建一个 Ansible 库用来存储用户密码:

  • 库名称为 /home/greg/ansible/locker.yml
  • 库中含有两个变量,名称如下:
    • pw_developer,值为 redhat
    • pw_manager,值为 redhat
  • 用于加密和解密该库的密码为 redhat
  • 密码存储在文件 /home/greg/ansible/secret.txt 中

解答:

[greg@bastion ansible]$ cat locker.yml 
pw_developer: redhat
pw_manager: redhat

[greg@bastion ansible]$ echo redhat > secret.txt
[greg@bastion ansible]$ cat secret.txt 
redhat

[greg@bastion ansible]$ ansible-vault encrypt --vault-id ./secret.txt locker.yml 
Encryption successful
[greg@bastion ansible]$ cat locker.yml 
$ANSIBLE_VAULT;1.1;AES256
38343336643863343232346262666635336631383662316661386366373635373466633938626531
3939376365653066396364333966653962353634333033340a333964653236663363656462316636
61383064323433613135633530646161396439653030626264373633636634343434383635613966
6636663136353134620a383863646535306337323838616438653132666163353236376235376630
30623461653566616636383863363338303533333964623231353431393262326164346636336634
6233366432366362333035626266613338653534613734316338
[greg@bastion ansible]$ ansible-vault view --vault-id ./secret.txt locker.yml 
pw_developer: redhat
pw_manager: redhat

第十四题: 创建用户账户

http://host/ex300/user_list.yml 下载要创建的用户列表,并将它保存到 /home/greg/ansible

在本次考试中使用在其他位置创建的密码库 /home/greg/ansible/locker.yml。创建名为 /home/greg/ansible/users.yml 的 playbook,从而按以下所属创建用户账户:

  • 职位描述为 developer 的用户应当:
    • 在 dev 和 test 主机组中的受管节点上创建
    • 从 pw_developer 变量分配密码
    • 是附属组 devops 的成员
  • 职位描述为 manager 的用户应当:
    • 在 prod 主机组中的受管节点上创建
    • 从 pw_manager 变量分配密码
    • 是附属组 opsmgr 的成员
  • 密码采用 SHA512 哈希格式

您的 playbook 应能够在本次考试中使用在其他位置创建的库密码文件 /home/greg/ansible/secret.txt 正常运行;考试时候可能会有个用户密码过期30天的需求,不用管他,默认就是30天。

解答:

# 读题需要两个play,分成 item1和item2,要从 locker.yml 读密码用,要从 user_list.yml 读用户列表来进行循环,密码要hash,执行时,要带 vault-id
[greg@bastion ansible]$ cat users.yml 
---
- name: item1
  hosts: dev,test
  vars_files:
  - /home/greg/ansible/locker.yml
  - /home/greg/ansible/user_list.yml
  tasks:
  - name: create group
    group: name=devops state=present 
  - name: create users
    user: name={{item.name}} groups=devops comment="developer" password={{pw_developer |password_hash('sha512')}}
    when: item.job=="developer"
    loop: "{{users}}"
- name: item2
  hosts: prod
  vars_files:
  - /home/greg/ansible/locker.yml
  - /home/greg/ansible/user_list.yml
  tasks:
  - name: create group
    group: name=opsmgr state=present 
  - name: create users
    user: name={{item.name}} groups=opsmgr comment="manager" password={{pw_manager |password_hash('sha512')}}
    when: item.job=="manager"
    loop: "{{users}}"

[greg@bastion ansible]$ ansible-playbook --vault-id ./secret.txt users.yml

第十五题: 更新 Ansible 库的密钥

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

  • http://host/ex300/salaries.yml 下载 Ansible 库到 /home/greg/ansible

  • 当前库密码为 111111

  • 新的密码为 redhat

  • 库使用新密码保持加密状态

解答:

[greg@bastion ansible]$ wget http://host/ex300/salaries.yml
[greg@bastion ansible]$ ansible-vault rekey salaries.yml

在练习环境里,做完之后,在物理机里,用 su - 切换到 root 用户