1368 lines
40 KiB
Markdown
1368 lines
40 KiB
Markdown
# 1. ansible自动化运维
|
||
|
||
## 1.1 ansible介绍
|
||
|
||
ansible 是一个开源的自动化运维工具,主要用于系统配置管理、应用部署、任务编排等场景。它使用 YAML 语法编写配置文件,语法简单易懂,学习曲线平缓。ansible 的任务是幂等的,意味着多次执行结果是一致的,不会产生意外结果,非常适合于持续部署和集成。
|
||
|
||
ansible 支持众多常见操作系统和中间件,具有良好的扩展性。同时它还支持自定义模块,可以满足各种复杂的自动化需求。另一个特点是 ansible 不需要在远程主机上安装任何代理,只需要有 SSH 访问权限即可,并且不需要中央控制节点,使用 SSH 协议直接连接远程主机,部署和维护相对简单。ansible 使用 SSH 进行远程连接和命令执行,保证了数据传输的安全性。
|
||
|
||
ansible由python开发,集合了众多自动化运维工具的优点,实现了批量系统部署、批量程序部署,批量运行命令等功能。ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是ansible运行的模块,ansible只是提供一个框架。
|
||
|
||
## 1.2 核心组件
|
||
|
||

|
||
|
||
ansible:ansible核心程序。 HostInventory:记录由ansible管理的主机信息,包括端口、密码、ip等。 Playbooks:“剧本”YAML格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。 CoreModules:核心模块,主要操作是通过调用核心模块来完成管理任务。 CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。 ConnectionPlugins:连接插件,ansible和Host通信使用
|
||
|
||
## 1.3 任务执行方式
|
||
|
||
- ad-HOC 点对点模式 使用单个模块,支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令 例如对大量服务器执行shell 或者执行某个linux命令。
|
||
- playbook 模式(剧本模式) 通过编写yaml格式文件组合多个task任务,实现一个想要达到的功能,相对于多个点对点模式组合操作配置,playbook这个功能非常强大
|
||
|
||
## 1.4 特点
|
||
|
||
- 不需要在被监控端上安装任何服务程序
|
||
- 无服务器端,使用时直接运行命令即可
|
||
- 基于模块工作,可以使用任意语言开发
|
||
- 使用yaml语言编写playbook
|
||
- 基于ssh工作
|
||
- 可实现多级指挥
|
||
- 具有幂等性,一种操作重复多次执行结果相同
|
||
|
||
## 1.5 执行过程
|
||
|
||
- 加载自己的配置文件,默认为/etc/ansible/ansible.cfg
|
||
- 加载自己对应的模块文件
|
||
- 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器
|
||
- 对应执行用户的家目录的.ansible/tmp/xx.py文件
|
||
- 给文件+x执行
|
||
- 执行并将返回结果,删除临时py文件,然后退出
|
||
|
||
# 2. ansible部署
|
||
|
||
- 安装ansible
|
||
|
||
```
|
||
[root@localhost ~]# yum install -y epel-release
|
||
[root@localhost ~]# yum install -y ansible
|
||
```
|
||
|
||
**说明:**ansible只是一个工具,不需要启动,安装好以后,直接使用即可。并且只有服务端需要安装,客户端不需要安装....
|
||
|
||
## 2.1 参数说明
|
||
|
||
```
|
||
`Inventory 文件参数:
|
||
-i 或 --inventory: 指定 Inventory 文件的路径
|
||
-l 或 --limit: 限制操作的主机范围
|
||
-g 或 --groups: 指定要操作的主机组
|
||
`剧本(Playbook)参数:
|
||
-p 或 --playbook-dir: 指定 Playbook 所在目录
|
||
-e 或 --extra-vars: 传递额外的变量
|
||
`任务(Task)参数:
|
||
-m 或 --module-name: 指定要使用的模块名称
|
||
-a 或 --args: 传递模块的参数
|
||
`连接参数:
|
||
-c 或 --connection: 指定连接类型,如 ssh、local 等
|
||
-u 或 --user: 指定远程连接的用户
|
||
`输出参数:
|
||
-v 或 --verbose: 增加输出信息的详细程度
|
||
--check: 进行一次"试运行",不会实际改变任何状态
|
||
--diff: 显示配置文件的改动情况
|
||
`其他参数:
|
||
-f 或 --forks: 指定并行执行的进程数
|
||
-t 或 --tags: 只执行带有指定 tag 的任务
|
||
--list-hosts: 列出受管主机
|
||
--list-tasks: 列出所有任务
|
||
```
|
||
|
||
## 2.2 快速开始
|
||
|
||
**实验环境:**四台Linux虚拟机,HOSTNAME分别为:ansible、server1、server2、server3
|
||
|
||
其中,ansible做为服务端,其他server均作为客户端
|
||
|
||
1. 免密登录
|
||
|
||
```
|
||
# 在ansible上修改hosts文件,方便使用主机名管理主机
|
||
[root@ansible ~]# vim /etc/hosts
|
||
.......
|
||
192.168.88.10 server1
|
||
192.168.88.20 server2
|
||
192.168.88.30 server3
|
||
|
||
|
||
# 生成密钥对
|
||
[root@ansible ~]# ssh-keygen -P "" -t rsa
|
||
.....
|
||
# 将公钥发送给需要被管理端,以实现免密登录
|
||
|
||
|
||
[root@ansible ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@server1
|
||
[root@ansible ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@server2
|
||
[root@ansible ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@server3
|
||
```
|
||
|
||
### 2.2.1 常用工具
|
||
|
||
- ansible:临时命令执行工具,常用于执行临时命令
|
||
- ansible-doc:常用于模块功能的查询
|
||
- ansible-playbook:用于执行剧本
|
||
|
||
### 2.2.2 主要配置文件
|
||
|
||
- /etc/ansible/ansible.cfg:主配置文件
|
||
- /etc/ansible/hosts:主机清单文件
|
||
- /etc/ansible/roles:角色目录
|
||
|
||
### 2.2.3 配置主机清单
|
||
|
||
编辑`/etc/ansible/hosts`文件,再最后面添加上被管理端
|
||
|
||
```
|
||
[root@ansible ~]# vim /etc/ansible/hosts
|
||
......
|
||
......
|
||
......
|
||
## [dbservers]
|
||
##
|
||
## db01.intranet.mydomain.net
|
||
## db02.intranet.mydomain.net
|
||
## 10.25.1.56
|
||
## 10.25.1.57
|
||
|
||
|
||
# Here's another example of host ranges, this time there are no
|
||
# leading 0s:
|
||
|
||
|
||
## db-[99:101]-node.example.com
|
||
# 定义自己的主机组
|
||
[all_servers]
|
||
server1
|
||
server2
|
||
server3
|
||
|
||
|
||
[node1]
|
||
server1
|
||
|
||
|
||
[node2]
|
||
server2
|
||
|
||
|
||
[node3]
|
||
server3
|
||
```
|
||
|
||
- 主配置文件`ansible.cfg`,默认可以不用改
|
||
|
||
```
|
||
[root@localhost ~]# vim /etc/ansible/ansible.cfg
|
||
[defaults]
|
||
|
||
|
||
# some basic default values...
|
||
|
||
|
||
#inventory = /etc/ansible/hosts # 定义主机清单文件
|
||
#library = /usr/share/my_modules/ # 库文件的存放位置
|
||
#module_utils = /usr/share/my_module_utils/
|
||
#remote_tmp = ~/.ansible/tmp # 生成的临时py文件在远程主机的目录
|
||
#local_tmp = ~/.ansible/tmp # 生成的临时py文件在本地主机的目录
|
||
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml
|
||
#forks = 5 # 默认的并发数
|
||
#poll_interval = 15 # 默认的线程池
|
||
#sudo_user = root # 默认的sudo用户
|
||
#ask_sudo_pass = True
|
||
#ask_pass = True
|
||
#transport = smart
|
||
#remote_port = 22
|
||
#module_lang = C
|
||
#module_set_locale = False
|
||
transport = smart
|
||
在ansible配置中,transport = smart 是指定 ansible 用于远程连接的传输机制。smart 是 ansible 的默认传输选项,它会尝试根据环境自动选择最佳的传输机制。
|
||
|
||
|
||
当 smart 被设置时,ansible 会按照以下顺序尝试不同的传输机制:
|
||
|
||
|
||
如果已经建立了 SSH 连接(例如,通过 SSH Agent 或者在 ansible.cfg 中配置了 SSH 连接参数),则使用 SSH 传输。
|
||
如果未建立 SSH 连接,并且目标主机是本地主机,则使用本地传输(即直接在本地执行命令)。
|
||
如果未建立 SSH 连接,并且目标主机是远程主机,则使用 Paramiko 传输(基于 Python 的 SSH2 实现)。
|
||
通过使用 smart 选项,ansible 可以自动选择合适的传输机制,以确保在不同的环境中都能正常工作。如果您希望显式地指定传输机制,可以将 transport 设置为 ssh、local 或 paramiko,以强制使用相应的传输方式。
|
||
```
|
||
|
||
### 2.2.4 执行状态
|
||
|
||
ansible的执行状态
|
||
|
||
- 绿色:执行成功并且不需要做改变的操作
|
||
- 黄色:执行成功并且对目标主机做变更
|
||
- 红色:执行失败
|
||
- 粉色:警告信息
|
||
- 蓝色:显示ansible命令执行的过程
|
||
|
||
## 2.3 常用模块
|
||
|
||
### 2.3.1 ping模块
|
||
|
||
测试与主机的连通性
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m ping all_servers
|
||
server1 | SUCCESS => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
server3 | SUCCESS => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
server2 | SUCCESS => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": false,
|
||
"ping": "pong"
|
||
}
|
||
|
||
|
||
# 返回说明:
|
||
"SUCCESS" 表示 ansible 成功执行了任务,没有遇到错误。
|
||
"ansible_facts" 是一个包含 ansible 任务执行期间收集到的事实(facts)的字典。
|
||
"discovered_interpreter_python" 是一个收集到的事实,它指示目标主机上的 Python 解释器的路径为 /usr/bin/python。这对于后续的 ansible 任务可能需要使用 Python 的情况很有用。
|
||
"changed" 表示 ansible 是否对目标主机进行了更改。在这种情况下,值为 false 表示没有进行任何更改。
|
||
"ping" 是一个简单的回应,用于测试与目标主机的连通性。如果值为 "pong",表示与目标主机的连接正常。
|
||
```
|
||
|
||
### 2.3.2 Group模块
|
||
|
||
用户创建和修改用户组
|
||
|
||
示例:对node1主机组的成员创建一个IT组,组ID为111
|
||
|
||
```
|
||
[root@ansible ~]# ansible-doc -s group
|
||
action: group
|
||
gid # 设置组的GID号
|
||
name= # 管理组的名称
|
||
state # 指定组状态,默认为创建,设置值为absent为删除
|
||
system # 设置值为yes,表示为创建系统组
|
||
|
||
|
||
[root@ansible ~]# ansible -m group -a "name=IT gid=111 system=yes" node1
|
||
server1 | CHANGED => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": true,
|
||
"gid": 111,
|
||
"name": "IT",
|
||
"state": "present",
|
||
"system": true
|
||
}
|
||
```
|
||
|
||
### 2.3.3 User模块
|
||
|
||
用于对用户的创建,修改和删除等操作
|
||
|
||
```
|
||
# 查看某个模块的具体用法
|
||
[root@ansible ~]# ansible-doc -l|wc -l
|
||
3387 #共有3387个模块
|
||
[root@ansible ~]# ansible‐doc ‐s user
|
||
comment # 用户的描述信息
|
||
createhom # 是否创建家目录
|
||
force # 在使用`state=absent'是, 行为与`userdel ‐‐force'一致.
|
||
group # 指定基本组
|
||
groups # 指定附加组,如果指定为('groups=')表示删除所有组
|
||
home # 指定用户家目录
|
||
name # 指定用户名
|
||
password # 指定用户密码
|
||
remove # 在使用 `state=absent'时, 行为是与 `userdel ‐‐remove'一致.
|
||
shell # 指定默认shell
|
||
state #设置帐号状态,不指定为创建,指定值为absent表示删除
|
||
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
|
||
uid #指定用户的uid
|
||
update_password # 更新用户密码
|
||
expires #指明密码的过期时间
|
||
......
|
||
```
|
||
|
||
示例:在主机组node1上创建一个系统用户张三,家目录为/home/zhangsan,uid为111,附加组为IT,以及给一个注释
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m user -a "system=yes name=zhangsan home=/home/zhangsan uid=111 groups=IT comment='hello zhangsan'" node1
|
||
server1 | CHANGED => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": true,
|
||
"comment": "hello zhangsan",
|
||
"create_home": true,
|
||
"group": 995,
|
||
"groups": "IT",
|
||
"home": "/home/zhangsan",
|
||
"name": "zhangsan",
|
||
"shell": "/bin/bash",
|
||
"state": "present",
|
||
"system": true,
|
||
"uid": 111
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
# 删除用户及家目录
|
||
[root@ansible ~]# ansible -m user -a "name=zhangsan state=absent remove=yes" node1
|
||
|
||
|
||
# 添加系统用户,指定uid、家目录、主组及注释、密码
|
||
[root@ansible ~]# ansible -m user -a "system=yes name=zhangsan home=/home/zhangsan uid=111 group=root comment='hello zhangsan' password='123456' shell=/bin/cbash " node1
|
||
```
|
||
|
||
### 2.3.4 Command模块
|
||
|
||
command模块是ansible默认使用的模块。不支持管道,变量及重定向等
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# ansible-doc ‐s command
|
||
......
|
||
......
|
||
[root@ansible ~]# ansible -a "touch /root/ansible.txt" all_servers
|
||
[WARNING]: Consider using the file module with state=touch rather than running
|
||
'touch'. If you need to use command because file is insufficient you can add
|
||
'warn: false' to this command task or set 'command_warnings=False' in
|
||
ansible.cfg to get rid of this message.
|
||
server2 | CHANGED | rc=0 >>
|
||
|
||
|
||
server1 | CHANGED | rc=0 >>
|
||
|
||
|
||
server3 | CHANGED | rc=0 >>
|
||
|
||
|
||
|
||
|
||
[root@ansible ~]# ansible -a "find / -name ifcfg-ens33" all_servers
|
||
server1 | CHANGED | rc=0 >>
|
||
/etc/sysconfig/network-scripts/ifcfg-ens33
|
||
server2 | CHANGED | rc=0 >>
|
||
/etc/sysconfig/network-scripts/ifcfg-ens33
|
||
server3 | CHANGED | rc=0 >>
|
||
/etc/sysconfig/network-scripts/ifcfg-ens33
|
||
```
|
||
|
||
### 2.3.5 Shell模块
|
||
|
||
在远程主机上执行bash命令
|
||
|
||
相对于command而言,支持性更好一点,但是对于某些复杂的命令,也可能会执行失败
|
||
|
||
解决方法:可以把命令卸载脚本中,使用script模块执行脚本到远程主机
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m shell -a "hostname" all_servers
|
||
server1 | CHANGED | rc=0 >>
|
||
server1
|
||
server2 | CHANGED | rc=0 >>
|
||
server2
|
||
server3 | CHANGED | rc=0 >>
|
||
server3
|
||
```
|
||
|
||
### 2.3.6 Script模块
|
||
|
||
可以发送shell脚本到远程主机上并执行
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# vim test.sh
|
||
#!/bin/bash
|
||
for i in `seq 5`
|
||
do
|
||
touch /root/test_${i}.txt
|
||
done
|
||
|
||
|
||
# script模块
|
||
[root@ansible ~]# ansible -m script -a "/root/test.sh" node2
|
||
server2 | CHANGED => {
|
||
"changed": true,
|
||
"rc": 0,
|
||
"stderr": "Shared connection to server2 closed.\r\n",
|
||
"stderr_lines": [
|
||
"Shared connection to server2 closed."
|
||
],
|
||
"stdout": "",
|
||
"stdout_lines": []
|
||
}
|
||
|
||
|
||
# server2验证
|
||
[root@server2 ~]# ls
|
||
anaconda-ks.cfg test_1.txt test_3.txt test_5.txt
|
||
ansible.txt test_2.txt test_4.txt
|
||
|
||
|
||
# 参数说明
|
||
chdir参数: 此参数的作用就是指定一个远程主机中的目录,在执行对应的脚本之前,会先进入到 chdir 参数指定的目录中。
|
||
creates参数: 使用此参数指定一个远程主机中的文件,当指定的文件存在时,就不执行对应脚本
|
||
removes参数: 使用此参数指定一个远程主机中的文件,当指定的文件不存在时,就不执行对应脚本
|
||
```
|
||
|
||
### 2.3.7 Copy模块
|
||
|
||
用于向复制文件到主机组中
|
||
|
||
参数解释:
|
||
|
||
```
|
||
[root@ansible ~]# ansible-doc -s copy
|
||
backup:在覆盖之前,将源文件备份,备份文件包含时间信息。
|
||
content:用于替代“src”,可以直接设定指定文件的值
|
||
dest:必选项。要将源文件复制到的远程主机的绝对路径
|
||
directory_mode:递归设定目录的权限,默认为系统默认权限
|
||
force:强制覆盖目的文件内容,默认为yes
|
||
others:所有的file模块里的选项都可以在这里使用
|
||
src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制
|
||
|
||
|
||
ansible -m copy -a "src=/本地文件 dest=/远程文件" nodes
|
||
```
|
||
|
||
示例:
|
||
|
||
- 在创建文件时修改文件的属主和属组信息
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m copy -a "src=/root/test.sh dest=/root/test1 owner=zhangsan group=ansibles" node1
|
||
```
|
||
|
||
- 在传输文件时修改文件的权限信息,并且备份远程主机文件
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m copy -a "src=/root/test.sh dest=/root/test2 backup=yes mode=777" node1
|
||
```
|
||
|
||
- 创建一个文件并直接编辑文件
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m copy -a "content='hello ansibles\n' dest=/root/test3" node1
|
||
```
|
||
|
||
### 2.3.8 File模块
|
||
|
||
用于对文件进行相关操作
|
||
|
||
参数解释:
|
||
|
||
```
|
||
[root@ansible ~]# ansible‐doc ‐s file
|
||
‐ name: Sets attributes of files
|
||
force:需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
|
||
group:定义文件/目录的属组
|
||
mode:定义文件/目录的权限
|
||
owner:定义文件/目录的属主
|
||
path:必选项,定义文件/目录的路径
|
||
recurse:递归设置文件的属性,只对目录有效
|
||
src:被链接的源文件路径,只应用于state=link的情况
|
||
dest:被链接到的路径,只应用于state=link的情况
|
||
state:
|
||
absent: 删除文件
|
||
directory:如果目录不存在,就创建目录
|
||
file:验证文件是否存在,即使文件不存在,也不会被创建
|
||
link:创建软链接
|
||
hard:创建硬链接
|
||
touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其后修改时间
|
||
```
|
||
|
||
示例:
|
||
|
||
- 创建目录
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m file -a "name=test1 owner=root group=root mode=644 state=directory " node1
|
||
```
|
||
|
||
- 创建文件
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m file -a "path=/root/test2 owner=root group=root mode=644 state=touch" node1
|
||
```
|
||
|
||
- 删除文件/目录
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m file -a "path=/root/test2 state=absent" node1
|
||
```
|
||
|
||
- 创建软链接文件
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m file -a "src=/root/test1 dest=/root/test2 state=link" node1
|
||
```
|
||
|
||
- 创建硬链接文件
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m file -a "src=/root/test.txt dest=/root/test2 state=hard" node2
|
||
```
|
||
|
||
### 2.3.9 Yum模块
|
||
|
||
用于远程操作主机下载软件包
|
||
|
||
参数说明:
|
||
|
||
```
|
||
[root@ansible ~]# ansible‐doc ‐s yum
|
||
conf_file #设定远程yum安装时所依赖的配置文件。如配置文件没有在默认的位置。
|
||
disable_gpg_check #是否禁止GPG checking,只用于`present' or `latest'。
|
||
disablerepo #临时禁止使用yum库。 只用于安装或更新时。
|
||
enablerepo #临时使用的yum库。只用于安装或更新时。
|
||
name= #所安装的包的名称
|
||
state #present安装, latest安装最新的, absent 卸载软件。
|
||
update_cache #强制更新yum的缓存
|
||
```
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m yum -a "name=httpd state=latest" node3
|
||
server3 | CHANGED => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": true,
|
||
"changes": {
|
||
"installed": [
|
||
"httpd"
|
||
],
|
||
"updated": []
|
||
},
|
||
"msg": "",
|
||
"rc": 0,
|
||
```
|
||
|
||
### 2.3.10 Service模块
|
||
|
||
用于远程管理主机上的service服务类
|
||
|
||
参数说明:
|
||
|
||
```
|
||
[root@ansible ~]# ansible-doc -s service
|
||
> SERVICE (/usr/lib/python2.7/site‐packages/ansible/modules/system/service.py)
|
||
Controls services on remote hosts. Supported init systems include BSD init, OpenRC, SysV, Solaris
|
||
SMF, systemd, upstart. For Windows targets, use the [win_service] module instead.
|
||
* note: This module has a corresponding action plugin.
|
||
......
|
||
......
|
||
arguments #命令行提供额外的参数
|
||
enabled #设置开机启动,可以设置为yes或者no。
|
||
name= #服务名称
|
||
runlevel #开机启动的级别,一般不用指定。
|
||
sleep #在重启服务的过程中,是否等待。如在服务关闭以后等待2秒再启动。
|
||
state #started启动服务, stopped停止服务, restarted重启服务, reloaded重载配置
|
||
```
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m service -a "name=httpd state=started" node3
|
||
server3 | CHANGED => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": true,
|
||
"name": "httpd",
|
||
"state": "started"
|
||
.....
|
||
.....
|
||
```
|
||
|
||
### 2.3.11 Selinux模块
|
||
|
||
用于管理远程主机的selinux设置
|
||
|
||
参考说明:
|
||
|
||
```
|
||
[root@node1 ~]# ansible-doc -s selinux
|
||
# selinux模块针对selinux的修改操作是针对配置文件进行修改的
|
||
‐ name: Change policy and state of SELinux
|
||
configfile:
|
||
描述: SELinux 配置文件的路径,如果不是标准路径。
|
||
参数类型: 字符串
|
||
policy:
|
||
描述: 要使用的 SELinux 策略的名称。
|
||
参数类型: 字符串
|
||
state:
|
||
描述: (必需) SELinux 的模式。
|
||
参数类型: 字符串
|
||
可选值:
|
||
enforcing: 强制 SELinux 策略生效。
|
||
permissive: 以警告模式运行 SELinux,不会阻止任何操作。
|
||
disabled: 完全禁用 SELinux。
|
||
```
|
||
|
||
示例:
|
||
|
||
```
|
||
[root@ansible ~]# ansible -m selinux -a "state=enforcing policy=targeted" node1
|
||
[WARNING]: Reboot is required to set SELinux state to 'enforcing'
|
||
server1 | CHANGED => {
|
||
"ansible_facts": {
|
||
"discovered_interpreter_python": "/usr/bin/python"
|
||
},
|
||
"changed": true,
|
||
"configfile": "/etc/selinux/config",
|
||
"msg": "Config SELinux state changed from 'disabled' to 'enforcing'",
|
||
"policy": "targeted",
|
||
"reboot_required": true,
|
||
"state": "enforcing"
|
||
}
|
||
```
|
||
|
||
# 3. Playbook(剧本)
|
||
|
||
## 3.1 介绍
|
||
|
||
Ansible playbook是一种可执行的YAML文件,用于描述如何部署和配置一个系统或应用程序。一个playbook由一个或多个play组成,每个play都针对特定的主机或主机组执行一系列任务。
|
||
|
||
一个playbook的基本结构如下:
|
||
|
||
```
|
||
- hosts: all
|
||
vars:
|
||
package_name: nginx
|
||
config_file: /etc/nginx/nginx.conf
|
||
tasks:
|
||
- name: Install Nginx
|
||
yum:
|
||
name: "{{ package_name }}"
|
||
state: present
|
||
- name: Copy Nginx configuration
|
||
copy:
|
||
src: nginx.conf
|
||
dest: "{{ config_file }}"
|
||
notify:
|
||
- restart nginx
|
||
handlers:
|
||
- name: restart nginx
|
||
service:
|
||
name: nginx
|
||
state: restarted
|
||
```
|
||
|
||
在上面的例子中,我们定义了以下几个主要字段:
|
||
|
||
- `hosts`: 指定要运行任务的主机或主机组。
|
||
- `vars`: 定义要在playbook中使用的变量。
|
||
- `tasks`: 定义要执行的任务列表。每个任务都有一个名称和一个模块。
|
||
- `handlers`: 定义当某些任务触发时需要执行的处理程序,比如重启服务。
|
||
|
||
执行playbook剧本:
|
||
|
||
`ansible-playbook xxxxx.yaml`即可
|
||
|
||
## 3.2 快速开始
|
||
|
||
### 3.2.1 案例:服务安装
|
||
|
||
安装nginx并且修改配置文件
|
||
|
||
1. 先编写一个nginx的子配置文件
|
||
|
||
```
|
||
[root@ansible ~]# mkdir -p playbook/conf
|
||
[root@ansible ~]# cd playbook/conf
|
||
[root@ansible conf]# cat site.conf
|
||
server {
|
||
listen 666;
|
||
server_name localhost;
|
||
|
||
|
||
location / {
|
||
root /data;
|
||
index index.html
|
||
}
|
||
}
|
||
```
|
||
|
||
1. 编写playbook,要求是为目标机器安装nginx并且拷贝配置文件到该机器上,然后启动nginx。
|
||
|
||
```
|
||
[root@ansible playbook]# vim nginx.yaml
|
||
- name: install nginx web server
|
||
hosts: node1
|
||
remote_user: root
|
||
|
||
|
||
tasks:
|
||
- name: Install epel-release
|
||
yum:
|
||
name: epel-release
|
||
state: latest
|
||
|
||
|
||
- name: Install Nginx
|
||
yum:
|
||
name: nginx
|
||
state: latest
|
||
|
||
|
||
- name: Copy conf to nginx.conf.d
|
||
copy:
|
||
src: /root/playbook/conf/site.conf
|
||
dest: /etc/nginx/conf.d/site.conf
|
||
|
||
|
||
- name: Create "data" directory
|
||
file:
|
||
name: /data
|
||
state: directory
|
||
|
||
|
||
- name: Start Nginx service
|
||
service:
|
||
name: nginx
|
||
state: started
|
||
|
||
|
||
- name: create web index file
|
||
shell: echo "Install Nginx use Ansible...." > /data/index.html
|
||
```
|
||
|
||

|
||
|
||
## 3.3 高级配置
|
||
|
||
### 3.3.1 fact(事实变量)
|
||
|
||
Ansible 内置了大量的事实(fact)变量,可以在 Playbook 中使用。这些事实变量可以帮助我们更好地了解目标主机的环境和配置信息,从而编写更加智能和动态的自动化脚本。
|
||
|
||
常用的内置事实变量包括:
|
||
|
||
1. **操作系统信息**:
|
||
- `ansible_distribution`: 操作系统发行版名称,如 "CentOS"、"Ubuntu"
|
||
- `ansible_distribution_version`: 操作系统版本号
|
||
- `ansible_os_family`: 操作系统家族,如 "RedHat"、"Debian"
|
||
- `ansible_kernel`: 内核版本
|
||
2. **硬件信息**:
|
||
- `ansible_processor`: CPU 型号
|
||
- `ansible_processor_vcpus`: 虚拟 CPU 核数
|
||
- `ansible_memtotal_mb`: 内存总量(MB)
|
||
- `ansible_architecture`: CPU 架构,如 "x86_64"
|
||
3. **网络信息**:
|
||
- `ansible_default_ipv4`: 默认 IPv4 地址和网关
|
||
- `ansible_all_ipv4_addresses`: 所有 IPv4 地址
|
||
- `ansible_interfaces`: 所有网络接口名称
|
||
- `ansible_hostname`: 主机名
|
||
4. **其他信息**:
|
||
- `ansible_user_id`: 当前执行 Ansible 的用户 ID
|
||
- `ansible_date_time`: 主机当前日期和时间
|
||
- `ansible_env`: 主机环境变量
|
||
- `ansible_play_hosts`: 当前 play 中涉及的所有主机
|
||
|
||
这些事实变量可以帮助我们编写出更加智能和定制化的 Playbook。比如,我们可以根据操作系统的不同,执行不同的软件包安装任务;根据 CPU 架构,选择合适的软件包版本;根据内存大小,调整应用程序的配置等。
|
||
|
||
### 3.3.2 循环迭代
|
||
|
||
在playbook中,可以使用循环进行数据的迭代。这样一个模块就可以执行多次任务,因为往往我们部署一个服务的时候,都需要安装多个软件包的。
|
||
|
||
示例:使用yum循环安装软件包
|
||
|
||
```
|
||
- name: Install packages
|
||
yum:
|
||
name: "{{ item }}"
|
||
state: present
|
||
loop:
|
||
- nginx
|
||
- mysql
|
||
- php
|
||
```
|
||
|
||
或者:
|
||
|
||
```
|
||
- name: Install packages
|
||
yum:
|
||
name: "{{ item }}"
|
||
state: present
|
||
with_items:
|
||
- httpd
|
||
- mysql
|
||
- php
|
||
```
|
||
|
||
这样就可以实现一个yum安装多个软件包了,避免了playbook过于臃肿。
|
||
|
||
#### 3.3.2.1 RHCE真题讲解(2023-10)
|
||
|
||
创建一个名为 /home/student/ansible/packages.yml的 playbook:
|
||
|
||
1. 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上
|
||
2. 将 Development Tools 软件包组安装到 dev 主机组中的主机上
|
||
3. 将 dev 主机组中主机上的所有软件包更新为最新版本
|
||
|
||
```
|
||
[root@ansible ~]# vim playbook/packages.yml
|
||
- name: install pkgs
|
||
hosts: dev,test,prod
|
||
tasks:
|
||
- name: install mariadb php
|
||
yum:
|
||
name: "{{ item }}"
|
||
state: present
|
||
loop:
|
||
- php
|
||
- mariadb
|
||
|
||
|
||
- name: install group pkgs
|
||
hosts: dev
|
||
tasks:
|
||
- name: install Development Tools
|
||
yum:
|
||
name: "@Development Tools"
|
||
state: present
|
||
|
||
|
||
- name: update pkgs
|
||
hosts: dev
|
||
tasks:
|
||
- name: update pkgs
|
||
yum:
|
||
name: "*"
|
||
state: latest
|
||
|
||
|
||
```
|
||
|
||
#### 3.3.2.2 案例:循环创建用户
|
||
|
||
循环创建用户,用户信息如下 名称、组、家目录、shell、描述信息 zhangsan xsb /home/xsb/zhangsan /bin/bash 销售 lisi xsb /home/xsb/lisi /bin/bash 销售 wangwu jsb /home/jsb/wangwu /bin/sh java工程师 maliu jsb /home/jsb/maliu /bin/sh linux工程师 zhaoqi cwb /home/cwb/zhaoqi /bin/sh 会计
|
||
|
||
循环创建出以上用户并指定用户信息:
|
||
|
||
```
|
||
[root@ansible ~]# vim playbook/user.yml
|
||
- name: Manage user
|
||
hosts: node1
|
||
remote_user: root
|
||
tasks:
|
||
- name: Ensure groups xsb, jsb, cwb exist
|
||
group:
|
||
name: "{{ item.group }}"
|
||
with_items:
|
||
- { group: xsb }
|
||
- { group: jsb }
|
||
- { group: cwb }
|
||
|
||
|
||
- name: Create users zhangsan, lisi, wangwu, maliu, zhaoqi
|
||
user:
|
||
name: "{{ item.name }}"
|
||
group: "{{ item.group }}"
|
||
shell: "{{ item.shell }}"
|
||
comment: "{{ item.comment }}"
|
||
home: "{{ item.home }}"
|
||
with_items:
|
||
- { name: 'zhangsan', group: 'xsb', home: '/home/xsb/zhangsan', shell: '/bin/bash', comment: '销售' }
|
||
- { name: 'lisi', group: 'xsb', home: '/home/xsb/lisi', shell: '/bin/bash', comment: '销售' }
|
||
- { name: 'wangwu', group: 'jsb', home: '/home/jsb/wangwu', shell: '/bin/sh', comment: 'java工程师' }
|
||
- { name: 'maliu', group: 'jsb', home: '/home/jsb/maliu', shell: '/bin/sh', comment: 'linux工程师' }
|
||
- { name: 'zhaoqi', group: 'cwb', home: '/home/cwb/zhaoqi', shell: '/bin/sh', comment: '会计' }
|
||
|
||
|
||
```
|
||
|
||
|
||
|
||
### 3.3.3 条件判断
|
||
|
||
在 Ansible Playbook 中,我们可以使用条件判断语句来根据不同的条件执行不同的任务。
|
||
|
||
**when 语句:**
|
||
|
||
`when` 语句是最常用的条件判断语句。它可以根据变量的值、事实(facts)或者 Jinja2 表达式来决定是否执行某个任务。
|
||
|
||
```
|
||
- name: Install packages on CentOS 7
|
||
yum:
|
||
name:
|
||
- httpd
|
||
- mariadb-server
|
||
state: present
|
||
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version|int == 7
|
||
|
||
|
||
- name: Install packages on CentOS 8
|
||
yum:
|
||
name:
|
||
- nginx
|
||
- mysql-server
|
||
state: present
|
||
when: ansible_distribution == 'CentOS' and ansible_distribution_major_version|int == 8
|
||
```
|
||
|
||
在这个例子中:
|
||
|
||
1. 第一个任务会在 CentOS 7 系统上安装 httpd 和 mariadb-server 软件包。`when` 语句确保了只有在 `ansible_distribution` 等于 'CentOS' 且 `ansible_distribution_major_version` 等于 7 时,这个任务才会执行。
|
||
2. 第二个任务会在 CentOS 8 系统上安装 nginx 和 mysql-server 软件包。同样的,`when` 语句确保了只有在 `ansible_distribution` 等于 'CentOS' 且 `ansible_distribution_major_version` 等于 8 时,这个任务才会执行。
|
||
|
||
#### 3.3.3.1 RHCE真题讲解(2023-10-)
|
||
|
||
**考试原题(第八题):**
|
||
|
||
创建一个名为/home/student/ansible/parted.yml 的playbook,它将在dev主机组上运行下列任务
|
||
|
||
1. 如果磁盘/dev/vdd存在,则创建1500m分区
|
||
2. 如果无法创建请求的分区大小,应显示错误消息 Could not create partition of that size,并且应改为使用大小 800m。
|
||
3. 如果磁盘/dev/vdd不存在 ,应显示错误消息 disk /dev/vdd does not exist。
|
||
4. 如果磁盘/dev/vdb存在,则创建1500m分区
|
||
5. 如果无法创建请求的分区大小,应显示错误消息 Could not create partition of that size,并且应改为使用大小 800m。
|
||
6. 最后分区都要格式化为ext4文件系统,并挂载在/mnt/fs01上
|
||
|
||
**简化题目:**在所有机器上创建sdb1分区,大小为1Gib,前提是sdb存在,如果不存在,请提示.......
|
||
|
||
```
|
||
[root@ansible playbook]# vim disk.yaml
|
||
- name: Create sdb1 partition
|
||
hosts: all_servers
|
||
tasks:
|
||
- name: Check if sdb block device exists
|
||
stat:
|
||
path: /dev/sdb
|
||
register: sdb_stat
|
||
|
||
|
||
- name: Create 1GB partition on sdb
|
||
parted:
|
||
device: /dev/sdb
|
||
number: 1
|
||
state: present
|
||
part_end: 1GB
|
||
when: sdb_stat.stat.exists
|
||
|
||
|
||
- name: sdb block device not exists
|
||
debug:
|
||
msg: "sdb block device does not exist, cannot create partition."
|
||
when: not sdb_stat.stat.exists
|
||
|
||
|
||
|
||
|
||
# Output:
|
||
TASK [Create 1GB partition on sdb] ************************************ *********
|
||
skipping: [server1]
|
||
skipping: [server3]
|
||
changed: [server2]
|
||
|
||
|
||
TASK [sdb block device not exists] ************************************ *********
|
||
ok: [server1] => {
|
||
"msg": "sdb block device does not exist, cannot create partition."
|
||
}
|
||
skipping: [server2]
|
||
ok: [server3] => {
|
||
"msg": "sdb block device does not exist, cannot create partition."
|
||
}
|
||
```
|
||
|
||
**验证:**
|
||
|
||
```
|
||
[root@server2 ~]# lsblk
|
||
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
|
||
sda 8:0 0 20G 0 disk
|
||
├─sda1 8:1 0 1G 0 part /boot
|
||
└─sda2 8:2 0 19G 0 part
|
||
├─centos-root 253:0 0 17G 0 lvm /
|
||
└─centos-swap 253:1 0 2G 0 lvm [SWAP]
|
||
sdb 8:16 0 2G 0 disk
|
||
└─sdb1 8:17 0 953M 0 part
|
||
sr0 11:0 1 918M 0 rom
|
||
```
|
||
|
||
## 3.4 Jinjia2模板
|
||
|
||
Jinja2是一个功能强大的Python模板引擎,它被广泛应用于Ansible的playbook中。Jinja2模板语法提供了丰富的功能,使得在playbook中插入动态内容变得更加容易和灵活。
|
||
|
||
简单来讲,就是将原本静态的playbook转变为动态的。
|
||
|
||
### 3.4.1 RHCE真题讲解(2023-10)
|
||
|
||
**原题(第九题):**生成主机文件
|
||
|
||
1. 编写模板文件/home/student/ansible/hosts.j2 ,针对每个清单主机包含一行内容,其格式与 /etc/hosts 相同。
|
||
2. 创建名为 /home/student/ansible/hosts.yml 的playbook,它将使用此模板在 dev 主机组中的主 机上生成文件 /etc/myhosts。
|
||
3. 该 playbook 运行后,dev 主机组中主机上的文件/etc/myhosts 应针对每个受管主机包含一行内 容。
|
||
|
||
**题目变更如下:**
|
||
|
||
我们使用jinjia2和ansible内置变量动态的生成hosts文件,并且发送给远程主机
|
||
|
||
1. 编写模板文件
|
||
|
||
```
|
||
[root@ansible playbook]# vim hosts.j2
|
||
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
|
||
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
||
|
||
|
||
{% for host in groups.all_servers %}
|
||
{{hostvars[host].ansible_ens33.ipv4.address}} {{hostvars[host].ansible_hostname}}
|
||
{% endfor %}
|
||
```
|
||
|
||
1. 编写hosts.yaml剧本来渲染并且发送该模板文件到目标主机,使之替换原本的hosts
|
||
|
||
```
|
||
[root@ansible playbook]# vim hosts.yaml
|
||
- name: Config hosts file
|
||
hosts: all_servers
|
||
remote_user: root
|
||
|
||
|
||
tasks:
|
||
- name: copy hosts.j2 to group servers
|
||
template:
|
||
src: hosts.j2
|
||
dest: /etc/hosts
|
||
|
||
# 执行该playbook
|
||
[root@ansible playbook]# ansible-playbook hosts.yaml
|
||
```
|
||
|
||
1. 检查并验证:
|
||
|
||
```
|
||
[root@server1 ~]# cat /etc/hosts
|
||
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
|
||
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
|
||
|
||
|
||
192.168.88.10 server1
|
||
192.168.88.20 server2
|
||
192.168.88.30 server3
|
||
```
|
||
|
||
### 3.4.2 案例:生成nginx配置文件
|
||
|
||
我们可以在playbook中自定义变量,然后更具自定义的变量使用jinjia2模板渲染nginx的配置文件
|
||
|
||
1. 先编写nginx.yaml剧本,在里面定义变量
|
||
|
||
```
|
||
[root@ansible ~]# mkdir ansible
|
||
[root@ansible ~]# cd ansible
|
||
[root@ansible ansible]# vim nginx.yaml
|
||
- name: nginx conf
|
||
hosts: node1
|
||
remote_user: root
|
||
vars:
|
||
nginx_vhosts:
|
||
- web1:
|
||
listen: 8080
|
||
root: "/var/www/nginx/web1/"
|
||
- web2:
|
||
listen: 8080
|
||
server_name: "web2.baidu.com"
|
||
root: "/var/www/nginx/web2/"
|
||
- web3:
|
||
listen: 8080
|
||
server_name: "web3.baidu.com"
|
||
root: "/var/www/nginx/web3/"
|
||
tasks:
|
||
- name: mkdir /data
|
||
file:
|
||
name: /data
|
||
state: directory
|
||
- name: template config
|
||
template:
|
||
src: /root/ansible/site.conf.j2
|
||
dest: /data/nginx.conf
|
||
```
|
||
|
||
1. 编写nginx子配置文件site.conf,子配置文件中使用jinjia2语法进行渲染
|
||
|
||
```
|
||
[root@ansible ansible]# vim site.conf.j2
|
||
{% for vhost in nginx_vhosts %}
|
||
server {
|
||
listen {{ vhost.listen }}
|
||
{% if vhost.server_name is defined %}
|
||
server_name {{ vhost.server_name }}
|
||
{% endif %}
|
||
root {{ vhost.root }}
|
||
}
|
||
{% endfor %}
|
||
```
|
||
|
||
1. server1上验证配置文件是否渲染成功
|
||
|
||
```
|
||
[root@server1 ~]# cat /data/nginx.conf
|
||
server {
|
||
listen 8080
|
||
root /var/www/nginx/web1/
|
||
}
|
||
server {
|
||
listen 8080
|
||
server_name web2.baidu.com
|
||
root /var/www/nginx/web2/
|
||
}
|
||
server {
|
||
listen 8080
|
||
server_name web3.baidu.com
|
||
root /var/www/nginx/web3/
|
||
}
|
||
```
|
||
|
||
# 4. Role(角色)
|
||
|
||
Ansible 中的 Role 是一种组织和重用代码的强大方式。角色可以帮助你将相关的任务、变量、文件等集中管理,使得代码更加模块化和可重用。
|
||
|
||
如果将所有的play都写在一个playbook中,很容易导致这个playbook文件变得臃肿庞大,且不易读。因此,可以将多个不同任务分别写在不同的playbook中,然后使用include将其包含进去即可。而role则是整合playbook的方式。无论是include还是role,其目的都是分割大playbook以及复用某些细化的play甚至是task。
|
||
|
||
## 4.1 目录结构
|
||
|
||
在角色中,将task,templates,handlers,files等内容都分开存放,然后再playbook中直接调用角色即可.....
|
||
|
||
```
|
||
[root@ansible roles]# tree apache/
|
||
apache/
|
||
├── defaults
|
||
│ └── main.yml
|
||
├── files
|
||
├── handlers
|
||
│ └── main.yml
|
||
├── meta
|
||
│ └── main.yml
|
||
├── README.md
|
||
├── tasks
|
||
│ └── main.yml
|
||
├── templates
|
||
├── tests
|
||
│ ├── inventory
|
||
│ └── test.yml
|
||
└── vars
|
||
└── main.yml
|
||
```
|
||
|
||
- `defaults/main.yml`: 定义角色的默认变量
|
||
- `handlers/main.yml`: 定义角色的处理程序
|
||
- `meta/main.yml`: 定义角色的元数据,如依赖关系、作者信息等
|
||
- `tasks/main.yml`: 定义角色的主要任务
|
||
- `templates/`: 存放角色使用的模板文件
|
||
- `tests/`: 存放角色的测试相关文件
|
||
- `vars/main.yml`: 定义角色的变量
|
||
|
||
## 4.2 初始化自定义Role
|
||
|
||
可以使用ansible-galaxy工具通过init选项初始化一个角色
|
||
|
||
```
|
||
[root@ansible roles]# ansible-galaxy init apache
|
||
- Role apache was created successfully
|
||
[root@ansible role]# ls apache/
|
||
defaults files handlers meta README.md tasks templates tests vars
|
||
```
|
||
|
||
## 4.3 案例:使用Role安装httpd
|
||
|
||
1. 初始化httpd角色
|
||
|
||
```
|
||
[root@ansible roles]# ansible-galaxy init httpd
|
||
- Role httpd was created successfully
|
||
[root@ansible role]# tree httpd/
|
||
httpd/
|
||
├── defaults
|
||
│ └── main.yml
|
||
├── files
|
||
├── handlers
|
||
│ └── main.yml
|
||
├── meta
|
||
│ └── main.yml
|
||
├── README.md
|
||
├── tasks
|
||
│ └── main.yml
|
||
├── templates
|
||
├── tests
|
||
│ ├── inventory
|
||
│ └── test.yml
|
||
└── vars
|
||
└── main.yml
|
||
|
||
|
||
8 directories, 8 files
|
||
```
|
||
|
||
1. 编写角色中的task
|
||
|
||
```
|
||
[root@ansible httpd]# vim tasks/main.yml
|
||
# tasks file for httpd
|
||
- name: Install httpd
|
||
yum:
|
||
name: httpd
|
||
state: present
|
||
- name: copy site2.conf to apache web server
|
||
copy:
|
||
src: site.conf
|
||
dest: /etc/httpd/conf.d/site2.conf
|
||
|
||
|
||
- name: create directory1 for apache web server
|
||
file:
|
||
name: /data/site1/
|
||
state: directory
|
||
|
||
|
||
- name: create directory2 for apache web server
|
||
file:
|
||
name: /data/site2/
|
||
state: directory
|
||
|
||
|
||
- name: Start httpd
|
||
service:
|
||
name: httpd
|
||
state: started
|
||
- name: Write index file
|
||
shell: echo "site1" > /data/site1/index.html && echo "site2" > /data/site2/index.html
|
||
```
|
||
|
||
1. 编写角色中的file
|
||
|
||
```
|
||
[root@ansible httpd]# vim files/site.conf
|
||
Listen 8080
|
||
Listen 9090
|
||
|
||
|
||
<Directory "/data/">
|
||
Require all granted
|
||
</Directory>
|
||
|
||
|
||
<VirtualHost *:8080>
|
||
DocumentRoot "/data/site1/"
|
||
</VirtualHost>
|
||
|
||
|
||
<VirtualHost *:9090>
|
||
DocumentRoot "/data/site2/"
|
||
</VirtualHost>
|
||
```
|
||
|
||
1. 编写一个playbook剧本调用该角色
|
||
|
||
```
|
||
[root@ansible roles]# vim httpd.yaml
|
||
- name: Install httpd web server
|
||
hosts: node1
|
||
roles:
|
||
- httpd
|
||
```
|
||
|
||
1. 验证
|
||
|
||
```
|
||
[root@server1 ~]# ss -nlt
|
||
State Recv-Q Send-Q Local Address:Port Peer Address:Port
|
||
LISTEN 0 128 *:22 *:*
|
||
LISTEN 0 100 127.0.0.1:25 *:*
|
||
LISTEN 0 128 :::8080 :::*
|
||
LISTEN 0 128 :::80 :::*
|
||
LISTEN 0 128 :::22 :::*
|
||
LISTEN 0 100 ::1:25 :::*
|
||
LISTEN 0 128 :::9090 :::*
|
||
```
|
||
|
||

|
||
|
||
## 4.4 RHCE真题讲解(2023-10)
|
||
|
||
**题目(第六题):**
|
||
|
||
根据下列要求,在 /home/student/ansible/roles中创建名为 apache 的角色:
|
||
|
||
1. httpd软件包已安装,设为在系统启动时启用
|
||
2. 防火墙已启用并正在运行,并使用允许访问 Web 服务器的规则
|
||
3. 模板文件 index.html.j2 已存在,用于创建具有以下输出的文件 /var/www/html/index.html: Welcome to HOSTNAME on IPADDRESS 其中,HOSTNAME 是受管节点的完全限定域名,IPADDRESS 则是受管节点的 IP 地址。
|
||
4. 按照下方所述,创建一个使用此角色的 playbook /home/student/ansible/newrole.yml: 该 playbook 在 webservers 主机组中的主机上运行
|
||
|
||
```bash
|
||
[student@workstation ansible# cd roles/
|
||
[student@workstation roles]# ansible-galaxy init apache
|
||
[student@workstation roles]# vim apache/tasks/main.yml
|
||
---
|
||
# tasks file for apache
|
||
- name: install http
|
||
yum:
|
||
name: httpd
|
||
state: present
|
||
- name: config system service
|
||
service:
|
||
name: "{{ item }}"
|
||
state: started
|
||
enabled: yes
|
||
loop:
|
||
- httpd
|
||
- firewalld
|
||
- name: firewalld service
|
||
firewalld:
|
||
zone: public
|
||
service: http
|
||
permanent: yes
|
||
immediate: yes
|
||
state: enabled
|
||
- name: user templates
|
||
template:
|
||
src: index.html.j2
|
||
dest: /var/www/html/index.html
|
||
[student@workstation roles]# vim apache/templates/index.html.j2
|
||
Welcome to {{ ansible_fqdn }} on {{ ansible_default_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 serverc
|
||
Welcome to serverc.lab.example.com on 172.25.250.12
|
||
[student@workstation ansible]# curl serverd
|
||
Welcome to serverd.lab.example.com on 172.25.250.13
|
||
``` |