网络信息:
所有系统的root密码都是redhat
重置实验环境:rhce8-reset
1.安装和配置Ansible
[gzy@RHCE9-EXAM1 ~]$ ssh control
//普通用户登录
[greg@control ~]$ su -
//切换root用户安装软件
[root@control ~]# yum -y install ansible-core rhel-system-roles wget vim
[greg@control ~]$ mkdir ansible
[greg@control ~]$ cd ansible/
[greg@control ansible]$ vi ansible.cfg
[greg@control ansible]$ cat ansible.cfg
[defaults]
inventory = /home/greg/ansible/inventory
remote_user = greg
roles_path = /home/greg/ansible/roles:/usr/share/ansible/roles/
collections_paths = /home/greg/ansible/collections
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
[greg@control ansible]$ vi inventory
[greg@control ansible]$ cat inventory
[dev]
node1
[test]
node2
[prod]
node3
node4
[balancers]
node5
[webservers:children]
prod
验证:
ansible all -m ping
node1 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
2.创建和运行Ansible临时命令
解法1使用bash脚本
[greg@control ansible]$ pwd
/home/greg/ansible
[greg@control ansible]$ vi adhoc.sh
[greg@control ansible]$ cat adhoc.sh
ansible all -m yum_repository -a " name='EX294_BASE' descriptinotallow='EX294 base software' baseurl='http://repo.domain10.example.com/rhce9/rhel9-baseos/BaseOS' gpgcheck=yes gpgkey='http://repo.domain10.example.com/rhce9/rhel9-baseos/RPM-GPG-KEY-redhat-release' enabled=yes"
ansible all -m yum_repository -a " name='EX294_STREAM' descriptinotallow='EX294 stream software' baseurl='http://repo.domain10.example.com/rhce9/rhel9-baseos/AppStream' gpgcheck=yes gpgkey='http://repo.domain10.example.com/rhce9/rhel9-baseos/RPM-GPG-KEY-redhat-release' enabled=yes"
[greg@control ansible]$ chmod +x adhoc.sh
[greg@control ansible]$ ./adhoc.sh
解法2使用yml方式
[greg@control ansible]$ vi yum.yml
[greg@control ansible]$ cat yum.yml
---
- name: set repo
hosts: all
tasks:
- name: Add base repo
yum_repository:
name: EX294_BASE
description: EX294 base software
baseurl: http://repo.domain10.example.com/rhce9/rhel9-baseos/BaseOS
gpgcheck: yes
gpgkey: http://repo.domain10.example.com/rhce9/rhel9-baseos/RPM-GPG-KEY-redhat-release
enabled: yes
- name: Add appstraem repo
yum_repository:
name: EX294_STREAM
description: EX294 stream software
baseurl: http://repo.domain10.example.com/rhce9/rhel9-baseos/AppStream
gpgcheck: yes
gpgkey: http://repo.domain10.example.com/rhce9/rhel9-baseos/RPM-GPG-KEY-redhat-release
enabled: yes
[greg@control ansible]$ ansible-playbook yum.yml
验证:
登录节点查看repo文件
cat /etc/yum.repos.d/E*
3.安装软件包
[greg@control ansible]$ pwd
/home/greg/ansible
[greg@control ansible]$ cat packages.yml
---
- name: install on 3
hosts: dev,test,prod
tasks:
- name: install php
yum:
name:
- php
- mariadb
- tftp
state: present
- name: install rpm on dev
hosts: dev
tasks:
- name: install group
yum:
name: "@RPM Development Tools"
state: present
- name: update
hosts: dev
tasks:
- name: up
yum:
name: "*"
state: latest
验证:
ansible-play packages.yml
4.配置计划任务
[greg@control ansible]$ pwd
/home/greg/ansible
[greg@control ansible]$ cat crond.yml
---
- name: crontab
hosts: test
tasks:
- name: create user
user:
name: natasha
- name: crond
cron:
name: test
minute: "*/5"
job: echo test
user: natasha
验证:
ansible-playbook crond.yml
5.使用RHEL系统角色-timesync
[greg@control ansible]$ pwd
/home/greg/ansible
[greg@control ansible]$ cat timesync.yml
---
- hosts: all
vars:
timesync_ntp_servers:
- hostname: rhgls.domain10.example.com
iburst: yes
roles:
- rhel-system-roles.timesync
验证:
ansible-playbook timesync.yml
登录节点:
cat /etc/chrony.conf
6.使用RHEL系统角色-selinux
[greg@control ansible]$ pwd
/home/greg/ansible
[greg@control ansible]$ cat selinux.yml
---
- name: selinux
hosts: all
vars:
selinux_policy: targeted
selinux_state: enforcing
roles:
- role: rhel-system-roles.selinux
验证:
ansible-playbook selinux.yml
ansible all -m shell -a 'cat /etc/selinux/config | grep ^SE'
7.使用Ansible Galaxy安装角色和collection
[greg@control ansible]$ cat requirements.yml
- src: http://rhgls.domain10.example.com/materials/haproxy.tar
name: balancer
- src: http://rhgls.domain10.example.com/materials/phpinfo.tar
name: phpinfo
[greg@control ansible]$ cat collections.yml
collections:
- name: http://rhgls.domain10.example.com/materials/ansible-posix-1.5.1.tar.gz
- name: http://rhgls.domain10.example.com/materials/community-general-6.3.0.tar.gz
[greg@control ansible]$ ansible-galaxy install -r requirements.yml
Starting galaxy role install process
- downloading role from http://rhgls.domain10.example.com/materials/haproxy.tar
- extracting balancer to /home/greg/ansible/roles/balancer
- balancer was installed successfully
- downloading role from http://rhgls.domain10.example.com/materials/phpinfo.tar
- extracting phpinfo to /home/greg/ansible/roles/phpinfo
- phpinfo was installed successfully
[greg@control ansible]$ ll roles/
total 0
drwxr-xr-x. 9 greg greg 122 Sep 1 15:16 balancer
drwxr-xr-x. 9 greg greg 122 Sep 1 15:16 phpinfo
[greg@control ansible]$ ansible-galaxy collection install -r collections.yml
[greg@control ansible]$ ll collections/ansible_collections/
total 0
drwxr-xr-x. 3 greg greg 19 Sep 1 15:18 ansible
drwxr-xr-x. 3 greg greg 21 Sep 1 15:18 community
验证:
查看安装后文件目录是否存在
8.创建一个web role
[greg@control ansible]$ ansible-galaxy init --init-path roles/ apache
- Role apache was created successfully
[greg@control ansible]$ ll roles/
total 0
drwxr-xr-x. 10 greg greg 154 Sep 1 15:24 apache
drwxr-xr-x. 9 greg greg 122 Sep 1 15:16 balancer
drwxr-xr-x. 9 greg greg 122 Sep 1 15:16 phpinfo
[greg@control ansible]$ cat roles/apache/tasks/main.yml
---
# tasks file for apache
- name: install
yum:
name: httpd
state: latest
- name: set httpd
service:
name: httpd
enabled: yes
state: started
- name: set firewalld
service:
name: firewalld
enabled: yes
state: started
- name: set firewalld
firewalld:
service: http
immediate: yes
permanent: yes
state: enabled
- name: set web
template:
src: index.html.j2
dest: /var/www/html/index.html
[greg@control ansible]$ cat roles/apache/templates/index.html.j2
Welcome to {{ ansible_fqdn }} on {{ ansible_default_ipv4['address'] }}
[greg@control ansible]$ cat apache.yml
---
- name: use apache
hosts: webservers
role:
- apache
[greg@control ansible]$ ansible-playbook apache.yml
验证:
[greg@control ansible]$ curl node3.domain10.example.com
Welcome to node3.domain10.example.com on 172.24.10.203
[greg@control ansible]$ curl node4.domain10.example.com
Welcome to node4.domain10.example.com on 172.24.10.204
9.从Ansible Galaxy使用角色
[greg@control ansible]$ cat roles.yml
---
- name: gaehters facts from hosts
hosts: webservers
- name: use phpinfo role
hosts: webservers
roles:
- phpinfo
- name: use balancers role
hosts: webservers
roles:
- balancer
[greg@control ansible]$ ansible-playbook roles.yml
[greg@control ansible]$ ssh root@node5
root@node5's password:
Last login: Fri Sep 1 17:09:54 2023 from 172.24.10.200
[root@node5 ~]#
[root@node5 ~]# firewall-cmd --add-port=80/tcp
success
[root@node5 ~]# firewall-cmd --add-port=80/tcp --per
success
验证:
[greg@control ansible]$ curl node5
Welcome to node3.domain10.example.com on 172.24.10.203
[greg@control ansible]$ curl node5
Welcome to node4.domain10.example.com on 172.24.10.204
10.管理节点分区
[greg@control ansible]$ cat part.yml
---
- name: part
hosts: all
tasks:
- name: fail message
fail:
msg: "vdc not found"
when: "'vdc' not in ansible_devices"
ignore_errors: yes
- block:
- name: part
parted:
device: /dev/vdc
number: 1
state: present
part_end: 2GiB
rescue:
- name: error
debug:
msg: "insufficient free space"
- name: part
parted:
device: /dev/vdc
number: 1
state: present
part_end: 800MiB
when: ansible_devices.vdc is defined
always:
- name: gather facts
setup:
- name: format filesystem
filesystem:
fstype: xfs
dev: /dev/vdc1
when: ansible_devices.vdc.partitions.vdc1 is defined
//在任务中,首先使用了一个名为fail message的任务,当 vdc 不在 ansible_devices 中时,会触发失败,并输出vdc not found的错误消息。使用了ignore_errors: yes参数,表示忽略此错误并继续执行 playbook。
接下来是一个block块,其中包含两个任务。第一个任务使用parted模块对/dev/vdc设备进行分区操作。分区号为1,结束位置为2GiB。如果此任务失败,将进入rescue块。
在rescue块中,首先有一个名为error的任务,它使用debug模块输出错误消息insufficient free space。然后再执行另一个parted任务,对/dev/vdc设备进行分区操作,分区号为1,结束位置为800MiB。这个任务仅在ansible_devices.vdc已定义时才会执行。
最后,在always块中,有两个任务。第一个任务使用setup模块,收集有关远程主机的事实信息。第二个任务使用filesystem模块,对/dev/vdc1进行文件系统格式化操作。这个任务仅在ansible_devices.vdc.partitions.vdc1已定义时才会执行。
[greg@control ansible]$ ansible-playbook part.yml
验证:
[greg@control ansible]$ ansible all -m shell -a 'lsblk | grep vdc'
node4 | CHANGED | rc=0 >>
vdc 253:32 0 1G 0 disk
????vdc1 253:33 0 799M 0 part
node5 | FAILED | rc=1 >>
non-zero return code
node2 | CHANGED | rc=0 >>
vdc 253:32 0 10G 0 disk
????vdc1 253:33 0 2G 0 part
node3 | CHANGED | rc=0 >>
vdc 253:32 0 10G 0 disk
????vdc1 253:33 0 2G 0 part
node1 | CHANGED | rc=0 >>
vdc 253:32 0 10G 0 disk
????vdc1 253:33 0 2G 0 part
11.创建和使用逻辑卷
[greg@control ansible]$ cat lv.yml
---
- name: create lv
hosts: all
task:
- block:
- name: create lv on research
lvol:
vg: research
lv: data
size: 1500
- name: format ext4
filesystem:
fstype: ext4
dev: /dev/research/data
rescue:
- name: out
debug:
msg: Could not create logical volume of that size
when: ansible_lvm.vgs.research is defined
- name: create lv on research
lvol:
vg: research
lv: data
size: 800
when: ansible_lvm.vgs.research is defined
- name: format ext4
filesystem:
fstype: ext4
dev: /dev/research/data
when: ansible_lvm.vgs.research is defined
- name: not exist
debug:
msg: Volume group does not exist
when: ansible_lvm.vgs.research is undefined
在任务中,首先有一个名为create lv on research的任务,使用lvol模块在research卷组(volume group)上创建了一个名为data的逻辑卷,大小为1500。如果此任务失败,将进入rescue块。
在rescue块中,首先是一个名为out的任务,它使用debug模块输出错误消息Could not create logical volume of that size,表示无法创建指定大小的逻辑卷。然后再执行另外两个任务,一个是创建800大小的逻辑卷,另一个是对逻辑卷进行格式化,这两个任务仅在ansible_lvm.vgs.research已定义时执行。
最后,在rescue块中还有一个名为not exist的任务,它使用debug模块输出错误消息Volume group does not exist,表示指定的卷组不存在。
[greg@control ansible]$ ansible-playbook lv.yml
验证:
[greg@control ansible]$ ansible all -m shell -a 'lsblk | grep data'
node1 | CHANGED | rc=0 >>
????research-data 252:0 0 1.5G 0 lvm
node3 | CHANGED | rc=0 >>
????research-data 252:0 0 800M 0 lvm
node2 | FAILED | rc=1 >>
non-zero return code
node4 | CHANGED | rc=0 >>
????research-data 252:0 0 800M 0 lvm
node5 | CHANGED | rc=0 >>
????research-data 252:0 0 1.5G 0 lvm
12.生成主机文件
[greg@control ansible]$ wget http://rhgls.domain10.example.com/materials/hosts.j2
空文件需要自己编辑
[greg@control 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@control ansible]$ cat hosts.yml
---
- name: create a host file
hosts: all
tasks:
- name: template a host file
template:
src: hosts.j2
dest: /etc/myhosts
when: '"dev" in group_names'
[greg@control ansible]$ ansible-playbook hosts.yml
验证:
[greg@control ansible]$ ansible node1 -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.24.10.201 node1.domain10.example.com node1
172.24.10.202 node2.domain10.example.com node2
172.24.10.205 node5.domain10.example.com node5
172.24.10.203 node3.domain10.example.com node3
172.24.10.204 node4.domain10.example.com node4
13.修改文件内容
[greg@control ansible]$ cat issue.yml
---
- name: create issue
hosts: all
tasks:
- name: dev
copy:
content: "Development"
dest: /etc/issue
when: "'dev' in group_names"
- name: test
copy:
content: "Test"
dest: /etc/issue
when: "'test' in group_names"
- name: prod
copy:
content: "Production"
dest: /etc/issue
when: "'prod' in group_names"
[greg@control ansible]$ ansible-playbook issue.yml
验证:
[greg@control ansible]$ ansible all -m shell -a 'cat /etc/issue'
node5 | CHANGED | rc=0 >>
\S
Kernel \r on an \m
node1 | CHANGED | rc=0 >>
Development
node2 | CHANGED | rc=0 >>
Test
node4 | CHANGED | rc=0 >>
Production
node3 | CHANGED | rc=0 >>
Production
14.创建web内容目录
[greg@control ansible]$ cat webcontent.yml
---
- name: set web content
hosts: dev
tasks:
- name: add web group
group:
name: webdev
state: present
- name: create a dir
file:
path: /webdev
state: directory
group: webdev
mode: "2775"
setype: "httpd_sys_content_t"
- name: create soft link
file:
src: /var/www/html/webdev
dest: /webdev
state: link
- name: set web content
copy:
content: Development
dest: /webdev/index.html
setype: "httpd_sys_content_t"
- name: set httpd service
servcie:
name: httpd
state: started
enabled: yes
- name: set firewalld
firewalld:
service: httpd
immediate: yes
permanet: yes
state: enabled
[greg@control ansible]$ ansible-playbook webcontent.yml
验证:
[greg@control ansible]$ curl http://node1.domain10.example.com/webdev/
15.生成硬件报告
[greg@control ansible]$ cat hwreport.yml
---
- name: create hardware report
hosts: all
vars:
hardware:
- hw_name: HOST
hw_info: "{{ ansible_hostname }}"
- hw_name: MEMORY
hw_info: "{{ ansible_memtotal_mb }}"
- hw_name: BIOS
hw_info: "{{ ansible_bios_version }}"
- hw_name: DISK_SIZE_VDA
hw_info: "{{ ansible_devices['vda']['size'] | default('NONE')
}}"
- hw_name: DISK_SIZE_VDB
hw_info: "{{ ansible_devices['vdb']['size'] | default('NONE')
}}"
- hw_name: DISK_SIZE_VDC
hw_info: "{{ ansible_devices['vdc']['size'] | default('NONE')
}}"
tasks:
- name: get file from url
get_url:
url: http://rhgls.domain10.example.com/materials/hwreport.empty
dest: /root/hwreport.txt
- name: set content
lineinfile:
path: /root/hwreport.txt
regexp: "^{{ item['hw_name'] }}="
line: "{{ item['hw_name'] }}={{ item['hw_info'] }}"
loop: "{{ hardware }}"
验证:
16.使用Ansible Vault
[greg@control ansible]$ cat locker.yml
pw_developer=Imadev
pw_manager=Imamgr
[greg@control ansible]$ cat secret.txt
whenyouwishuponastar
[greg@control ansible]$ ansible-vault encrypt --vault-password-file secret.txt locker.yml
Encryption successful
[greg@control ansible]$ cat locker.yml
$ANSIBLE_VAULT;1.1;AES256
63376463616365643738323137636162363537303430373264616233333431346333323336353831
6338663338616530373134363961343161626263306464370a643731313130353435663131353635
35363439666538306436306636383734623161616530323366626364646561306639643132663732
3466383139323939390a646531346163353864386366303332663062373936346132373038353065
32636637336437653534393139383761613733666331383635326665356562323064353730626336
6461393039353039396631666635383935326665643834363066
验证:
[greg@control ansible]$ ansible-vault view --vault-password-file secret.txt locker.yml
pw_developer: Imadev
pw_manager: Imamgr
17.创建批量添加用户role
[greg@control ansible]$ wget http://rhgls.domain10.example.com/materials/user_list.yml
[greg@control ansible]$ cat user_list.yml
---
users:
- name: gzy001
job: developer
password_expire_MAX: 30
- name: gzy002
job: developer
password_expire_MAX: 30
- name: gzy003
job: developer
password_expire_MAX: 30
- name: gzy101
job: manager
password_expire_MAX: 30
[greg@control ansible]$ cat users.yml
---
- name: create user on dev
hosts: dev,test
vars_files:
- locker.yml
- user_list.yml
tasks:
- name: create group
group:
name: devops
- name: create user
user:
name: "{{ item['name'] }}"
password: "{{ pw_developer | password_hash('sha512','mysecretsalt') }}"
password_expire_max: "{{ item.password_expire_MAX }}"
groups: devops
loop: "{{ users }}"
when: item.job == 'developer'
- name: create user on prod
hosts: prod
vars_files:
- locker.yml
- user_list.yml
tasks:
- name: create group
group:
name: opsmgr
- name: create user
user:
name: "{{ item['name'] }}"
password: "{{ pw_manager | password_hash('sha512','mysecretsalt') }}"
password_expire_max: "{{ item.password_expire_MAX }}"
groups: opsmgr
loop: "{{ users }}"
when: item.job == 'manager'
[greg@control ansible]$ ansible-playbook users.yml --vault-password-file secret.txt
验证:
[greg@control ansible]$ ansible node1,node2,node3,node4 -m shell -a "cat /etc/passwd | grep gzy"
node1 | CHANGED | rc=0 >>
gzy:x:1000:1000:gzy:/home/gzy:/bin/bash
gzy001:x:1002:1004::/home/gzy001:/bin/bash
gzy002:x:1003:1005::/home/gzy002:/bin/bash
gzy003:x:1004:1006::/home/gzy003:/bin/bash
node2 | CHANGED | rc=0 >>
gzy:x:1000:1000:gzy:/home/gzy:/bin/bash
gzy001:x:1003:1004::/home/gzy001:/bin/bash
gzy002:x:1004:1005::/home/gzy002:/bin/bash
gzy003:x:1005:1006::/home/gzy003:/bin/bash
node3 | CHANGED | rc=0 >>
gzy:x:1000:1000:gzy:/home/gzy:/bin/bash
gzy101:x:1002:1003::/home/gzy101:/bin/bash
node4 | CHANGED | rc=0 >>
gzy:x:1000:1000:gzy:/home/gzy:/bin/bash
gzy101:x:1002:1003::/home/gzy101:/bin/bash
18.重新设置Ansible Vault密码
[greg@control ansible]$ ansible-vault view salaries.yml
Vault password: insecure4sure
Your salaries is 1 million per month
//查看
[greg@control ansible]$ ansible-vault rekey salaries.yml
Vault password: insecure4sure
New Vault password: bbe2de98389b
Confirm New Vault password: bbe2de98389b
Rekey successful
//修改密码
验证:
[greg@control ansible]$ ansible-vault view salaries.yml
Vault password: bbe2de98389b
Your salaries is 1 million per month