主机 | IP | 作用 |
---|---|---|
workstation.lab.example.com | 172.25.250.9 | Ansible control node |
servera.lab.example.com | 172.25.250.10 | Ansible managed node |
serverb.lab.example.com | 172.25.250.11 | Ansible managed node |
serverc.lab.example.com | 172.25.250.12 | Ansible managed node |
serverd.lab.example.com | 172.25.250.13 | Ansible managed node |
bastion.lab.example.com | 172.25.250.254 | Ansible managed node |
workstation为ansible节点
servera、serverb、serverc、serverd、bastion为受控主机
Ansible 控制节点上已创建了用户帐户 student。此帐户预装了 SSH密钥,
允许在 Ansible 控制节点和各个 Ansible 受管节点之间进行SSH 登录。
请勿对系统上的 student SSH 配置文件进行任何修改。
您可以从 root 帐户使用 su 访问此用户帐户
[root@foundation ~]$ virt-manager
[root@foundation ~]$ rht-vmctl reset all
输入y确认重置所有主机
[root@foundation ~]$ ssh -X root@workstation
[root@workstation ~]# dnf install -y ansible
[root@workstation ~]# vim /etc/sudoers.d/student
student ALL=(ALL) NOPASSWD: ALL
[root@workstation ~]# for i in server{a..d} bastion
> do scp /etc/sudoers.d/student root@$i:/etc/sudoers.d/
> done
>
更改workstation、servera、serverb、serverc、serverd、bastion
主机的/etc/hosts文件,把文件中content.example.com对应的ip改为172.25.254.250
[root@workstation ~]# for i in server{a..d} bastion
> do scp /etc/hosts root@$i:/etc/hosts
> done
关闭bastion的httpd服务
[root@foundation ~]$ ssh root@bastion
[root@bastion ~]# systemctl stop httpd
[root@bastion ~]# systemctl disable httpd
按照下方所述,在控制节点workstation.lab.example.com 上安装和配置Ansible:
安装所需的软件包
创建名为/home/student/ansible/inventory的静态清单文件, 以满足以下需求:
servera是dev主机组的成员
serverb是test主机组的成员
serverc和serverd是prod主机组的成员
bastion是balancers主机组的成员
prod组是webservers主机组的成员
创建名为/home/student/ansible/ansible.cfg的配置文件, 以满足以下要求:
主机清单文件为/home/student/ansible/inventory
playbook中使用的角色的位置包括/home/student/ansible/roles
[root@foundation ~]$ ssh root@workstation
[student@workstation ~]$ su - student
[student@workstation ~]$ mkdir ansible
[student@workstation ~]$ cd ansible
[student@workstation ansible]$ cp /etc/ansible/ansible.cfg /home/student/ansible/
[student@workstation ansible]$ mkdir /home/student/ansible/roles
[student@workstation ansible]$ vi ansible.cfg
[defaults]
inventory = /home/student/ansible/inventory
remote_user = student
roles_path = /home/student/ansible/roles
host_key_checking = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[student@workstation ansible]$ vim inventory
[dev]
servera
[test]
serverb
[prod]
serverc
serverd
[balancers]
bastion
[webservers:children]
prod
[student@workstation ansible]$ ansible all -m ping
2、创建和运行Ansible临时命令
作为系统管理员, 您需要在受管节点上安装软件.
请按照下方所述, 创建一个名为/home/student/ansible/adhoc.sh的shell脚本,
该脚本将使用Ansible临时命令在各个受管节点上安装yum存储库:
存储库1:
存储库的名称为 rh294_BASE
描述为 rh294 base software
基础URL为 http://content.example.com/rhel8.0/x86_64/dvd/BaseOS
GPG签名检查为启用状态
GPG密钥URL为 http://content.example.com/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
存储库为开启状态
存储库2:
存储库的名称为 rh294_STREAM
描述为 rh294 stream software
基础URL为 http://content.example.com/rhel8.0/x86_64/dvd/AppStream
GPG签名检查为启用状态
GPG密钥URL为 http://content.example.com/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release
存储库为开启状态
[student@workstation ansible]$ vim adhoc.sh
#!/bin/bash
ansible all -m yum_repository -a "name=rh294_BASE description='rh294 base software'
file=rhel_dvd baseurl=http://content.example.com/rhel8.0/x86_64/dvd/BaseOS gpgcheck=yes
gpgkey=http://content.example.com/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release enabled=yes"
ansible all -m yum_repository -a "name=rh294_STREAM description='rh294 stream software'
file=rhel_dvd baseurl=http://content.example.com/rhel8.0/x86_64/dvd/AppStream
gpgcheck=yes gpgkey=http://content.example.com/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release enabled=yes"
[student@workstation ansible]$ chmod +x adhoc.sh
[student@workstation ansible]$ ./adhoc.sh
创建一个名为 /home/student/ansible/packages.yml的 playbook:
将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上
将 RPM Development Tools 软件包组安装到 dev主机组中的主机上
将 dev 主机组中主机上的所有软件包更新为最新版本
[student@workstation ansible]$ vim packages.yml
---
- name: install pkgs
hosts: dev, test, prod
tasks:
- name: install mariadb php
yum:
name:
- php
- mariadb
state: present
- name: install group pkgs
hosts: dev
tasks:
- name: install Development Tools
yum:
name: "@Development Tools"
state: present
- name: update all pkgs
hosts: dev
tasks:
- name: update pkgs
yum:
name: '*'
state: latest
[student@workstation ansible]$ ansible-playbook packages.yml
安装 RHEL 系统角色软件包,并创建符合以下条件的playbook /home/student/ansible/timesync.yml:
在所有受管节点上运行
使用 timesync 角色
配置该角色,以使用当前有效的 NTP 提供商
配置该角色,以使用时间服务器 classroom.example.com
配置该角色,以启用 iburst 参数
[student@workstation ansible]$ sudo yum -y install rhel-system-roles
[student@workstation ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync/ /home/student/ansible/roles/timesync
[student@workstation ansible]$ ls roles/timesync/
COPYING defaults handlers library meta README.html README.md semaphore tasks templates tests vars
[student@workstation ansible]$ vim timesync.yml
---
- name: set timesync
hosts: all
vars:
timesync_ntp_servers:
- hostname: classroom.example.com
iburst: yes
roles:
- timesync
[student@workstation ansible]$ ansible-playbook timesync.yml
配置该角色,开启所有受控节点的selinux
[student@workstation ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.selinux/ /home/student/ansible/roles/selinux
[student@workstation ansible]$ vim selinux.yml
---
- name: start selinux
hosts: all
vars:
selinux_state: enforcing
roles:
- role: selinux
become: true
[student@workstation ansible]$ ansible-playbook selinux.yml
使用 Ansible Galaxy 和要求文件 /home/student/ansible/roles/requirements.yml,从以下 URL 下载角色并安装到 /home/student/ansible/roles:
http://content.example.com/haproxy.tar.gz 此角色的名称应当为 balancer
http://content.example.com/phpinfo.tar.gz 此角色的名称应当为 phpinfo
[student@workstation ansible]$ vim roles/requirements.yml
---
- name: balancer
src: http://content.example.com/haproxy.tar.gz
- name: phpinfo
src: http://content.example.com/phpinfo.tar.gz
[student@workstation ansible]$ ansible-galaxy install -r /home/student/ansible/roles/requirements.yml -p /home/student/ansible/roles/
- downloading role from http://content.example.com/haproxy.tar.gz
- extracting balancer to /home/student/ansible/roles/balancer
- balancer was installed successfully
- downloading role from http://content.example.com/phpinfo.tar.gz
- extracting phpinfo to /home/student/ansible/roles/phpinfo
- phpinfo was installed successfully
[student@workstation ansible]$ ls roles/
balancer phpinfo requirements.yml selinux timesync
根据下列要求,在/home/student/ansible/roles中创建名为apache的角色:
httpd软件包已安装,设为在系统启动时启用并启动
防火墙已启用并正在运行,并使用允许访问Web服务器的规则
模板文件 index.html.j2 已存在,用于创建具有以下输出的文件/var/www/html/index.html:
Welcome to HOSTNAME on IPADDRESS
其中,HOSTNAME是受管节点的完全限定域名,IPADDRESS则是受管节点的IP地址。
按照下方所述,创建一个使用此角色的playbook /home/student/ansible/newrole.yml:
该playbook在webservers主机组中的主机上运行
[student@workstation ansible]$ cd roles/
[student@workstation roles]$ ansible-galaxy init apache
- apache was created successfully
[student@workstation roles]$ vim apache/tasks/main.yml
---
# tasks file for apache
- name: install httpd firewalld
yum:
name:
- httpd
- firewalld
state: present
- name: copy file
template:
src: index.html.j2
dest: /var/www/html/index.html
- name: start httpd service
service:
name: httpd
state: started
enabled: yes
- name: restart firewalld
service:
name: firewalld
state: restarted
enabled: yes
- name: set firewalld
firewalld:
service: http
permanent: yes
state: enabled
immediate: yes
[student@workstation roles]$ vim apache/templates/index.html.j2
Welcome to {{ ansible_fqdn }} on {{ ansible_enp1s0.ipv4.address }}
[student@workstation roles]$ cd ..
[student@workstation ansible]$ vim newrole.yml
---
- name: use apache role
hosts: webservers
roles:
- apache
[student@workstation ansible]$ ansible-playbook newrole.yml
[student@workstation ansible]$ curl http://serverc
Welcome to serverc.lab.example.com on 172.25.250.12
[student@workstation ansible]$ curl http://serverd
Welcome to serverd.lab.example.com on 172.25.250.13
根据下列要求,创建一个名为 /home/student/ansible/roles.yml的playbook:
playbook中包含一个play,该play在balancers主机组中的主机上运行并将使用balancer角色。
此角色配置一项服务,以在webservers主机组中的主机之间平衡Web服务器请求的负载。
浏览到balancers主机组中的主机(例如http://bastion.lab.example.com/ )将生成以下输出:
Welcome to serverc.example.com on 172.25.1.12
重新加载浏览器将从另一Web服务器生成输出:
Welcome to serverd.example.com on 172.25.1.13
playbook 中包含一个 play,该 play 在 webservers主机组中的主机上运行并将使用 phpinfo 角色。
通过 URL /hello.php 浏览到 webservers 主机组中的主机将生成以下输出:
Hello PHP World from FQDN
其中,FQDN是主机的完全限定名称。
例如,浏览到 http://serverc.lab.example.com/hello.php 会生成以下输出:
Hello PHP World from serverc.lab.example.com
另外还有 PHP 配置的各种详细信息,如安装的PHP 版本等。
同样,浏览到 http://serverd.lab.example.com/hello.php 会生成以下输出:
Hello PHP World from serverd.lab.example.com
另外还有 PHP 配置的各种详细信息,如安装的PHP 版本等。
[student@workstation ansible]$ vim roles.yml
---
- name: webservers facts
hosts: webservers
- name: balancer role
hosts: balancers
roles:
- balancer
- name: php role
hosts: webservers
roles:
- phpinfo
[student@workstation ansible]$ ansible-playbook roles.yml
[student@workstation ansible]$ curl http://bastion.lab.example.com
Welcome to serverc.lab.example.com on 172.25.250.12
[student@workstation ansible]$ curl http://bastion.lab.example.com
Welcome to serverd.lab.example.com on 172.25.250.13
[student@workstation ansible]$ curl http://serverc.lab.example.com/hello.php
Hello PHP World form serverc.lab.example.com
[student@workstation ansible]$ curl http://serverd.lab.example.com/hello.php
Hello PHP World form serverd.lab.example.com
创建一个名为/home/student/ansible/lv.yml 的playbook,它将在所有受管节点上运行以执行下列任务:
创建符合以下要求的逻辑卷:
逻辑卷创建在research卷组中
逻辑卷名称为data
逻辑卷大小为1500MiB
使用ext4文件系统格式化逻辑卷
如果无法创建请求的逻辑卷大小,应显示错误消息
Could not create logical volume of that size,并且应改为使用大小 800MiB。
如果卷组research 不存在 ,应显示错误消息
Volume group does not exist。
不要以任何方式挂载逻辑卷
首先执行lvm_pre.yml
[student@workstation ansible]$ ansible-playbook lvm_pre.yml
再编辑playbook
[student@workstation ansible]$ vim lv.yml
---
- name: create lvm
hosts: all
tasks:
- name: create lv data
block:
- name: create lv 1500
lvol:
lv: data
vg: research
size: 1500
rescue:
- name: output fail message
debug:
msg: Could not create logical volume of that size
- name: create lv 800
lvol:
lv: data
vg: research
size: 800
always:
- name: format lv
filesystem:
dev: /dev/research/data
fstype: ext4
when: "'research' in ansible_lvm.vgs"
- name: search not exists
debug:
msg: Volume group does not exist
when: "'research' not in ansible_lvm.vgs"
[student@workstation ansible]$ ansible-playbook lv.yml
创建名为partition.yml的playbook,对所有节点进行操作:
在vdb上创建一个主分区1500MiB
使用ext4文件系统进行格式化
将文件系统挂载到/newpart
如果分区大小不满足,产生报错信息 could not create partition os that size
则创建分区大小变成800MiB
如果磁盘不存在,产生报错信息:disk does not exist
[student@workstation ansible]$ vim partition.yml
---
- name: create partition
hosts: all
tasks:
- name: create part1
block:
- name: create part 1500
parted:
device: /dev/vdb
number: 1
part_type: primary
part_start: 10
part_end: 1510
state: present
rescue:
- name: output fail message
debug:
msg: could not create partition os that size
- name: create part 800
parted:
device: /dev/vdb
number: 1
part_type: primary
part_start: 10
part_end: 800
state: present
always:
- name: format part
filesystem:
dev: /dev/vdb1
fstype: ext4
- name: create mount point
file:
path: /newpart
state: directory
- name: mount
mount:
src: /dev/vdb1
path: /newpart
fstype: ext4
state: mounted
when: "ansible_devices.vdb is defined"
- name: vdb not exist
debug:
msg: disk does not exist
when: "ansible_devices.vdb is not defined"
[student@workstation ansible]$ ansible-playbook partition.yml
将一个初始模板文件从http://content.example.com/hosts.j2下载到/home/student/ansible
完成该模板,以便用它生成以下文件:针对每个清单主机包含一行内容,其格式与 /etc/hosts 相同
创建名为 /home/student/ansible/hosts.yml 的playbook,它将使用此模板在 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.24.1.6 servera.lab1.example.com servera
172.24.1.7 serverb.lab1.example.com serverb
172.24.1.8 serverc.lab1.example.com serverc
172.24.1.9 serverd.lab1.example.com serverd
172.24.1.10 bastion.lab1.example.com bastion
[student@workstation ansible]$ wget http://content.example.com/hosts.j2
[student@workstation ansible]$ vim hosts.j2
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
{% for ho in groups.all %}
{{ hostvars[ho].ansible_enp1s0.ipv4.address }} {{ hostvars[ho].ansible_fqdn }} {{ hostvars[ho].ansible_hostname }}
{% endfor %}
[student@workstation ansible]$ vim hosts.yml
---
- name: all variable
hosts: all
- name: cp to myhosts
hosts: dev
tasks:
- name: cp hosts
template:
src: /home/student/ansible/hosts.j2
dest: /etc/myhosts
[student@workstation ansible]$ ansible-playbook hosts.yml
[student@workstation ansible]$ ssh root@servera
[root@servera ~]# cat /etc/myhosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.25.250.10 servera.lab.example.com servera
172.25.250.11 serverb.lab.example.com serverb
172.25.250.254 bastion.lab.example.com bastion
172.25.250.12 serverc.lab.example.com serverc
172.25.250.13 serverd.lab.example.com serverd
按照下方所述,创建一个名为 /home/student/ansible/issue.yml 的 playbook:
该 playbook 将在所有清单主机上运行
该 playbook 会将 /etc/issue 的内容替换为下方所示的一行文本:
在 dev 主机组中的主机上,这行文本显示为:Development
在 test 主机组中的主机上,这行文本显示为:Test
在 prod 主机组中的主机上,这行文本显示为:Production
[student@workstation ansible]$ vim issue.yml
---
- name: modify issue
hosts: all
tasks:
- name: input to issue
copy:
content: |
{% if 'dev' in group_names %}
Development
{% elif 'test' in group_names %}
Test
{% elif 'prod' in group_names %}
Production
{% endif %}
dest: /etc/issue
[student@workstation ansible]$ ansible-playbook issue.yml
[root@servera ~]# cat /etc/issue
Development
[root@serverb ~]# cat /etc/issue
Test
[root@serverc ~]# cat /etc/issue
Production
[root@serverd ~]# cat /etc/issue
Production
按照下方所述,创建一个名为 /home/student/ansible/webcontent.yml 的 playbook:
该 playbook 在 dev 主机组中的受管节点上运行
创建符合下列要求的目录 /webdev:
所有者为 devops 组
具有常规权限:owner=read+write+execute,group=read+write+execute,other=read+execute
具有特殊权限: set group ID
用符号链接将 /var/www/html/webdev 链接到 /webdev
创建文件 /webdev/index.html,其中包含如下所示的单行文本:Development
在 dev 主机组中主机上浏览此目录(例如 http://servera.lab.example.com/webdev/ )将生成以下输出:
Development
[student@ansible ansible]$ vim webcontent.yml
---
- name: webcontent
hosts: dev
tasks:
- name: create user
user:
name: devops
- name: create directory
file:
path: /webdev
group: devops
mode: 2775
state: directory
- name: write file
copy:
dest: /webdev/index.html
content: Development
- name: set context
sefcontext:
target: /webdev(/.*)?
setype: httpd_sys_content_t
- name: restorecon
command: restorecon -Rv /webdev
- name: create link
file:
src: /webdev
path: /var/www/html/webdev
state: link
- name: set firewalld
firewalld:
service: http
premanent: yes
immediate: yes
state: enabled
- name: restart httpd serice
service:
name: httpd
state: restarted
[student@ansible ansible]$ ansible-playbook webcontent.yml
[student@ansible ansible]$ curl http://node1/webdev/
Development
创建一个名为 /home/student/ansible/hwreport.yml的 playbook,它将在所有受管节点上生成含有以下信息的输出文件 /root/hwreport.txt:
输出文件中的每一行含有一个 key=value 对。
您的 playbook 应当:
从 http://content.example.com/hwreport.empty 下载文件,并将它保存为/root/hwreport.txt
使用正确的值修改 /root/hwreport.txt
如果硬件项不存在,相关的值应设为NONE
[student@workstation ansible]$ vim hwreport.yml
---
- name: get hwreport
hosts: all
tasks:
- name: Create report file
get_url:
url: http://content.example.com/hwreport.empty
dest: /root/hwreport.txt
- name: get inventory_hostname
replace:
path: /root/hwreport.txt
regexp: 'inventoryhostname'
replace: "{{ inventory_hostname }}"
- name: get mem
replace:
path: /root/hwreport.txt
regexp: 'memory_in_MB'
replace: "{{ ansible_memtotal_mb }}"
- name: get bios
replace:
path: /root/hwreport.txt
regexp: 'BIOS_version'
replace: "{{ ansible_bios_version }}"
- name: get vda
replace:
path: /root/hwreport.txt
regexp: 'disk_vda_size'
replace: "{{ ansible_devices.vda.size if ansible_devices.vda is defined else 'NONE'}}"
- name: get vdb
replace:
path: /root/hwreport.txt
regexp: 'disk_vdb_size'
replace: "{{ ansible_devices.vdb.size if ansible_devices.vdb is defined else 'NONE'}}"
[student@workstation ansible]$ ansible-playbook hwreport.yml
按照下方所述,创建一个 Ansible 库来存储用户密码:
库名称为 /home/student/ansible/locker.yml
库中含有两个变量,名称如下:
pw_developer,值为 Imadev
pw_manager,值为 Imamgr
用于加密和解密该库的密码为whenyouwishuponastar
密码存储在文件 /home/student/ansible/secret.txt中
[student@workstation ansible]$ vim locker.yml
---
pw_developer: lmadev
pw_manager: lmamgr
[student@workstation ansible]$ echo "whenyouwishuponastar" >secret.txt
[student@workstation ansible]$ chmod 600 secret.txt
[student@workstation ansible]$ ansible-vault encrypt locker.yml --vault-id secret.txt
Encryption successful
从 http://content.example.com/user_list.yml 下载要创建的用户的列表,并将它保存到 /home/student/ansible
在本次考试中使用在其他位置创建的密码库 /home/student/ansible/locker.yml,创建名为/home/student/ansible/users.yml 的playbook,从而按以下所述创建用户帐户:
职位描述为 developer 的用户应当:
在 dev 和 test 主机组中的受管节点上创建
从 pw_developer 变量分配密码,密码有效期为30天
是附加组 student 的成员
职位描述为 manager 的用户应当:
在 prod 主机组中的受管节点上创建
从 pw_manager 变量分配密码,密码有效期为30天
是附加组 opsmgr 的成员
密码应采用 SHA512 哈希格式。
您的 playbook 应能够在本次考试中使用在其他位置创建的库密码文件/home/student/ansible/secret.txt 正常运行
[student@workstation ansible]$ wget http://content.example.com/user_list.yml
[student@workstation ansible]$ vim users.yml
---
- name: create user is developer
hosts: dev, test
vars_files:
- /home/student/ansible/locker.yml
- /home/student/ansible/user_list.yml
tasks:
- name: create student group
group:
name: student
state: present
- name: create user in developer
user:
name: "{{ item.name }}"
groups: student
password: "{{ pw_developer | password_hash('sha512') }}"
state: present
loop: "{{ users }}"
when: item.job == "developer"
- name: chage
shell:
cmd: chage -M 30 {{ item.name }}
loop: "{{ users }}"
when: item.job == "developer"
- name: create user is manager
hosts: prod
vars_files:
- /home/student/ansible/locker.yml
- /home/student/ansible/user_list.yml
tasks:
- name: create opsmgr group
group:
name: opsmgr
state: present
- name: create user in manager
user:
name: "{{ item.name }}"
groups: opsmgr
password: "{{ pw_manager | password_hash('sha512') }}"
state: present
loop: "{{ users }}"
when: item.job == "manager"
- name: chage1
shell:
cmd: chage -M 30 {{ item.name }}
loop: "{{ users }}"
when: item.job == "manager"
[student@workstation ansible]$ ansible-playbook users.yml --vault-id secret.txt
按照下方所述,更新现有 Ansible 库的密钥:
从 http://content.example.com/salaries.yml 下载 Ansible 库到 /home/student/ansible
当前的库密码为 AAAAAAAAA
新的库密码为 bbe2de98389b
库使用新密码保持加密状态
[student@workstation ansible]$ wget http://172.25.250.250/ansible2.8/salaries.yml
[student@workstation ansible]$ ansible-vault rekey salaries.yml
输入旧密码
输入新密码
确认新密码
创建⼀个名为 /home/greg/ansible/cron.yml 的 playbook
配置 cron 作业,该作业每隔 2 分钟运⾏并执⾏以下命令:
logger “EX294 in progress”,以⽤户 natasha 身份运⾏
[student@workstation ansible]$ vim cron.yml
---
- name: create cron
hosts: all
tasks:
- name: create user
user:
name: natasha
state: present
- name: create cron for all
cron:
name: cy
minute: '*/2'
job: logger "EX294 in progress"
user: natasha
[student@workstation ansible]$ ansible-playbook cron.yml