环境介绍
系统 | IP 地址 | Ansible 角色 |
---|
bastion | 172.25.250.254 | ansible 的控制节点 | workstation | 172.25.250.9 | 用于进行系统管理的图形工作站 | servera | 172.25.250.10 | 通过ansible管理的主机 | serverb | 172.25.250.11 | 通过ansible管理的主机 | serverc | 172.25.250.12 | 通过ansible管理的主机 | serverd | 172.25.250.13 | 通过ansible管理的主机 |
重要信息 编写的 Ansible playbook 将通过以 greg 用户身份从控制节点上的目录 /home/greg/ansible 目录运行来应用。在 playbook 运行后,系统会对您的受管节点进行评估,以判断它们是否按照规定进行了配置
进入foundation
[kiosk@foundation0 ~]$ rht-vmctl status all
bastion DEFINED
workstation DEFINED
servera DEFINED
serverb DEFINED
serverc DEFINED
serverd DEFINED
[kiosk@foundation0 ~]$ rht-vmctl start all
Starting bastion.
Starting workstation.
Starting servera.
Starting serverb.
Starting serverc.
Starting serverd.
开启所有服务器
挂载ISO2.ios
在foundation0上
[kiosk@foundation0 init]$ ssh root@localhost 'yum -y install /run/media/kiosk/20191229_164114/ex300v8-1.3.0-191229.x86_64.rpm'
cd /home/kiosk/ex300/roles/init/files
将两个Ansible Galaxy 角色和硬件报告模板复制进materials目录里
[kiosk@foundation0 files]$ ssh root@localhost 'cp /home/kiosk/ex300/roles/init/files/haproxy.tar /home/kiosk/ex300/roles/init/files/phpinfo.tar /home/kiosk/ex300/roles/init/files/hwreport.empty /content/courses/rh294/rhel8.0/materials/'
[kiosk@foundation0 files]$ ls /content/courses/rh294/rhel8.0/materials
Ansible-Tower-license.txt dynamic jinja2 roles-library yum
ansible-vim.tar.gz grading labs solutions yum.conf.d
classroom haproxy.tar phpinfo.tar tower
docs hwreport.empty playbooks troubleshooting
连接bastion
ssh root@172.25.254.250
[root@bastion ~]# yum install ansible
创建greg
[root@bastion ~]# useradd greg
[root@bastion ~]# passwd greg
考试要求
安装和配置 Ansible
按照下方所述,在控制节点 172.25.250.254 上安装和配置 Ansible:
解答
[root@bastion ~]# su - greg
创建ansible的目录
[greg@bastion ~]$ mkdir ansible
查看ansible版本
[greg@bastion ansible]$ ansible --version
ansible 2.8.0
config file = /etc/ansible/ansible.cfg
发现config文件是/etc/下面的
这里需要说明一下:
ansible的配置文件有四种优先级
参数命令>当前目录的配置文件>家目录的配置文件>/etc/下的配置文件
因此我们将配置文件拷贝到家目录里
[greg@bastion ansible]$ cp /etc/ansible/ansible.cfg ./
同时查找主机清单的路径
[greg@bastion ansible]$ rpm -qc ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
拷贝主机清单
[greg@bastion ansible]$ cp /etc/ansible/hosts ./inventory
[greg@bastion ansible]$ ansible --version
ansible 2.8.0
config file = /home/greg/ansible/ansible.cfg
配置文件优先级变更成家目录了
创建角色的目录
[greg@bastion ansible]$ mkdir roles
[greg@bastion ansible]$ vim ansible.cfg
# 主机清单
inventory = /home/greg/ansible/inventory
# 角色目录
roles_path = /home/greg/ansible/roles
# 表示受控端在执行主控端下达的命令时用什么身份进行执行 因此是root
remote_user = root
# 主机密钥检查性关闭,管理端就不会进行ssh密钥验证了
host_key_checking = False
# 受控端执行ansible用户提权的参数
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
配置主机清单
[greg@bastion ansible]$ vim 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 ansible]$ ansible-inventory --graph
@all:
|--@balancers:
| |--172.25.250.13
|--@dev:
| |--172.25.250.9
|--@test:
| |--172.25.250.10
|--@ungrouped:
|--@webservers:
| |--@prod:
| | |--172.25.250.11
| | |--172.25.250.12
主机清单已经配置完毕
我们测试能否ping通节点服务器
-k 是输入密码进行验证 密码是redhat
[greg@bastion ansible]$ ansible all -m ping -k
SSH password:
172.25.250.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
在主机清单下面添加自动连接的密码
[greg@bastion ansible]$ vim inventory
[all:vars]
ansible_password=redhat
验证
主机清单
[greg@bastion ansible]$ ansible-inventory --graph
@all:
|--@balancers:
| |--172.25.250.13
|--@dev:
| |--172.25.250.9
|--@test:
| |--172.25.250.10
|--@ungrouped:
|--@webservers:
| |--@prod:
| | |--172.25.250.11
| | |--172.25.250.12
ping所有节点
[greg@bastion ansible]$ ansible all -m ping
172.25.250.11 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
172.25.250.12 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
172.25.250.10 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
172.25.250.13 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
172.25.250.9 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
创建和运行 Ansible 临时命令
作为系统管理员,您需要在受管节点上安装软件。
请按照正文所述,创建一个名为 /home/greg/ansible/adhoc.sh 的 shell 脚本,该脚本将使用 Ansible 临时命令在各个受管节点上安装 yum 存储库:
-
存储库1:
-
存储库2:
-
存储库的名称为 EX294_STREAM -
描述为 EX294 stream software -
基础 URL 为 http://content/rhel8.0/x86_64/dvd/AppStream -
GPG 签名检查为启用状态 -
GPG 密钥 URL 为 http://content/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release -
存储库为启用状态
解答
因为实现安装 yum 存储库,当接触一个不了解的模块时,我通常的做法就是查看帮助文档
在帮助文档里过滤与yum相关的模块
[greg@bastion ansible]$ ansible-doc -l |grep yum
yum Manages packages with the `yum` package manager
yum_repository Add or remove YUM repositories
yum_repository就是添加和删除yum数据库的模块
查看帮助
[greg@bastion ansible]$ ansible-doc yum_repository
通过EXAMPLES知道具体语法
编写脚本
[greg@bastion ansible]$ vim adhoc.sh
#!/bin/bash
ansible all -m yum_repository -a 'name="EX294_BASE" description="EX294 base software" baseurl="http://content/rhel8.0/x86_64/
dvd/BaseOS" gpgcheck=yes gpgkey="http://content/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release" enabled=yes'
ansible all -m yum_repository -a 'name="EX294_STREAM" description="EX294 stream software" baseurl="http://content/rhel8.0/x86
_64/dvd/AppStream" gpgcheck=yes gpgkey="http://content/rhel8.0/x86_64/dvd/RPM-GPG-KEY-redhat-release" enabled=yes'
执行脚本
[greg@bastion ansible]$ bash adhoc.sh
验证
查看yum数据库目录
[greg@bastion ansible]$ ansible all -m shell -a 'ls /etc/yum.repos.d'
172.25.250.12 | CHANGED | rc=0 >>
EX294_BASE.repo
EX294_STREAM.repo
redhat.repo
rhel_dvd.repo
172.25.250.13 | CHANGED | rc=0 >>
EX294_BASE.repo
EX294_STREAM.repo
redhat.repo
rhel_dvd.repo
172.25.250.11 | CHANGED | rc=0 >>
EX294_BASE.repo
EX294_STREAM.repo
redhat.repo
rhel_dvd.repo
172.25.250.10 | CHANGED | rc=0 >>
EX294_BASE.repo
EX294_STREAM.repo
redhat.repo
rhel_dvd.repo
172.25.250.9 | CHANGED | rc=0 >>
additional.repo
EX294_BASE.repo
EX294_STREAM.repo
redhat.repo
rhel_dvd.repo
每个收管节点都有了 EX294_BASE.repo和EX294_STREAM.repo
也可以用adhoc命令检查,查看yum仓库的情况
[greg@bastion ansible]$ ansible all -a 'yum repolist'
172.25.250.10 | CHANGED | rc=0 >>
repo id repo name status
EX294_BASE EX294 base software 1,658
EX294_STREAM EX294 stream software 4,672
rhel-8.0-for-x86_64-appstream-rpms Red Hat Enterprise Linux 8.0 AppStream 4,672
rhel-8.0-for-x86_64-baseos-rpms Red Hat Enterprise Linux 8.0 BaseOS (d 1,658Last metadata expiration check: 0:44:42 ago on
Tue 27 Apr 2021 08:22:41 PM CST.
安装软件包
解答
一样的方法 先去查看帮助文档
[greg@bastion ansible]$ ansible-doc yum
EXAMPLES:
- name: install the latest version of Apache
yum:
name: httpd
state: latest
创建剧本
[greg@bastion ansible]$ vim /home/greg/ansible/packages.yml
---
- hosts: dev test prod
tasks:
- name: ensure a list of packages installed
yum:
name: "{{ packages }}"
vars:
packages:
- php
- mariadb
- hosts: dev
tasks:
- name: install package group
yum:
name: "@RPM Development Tools"
state: present
- name: upgrade all packages
yum:
name: '*'
state: latest
验证
执行剧本
[greg@bastion ansible]$ ansible-playbook packages.yml
验证安装php
[greg@bastion ansible]$ ansible all -m shell -a 'rpm -qa | grep php'
172.25.250.12 | CHANGED | rc=0 >>
php-cli-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-common-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-fpm-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-7.2.11-1.module+el8+2561+1aca3413.x86_64
172.25.250.11 | CHANGED | rc=0 >>
php-cli-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-common-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-fpm-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-7.2.11-1.module+el8+2561+1aca3413.x86_64
172.25.250.13 | FAILED | rc=1 >>
non-zero return code
172.25.250.10 | CHANGED | rc=0 >>
php-cli-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-common-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-fpm-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-7.2.11-1.module+el8+2561+1aca3413.x86_64
172.25.250.9 | CHANGED | rc=0 >>
php-common-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-fpm-7.2.11-1.module+el8+2561+1aca3413.x86_64
php-cli-7.2.11-1.module+el8+2561+1aca3413.x86_64
除balancers组的服务器没有安装 其他都安装了
验证安装开发工具包
[greg@bastion ansible]$ ansible dev -m shell -a 'yum grouplist'
172.25.250.9 | CHANGED | rc=0 >>
Last metadata expiration check: 0:58:46 ago on Tue 27 Apr 2021 08:22:18 PM CST.
Available Environment Groups:
Server with GUI
Server
Minimal Install
Virtualization Host
Custom Operating System
Installed Environment Groups:
Workstation
Installed Groups:
RPM Development Tools
Available Groups:
Container Management
.NET Core Development
Smart Card Support
Development Tools
Graphical Administration Tools
Headless Management
Legacy UNIX Compatibility
Network Servers
Scientific Support
Security Tools
System Tools
使用 RHEL 系统角色
安装 RHEL 系统角色软件包,并创建符合以下条件的 playbook /home/greg/ansible/timesync.yml :
解答
利用playbook进行NTP时间的同步,需要使用系统角色,因此先安装下RHEL的系统角色包——rhel-system-roles
[root@bastion ansible]# yum -y install rhel-system-roles.noarch
使用timesync这个角色,就是安装的RHEL系统角色里带的timesync这个角色,我们找到rhel系统角色,并且把timesync这个角色拷贝到我们的角色roles目录下
[greg@bastion ansible]$ cp -r /usr/share/ansible/roles/rhel-system-roles.timesync/ /home/greg/ansible/roles/timesync
查看角色
[greg@bastion ansible]$ ansible-galaxy list
# /home/greg/ansible/roles
- timesync, (unknown version)
编写playbook脚本,这里的playbook是让我们配置ntp服务器,我们可以借助我们刚才拷贝的timesync这个目录里的帮助文档进行参考
[greg@bastion ansible]$ vim /home/greg/ansible/timesync.yml
---
- name: ntp service
hosts: all
vars:
timesync_btp_servers:
- hostname: 172.25.254.254
iburst: yes
roles:
- timesync
iburst是否开启快速同步
[greg@bastion ansible]$ ansible-playbook timesync.yml
PLAY RECAP ******************************************************************************************************************
172.25.250.10 : ok=16 changed=0 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
172.25.250.11 : ok=16 changed=0 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
172.25.250.12 : ok=16 changed=0 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
172.25.250.13 : ok=16 changed=0 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
172.25.250.9 : ok=16 changed=0 unreachable=0 failed=0 skipped=18 rescued=0 ignored=6
验证
查看 /etc/chrony.conf-rht 里面是否有同步时间服务器的地址
[greg@bastion ansible]$ ansible all -m shell -a 'grep '172.25.254.254' /etc/chrony.conf-rht '
172.25.250.10 | CHANGED | rc=0 >>
server 172.25.254.254 iburst
172.25.250.12 | CHANGED | rc=0 >>
server 172.25.254.254 iburst
172.25.250.13 | CHANGED | rc=0 >>
server 172.25.254.254 iburst
172.25.250.11 | CHANGED | rc=0 >>
server 172.25.254.254 iburst
172.25.250.9 | CHANGED | rc=0 >>
server 172.25.254.254 iburst
使用 Ansible Galaxy 安装角色
使用 Ansible Galaxy 和要求文件 /home/greg/ansible/roles/requirements.yml 。从以下 URL 下载角色并安装到 /home/greg/ansible/roles :
解答
创建一个playbook脚本,用来指定下载的角色名称和下载链接
[greg@bastion ansible]$ vim /home/greg/ansible/requirements.yml
---
- name: balancer
src: http://materials/haproxy.tar
- name: phpinfo
src: http://materials/phpinfo.tar
用ansible-galaxy命令来安装角色,-r选项指定playbook文件,-p指定角色安装的位置,因为第一题定义了ansible角色的位置在 /home/student/ansible/roles/
[greg@bastion ansible]$ ansible-galaxy install -r requirements.yml -p /home/greg/ansible/roles/
[greg@bastion roles]$ ls
balancer phpinfo timesync
验证
[greg@bastion ansible]$ ansible-galaxy list
# /home/greg/ansible/roles
- timesync, (unknown version)
- balancer, (unknown version)
- phpinfo, (unknown version)
创建和使用角色
根据下列要求,在 /home/greg/ansible/roles 中创建名为 apache 的角色:
-
httpd 软件包已安装,设为在系统启动时启用并启动 -
防火墙已启用并正在运行,并使用允许访问 Web 服务器的规则 -
模板文件 index.html.j2 已存在,用于创建具有以下输出的文件 /var/www/html/index.html :
解答
我们首先创建名为apache的角色,注意:ansible-galaxy init 角色名称,此命令必须在roles目录下执行
[greg@bastion roles]$ ansible-galaxy init apache
- apache was created successfully
[greg@bastion roles]$ ll
total 0
drwxrwxr-x. 10 greg greg 135 Apr 26 04:37 apache
drwxrwxr-x. 9 greg greg 122 Apr 26 17:02 balancer
drwxrwxr-x. 9 greg greg 118 Apr 26 17:02 phpinfo
drwxr-xr-x. 10 greg greg 188 Apr 26 04:17 timesync
我们进入角色,来编写我们的任务,需要进行编辑的文件为这两个
[greg@bastion roles]$ cd apache/
[greg@bastion apache]$ ls
defaults files handlers meta README.md tasks templates tests vars
tasks 任务集
templates 模板文件
查看service模块和template的用法
[greg@bastion roles]$ ansible-doc template
编写角色任务
[greg@bastion apache]$ vim tasks/main.yml
[greg@bastion apache]$ vim tasks/main.yml
---
- name: install the latest version of Apache
yum:
name: httpd
state: latest
- name: firewalld
firewalld:
service: http
state: enabled
permanent: yes 永久开启
immediate: yes 立刻生效立即运行
- name: Template a file
template:
src: index.html.j2
dest: /var/www/html/index.html
owner: apache
group: apache
mode: '0644'
- name: start service httpd
service:
name: "{{ item }}"
state: restarted
enabled: yes
loop:
- httpd
- firewalld
接下来写模板文件 index.html.j2,在template这个文件夹内(用vim创建并且编辑,template目录内是空的,index.html.j2需要我们手动创建)
首先查询完全限定域名
[greg@bastion ansible]$ ansible dev -m setup -a 'filter=*fqdn*'
172.25.250.9 | SUCCESS => {
"ansible_facts": {
"ansible_fqdn": "workstation.lab.example.com",
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false
}
再查询IPADDRESS
[greg@bastion ansible]$ ansible dev -m setup -a 'filter=*ipv4*'
发现ip魔法参数是ansible_default_ipv4.address
[greg@bastion templates]$ vim index.html.j2
Welcome to {{ ansible_hostname }} on {{ ansible_default_ipv4.address }}
playbook脚本中使用apache角色
[greg@bastion ansible]$ vim apache.yml
---
- name: apache
hosts: webservers
roles:
- apache
执行剧本
[greg@bastion ansible]$ ansible-playbook apache.yml
验证
当执行完playbook脚本后,webservers主机组里的主机有index.html首页文件,访问它们的界面,看跟我们用template传过去的文件内容是否一致
[greg@bastion ansible]$ curl http://serverb
Welcome to serverb on 172.25.250.11
[greg@bastion ansible]$ curl http://serverc
Welcome to serverc on 172.25.250.12
从 Ansible Galaxy 使用角色
根据下列要求,创建一个名为 /home/greg/ansible/roles.yml 的 playbook :
-
playbook 中包含一个 play, 该 play 在 balancers 主机组中的主机上运行并将使用 balancer 角色。
-
此角色配置一项服务,以在 webservers 主机组中的主机之间平衡 Web 服务器请求的负载。 -
浏览到 balancers 主机组中的主机(例如 http://172.25.250.13 )将生成以下输出: Welcom to serverb.lab.example.com on 172.25.250.11
-
重新加载浏览器将从另一 Web 服务器生成输出: Welcom to serverc.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
serverb.lab.example.com
-
另外还有 PHP 配置的各种详细信息,如安装的 PHP 版本等。 -
同样,浏览到 http://172.25.250.12/hello.php 会生成以下输出: Hello PHP World from
serverc.lab.example.com
- 另外还有 PHP 配置的各种详细信息,如安装的 PHP 版本等。
解答
balancers 的主机组内的主机用balancer角色webservers 主机组内的主机用phpinfo角色
[greg@bastion ansible]$ vim /home/greg/ansible/roles.yml
---
- name: balancers
hosts: balancers
roles:
- balancer
- name: web
hosts: webservers
roles:
- phpinfo
- name: apache
hosts: webservers
roles:
- apache
执行剧本
[greg@bastion ansible]$ ansible-playbook roles.yml
验证
进行webservers主机组中的主机之间平衡Web服务器请求的负载
[greg@bastion ansible]$ curl http://serverd
Welcome to serverb on 172.25.250.11
[greg@bastion ansible]$ curl http://serverd
Welcome to serverc on 172.25.250.12
[greg@bastion ansible]$ curl http://serverd
Welcome to serverb on 172.25.250.11
[greg@bastion ansible]$ curl http://serverd
Welcome to serverc on 172.25.250.12
以及webservers主机组内的主机的输出php的信息
[greg@bastion ansible]$ curl http://serverc/hello.php
Hello PHP World from serverc.lab.example.com
创建一个名为 /home/greg/ansible/lv.yml 的 playbook ,它将在所有受管节点上运行以执行下列任务:
-
创建符合以下要求的逻辑卷:
-
逻辑卷创建在 research 卷组中 -
逻辑卷名称为 data -
逻辑卷大小为 1500 MiB -
使用 ext4 文件系统格式化逻辑卷 -
如果无法创建请求的逻辑卷大小,应显示错误信息 Could not create logical volume of that size
-
如果卷组 research 不存在,应显示错误信息 Volume group done not exist
-
不要以任何方式挂载逻辑卷
解答
-
创建逻辑卷,但如果创建逻辑卷大小超过了vg的大小,就应当缩小容量然后再次创建,如果vg卷组不存在的话就要显示错误信息 -
使用了block rescue always -
block、rescue和always之间的关系:block执行有误时执行rescue,而always无论block是否成功执行都会执行 -
并且进行when 判断,如果research这个VG组存在就执行block,research和always的语句,不存在就返回一条信息,说明research这个vg组不存在
[greg@bastion ansible]$ vim /home/greg/ansible/lv.yml
---
- name: Create a logical volume
hosts: all
tasks:
- name: Create a logical volume
block:
- name: Create a logical volume
lvol:
vg: research
lv: data
size: 1500m
rescue:
- name: report size not enough
debug:
msg: Could not create logical volume of that size
- name: Create a logical volume
lvol:
vg: research
lv: data
size: 800m
always:
- name: Create a logical volume
filesystem:
dev: /dev/research/data
fstype: ext4
when: "'research' in ansible_lvm.vgs"
- name: judge
debug:
msg: Volume group does not exist
when: "'research' not in ansible_lvm.vgs"
执行剧本
[greg@bastion ansible]$ ansible-playbook lv.yml
验证
查看逻辑卷
[greg@bastion ansible]$ ansible all -m shell -a 'lvs'
生成主机文件
-
将一个初始模板文件从 http://materials/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.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
注:清单主机名称的显示顺序不重要。
解答
- 用template模块进行文件的传输,通过帮助文档查看模块用法
- 文件内包含IP地址,域名,主机名。所以我们需要用到主机内置的变量
- 内置变量通过setup filter来查
- 在这里运用for循环,这里的groups.all为受控端主机的清单,即为受控制的5台主机。hostvars 为主机变量,i 是从groups.all里面取值,那么就是受控主机的名称了
- 第一个 i 的取值为 servera 那 hostvars[i] 可以理解成 hostvars[servera] 就表示 servera 主机的内置主机变量
将模板下载到bastion
[kiosk@foundation0 files]$ scp hosts.j2 root@bastion:/home/greg/ansible
[greg@bastion ansible]$ 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_enp1s0.ipv4.address }} {{ hostvars[i].ansible_fqdn }} {{ hostvars[i].ansible_hostname }}
{% endfor %}
编写剧本,这里需要注意 :
- 先引用所有主机的内置变量,因为我们在hosts.j2里面调用了所有主机的变量,但是如果不在playbook里先调用所有主机的变量的话,那playbook脚本将执行失败
[greg@bastion ansible]$ vim /home/greg/ansible/hosts.yml
---
- name: vars
hosts: all
- name: host
hosts: dev
tasks:
- name: host
template:
src: hosts.j2
dest: /etc/myhosts
[greg@bastion ansible]$ ansible-playbook hosts.yml
验证
查看dev主机上myhosts文件的信息
[greg@bastion ansible]$ ansible dev -m shell -a 'cat /etc/myhosts'
172.25.250.9 | CHANGED | rc=0 >>
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 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.13 serverd.lab.example.com serverd
172.25.250.11 serverb.lab.example.com serverb
172.25.250.12 serverc.lab.example.com serverc
修改文件内容
按照下方所述,创建一个名为 /home/greg/ansible/issue.yml 的 playbook :
解答
- copy模块,在copy模块中有个名为content的选项,将指定的内容复制到远程文件内
- 要求只有在指定主机组内的主机才进行替换,我们要用到when判断,inventory_hostname则表示为受控主机名称,例如:servera,serverb
编写剧本
[greg@bastion ansible]$ vim /home/greg/ansible/issue.yml
---
- name: content
hosts: all
tasks:
- name: content1
copy:
content: "Development\n"
dest: /etc/issue
when: "inventory_hostname in groups.dev"
- name: content2
copy:
content: "Test\n"
dest: /etc/issue
when: "inventory_hostname in groups.test"
- name: content3
copy:
content: "Production\n"
dest: /etc/issue
when: "inventory_hostname in groups.prod"
groups.dev则表示dev主机组内的主机,那这句判断可以理解为inventory_hostname的主机是否在groups.dev里
如果inventory_hostname取的第一个值为servera的话,那servera在dev主机组内,那就执行copy模块下的任务,如果第一个值取的是serverb的话,那serverb并不在dev主机组内,那就不执行copy模块下的任务
验证
[greg@bastion ansible]$ ansible-playbook issue.yml
[greg@bastion ansible]$ ansible all -m shell -a 'cat /etc/issue'
172.25.250.11 | CHANGED | rc=0 >>
Production
172.25.250.10 | CHANGED | rc=0 >>
Test
172.25.250.13 | CHANGED | rc=0 >>
\S
Kernel \r on an \m
172.25.250.12 | CHANGED | rc=0 >>
Production
172.25.250.9 | CHANGED | rc=0 >>
Development
创建 Web 内容目录
按照下方所述,创建一个名为 /home/greg/ansible/webcontent.yml 的 playbook :
-
该 playbook 在 dev 主机组中的受管节点上运行 -
创建符合下列要求的目录 /webdev :
-
用符号链接将 /var/www/html/webdev 链接到 /webdev -
创建文件 /webdev/index.html ,其中包含如下所示的单行文件: Development -
在 dev 主机组中主机上浏览此目录(例如 http://172.25.250.9/webdev/ )将生成以下输出: Development
解答
- 创建web目录,那首先想到web服务,先进行apache服务的安装,并且把防火墙和服务自启打开
- 创建web目录时切记更改selinux值,改为httpd_sys_content_t,以及index.html文件的selinux值
- group是帮助创建用户组
[greg@bastion ansible]$ vim /home/greg/ansible/webcontent.yml
---
- name: web service
hosts: dev
tasks:
- name: yum httpd
yum:
name: httpd
state: present
- name: firewalld
firewalld:
service: http
state: enabled
permanent: yes
immediate: yes
- name: service
service:
name: "{{ item }}"
state: restarted
enabled: yes
loop:
- httpd
- firewalld
- name: Ensure group "webdev" exists
group:
name: webdev
state: present
- name: mkdir
file:
path: /webdev
group: webdev
mode: '2775'
state: directory
setype: httpd_sys_content_t
- name: link
file:
src: /webdev
dest: /var/www/html/webdev
state: link
- name: touch
copy:
content: "Development\n"
dest: /webdev/index.html
setype: httpd_sys_content_t
验证
[greg@bastion ansible]$ ansible-playbook webcontent.yml
[greg@bastion ansible]$ curl http://172.25.250.9/webdev/
Development
生成硬件报告
创建一个名为 /home/greg/ansible/hwreport.yml 的 playbook ,它将在所有受管节点上生成含有以下信息的输出文件 /root/hwreport.txt :
您的 playbook 应当:
解答
主机名称
[greg@bastion ansible]$ ansible dev -m setup -a 'filter=*host*'
得到主机名称的变量:ansible_hostname
总内存大小
[greg@bastion ansible]$ ansible dev -m setup |grep mem
得到总内存大小的变量:ansible_memtotal_mb
BIOS 版本
[greg@bastion ansible]$ ansible dev -m setup |grep bios
得到BIOS 版本的变量:ansible_bios_version
vda和vdb的大小
[greg@bastion ansible]$ ansible dev -m setup -a 'filter=*device*'
得到vda和vdb的大小的变量:ansible_devices.vda.size
和 ansible_devices.vdb.size
[greg@bastion ansible]$ vim /home/greg/ansible/hwreport.yml
---
- name: product hardware report
hosts: all
tasks:
- name: Download hwreport.empty
get_url:
url: http://materials/hwreport.empty
dest: /root/hwreport.txt
- name: Ensure1
lineinfile:
path: /root/hwreport.txt
regexp: '^HOST='
line: HOST={{ inventory_hostname }}
- name: Ensure2
lineinfile:
path: /root/hwreport.txt
regexp: '^MEMORY='
line: MEMORY={{ ansible_memtotal_mb }}
- name: Ensure3
lineinfile:
path: /root/hwreport.txt
regexp: '^BIOS='
line: BIOS={{ ansible_bios_version }}
- name: Ensure4
lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDA='
line: DISK_SIZE_VDA={{ ansible_devices.vda.size }}
- name: Ensure5
lineinfile:
path: /root/hwreport.txt
regexp: '^DISK_SIZE_VDB='
line: DISK_SIZE_VDB={{ ansible_devices.vdb.size | default('NONE',true) }}
默认值是NONE,如果不存在vdb
[greg@bastion ansible]$ ansible-playbook hwreport.yml
验证
[greg@bastion ansible]$ ansible all -a 'cat /root/hwreport.txt'
172.25.250.11 | CHANGED | rc=0 >>
# Hardware report
HOST=172.25.250.11
MEMORY=821
BIOS=1.11.1-3.module+el8+2529+a9686a4d
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=5.00 GB
172.25.250.13 | CHANGED | rc=0 >>
# Hardware report
HOST=172.25.250.13
MEMORY=821
BIOS=1.11.1-3.module+el8+2529+a9686a4d
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=5.00 GB
172.25.250.12 | CHANGED | rc=0 >>
# Hardware report
HOST=172.25.250.12
MEMORY=821
BIOS=1.11.1-3.module+el8+2529+a9686a4d
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=5.00 GB
172.25.250.10 | CHANGED | rc=0 >>
# Hardware report
HOST=172.25.250.10
MEMORY=821
BIOS=1.11.1-3.module+el8+2529+a9686a4d
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=5.00 GB
172.25.250.9 | CHANGED | rc=0 >>
# Hardware report
HOST=172.25.250.9
MEMORY=1829
BIOS=1.11.1-3.module+el8+2529+a9686a4d
DISK_SIZE_VDA=10.00 GB
DISK_SIZE_VDB=NONE
创建密码库
按照下方所述,创建一个 Ansible 库来存储用户密码:
-
库名称为 /home/greg/ansible/locker.yml -
库中含有两个变量,名称如下:
-
pw_developer,值为 Imadev -
pw_manager,值为 Imamgr -
用于加密和解密该库的密码为 whenyouwishuponastar -
密码存储在文件 /home/greg/ansible/secret.txt 中
解答
- 创建一个包含变量的playbook脚本,这个playbook脚本的加密密码为redhat,但是这个密码包含在secret.txt这个文件内
- 加密playbook脚本的话需要用到
ansible-vault 这条命令,用来加密脚本
[greg@bastion ansible]$ vim /home/greg/ansible/locker.yml
---
- pw_developer: Imadev
- pw_manager: Imager
用echo命令加重定向符号将redhat输入到secret这个文件内。
[greg@bastion ansible]$ echo whenyouwishuponastar > /home/greg/ansible/secret.txt
[greg@bastion ansible]$ cat /home/greg/ansible/secret.txt
whenyouwishuponastar
[greg@bastion ansible]$ ansible-vault encrypt --vault-id=secret.txt locker.yml
Encryption successful
验证
用ansible-vault view 文件名,然后输入加密时的密码,就可以看见我们加密后的playbook脚本的内容了
[greg@bastion ansible]$ ansible-vault view locker.yml
Vault password:
- pw_developer: Imadev
- pw_manager: Imager
创建用户帐户
-
从 http://materials/user_list.yml 下载要创建的用户的列表,并将它保存到 /home/greg/ansible -
在本次考试中使用在其他位置创建的密码库 /home/greg/ansible/locker.yml 。创建名为 /home/greg/ansible/users.yml 的 playbook ,从而按以下所述创建用户帐户:
-
职位描述为 developer 的用户应当:
-
职位描述为 manager 的用户应当:
-
在 prod 主机组中的受管节点上创建 -
从 pw_manager 变量分配密码 -
是补充组 opsmgr 的成员 -
密码采用 SHA512 哈希格式。 -
您的 playbook 应能够在本次考试中使用在其他位置创建的库密码文件 /home/greg/ansible/secret.txt 正常运行。
解答
- 需要用到我们上一题所创建的变量,要用vars_files选项来引入变量文件根据题目要求职位为developer才进行创建用户操作
- 那必然需要用到when判断。这里的用户不止一个,那就需要用到loop循环进行逐一创建
下载创建的用户的列表
[kiosk@foundation0 materials]$ scp user_list.yml greg@bastion:/home/greg/ansible/
[greg@bastion ansible]$ cat user_list.yml
users:
- name: bob
job: developer
- name: sally
job: manager
- name: fred
job: developer
[greg@bastion ansible]$ vim /home/greg/ansible/users.yml
---
- name: user
hosts: dev,test
vars_files:
- user_list.yml
- locker.yml
tasks:
- name: add group
group:
name: devops
state: present
- name: add user
user:
name: "{{ item.name }}"
password: "{{ pw_developer | password_hash('sha512') }}"
groups: devops
loop:
"{{ users }}"
when: item.job == 'developer'
- name: user1
hosts: prod
vars_files:
- user_list.yml
- locker.yml
tasks:
- name: add group
group:
name: opsmgr
state: present
- name: add user
user:
name: "{{ item.name }}"
password: "{{ pw_manager | password_hash('sha512') }}"
groups: opsmgr
loop:
"{{ users }}"
when: item.job == 'manager'
执行剧本需要上一题的密码
[greg@bastion ansible]$ ansible-playbook --ask-vault-pass users.yml
输入密码:whenyouwishuponastar
验证
执行完毕后
[greg@bastion ansible]$ ansible dev,test -m shell -a 'tail -2 /etc/passwd'
172.25.250.10 | CHANGED | rc=0 >>
bob:x:1002:1002::/home/bob:/bin/bash
fred:x:1003:1003::/home/fred:/bin/bash
172.25.250.9 | CHANGED | rc=0 >>
bob:x:1002:1003::/home/bob:/bin/bash
fred:x:1003:1004::/home/fred:/bin/bash
[greg@bastion ansible]$ ansible prod -m shell -a 'tail -3 /etc/passwd'
172.25.250.11 | CHANGED | rc=0 >>
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
nginx:x:990:986:Nginx web server:/var/lib/nginx:/sbin/nologin
sally:x:1002:1003::/home/sally:/bin/bash
172.25.250.12 | CHANGED | rc=0 >>
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
nginx:x:990:986:Nginx web server:/var/lib/nginx:/sbin/nologin
sally:x:1002:1003::/home/sally:/bin/bash
不同服务器的不同用户创建成功
更新 Ansible 库的密钥
按照下方所述,更新现有 Ansible 库的密钥:
解答
- 需要用到ansible-vault rekey 这条命令,此命令是来更改加密文件的密码的
[kiosk@foundation0 materials]$ scp salaries.yml greg@bastion:/home/greg/ansible/
salaries.yml
[greg@bastion ansible]$ cat salaries.yml
$ANSIBLE_VAULT;1.1;AES256
30663136613361646566623236613636363637666234336639643037353861373066643366343764
3166313830316162333838623537386161353637373935300a316463633364616461636335323336
36316163656266303261343763666432623931326530623934663930393939663233306535346631
3236306163633833300a623836616639303732663833353832346435373736313230373036336132
6235
[greg@bastion ansible]$ ansible-vault rekey salaries.yml
Vault password: insecure8sure
New Vault password: bbs2you9527
Confirm New Vault password: bbs2you9527
Rekey successful
验证
新密码验证
[greg@bastion ansible]$ ansible-vault view salaries.yml
Vault password:
haha
|