#### 一、Ansible补充模块
try () {
} catch () {
} finally
等同于
block () {
} rescue () {
} always
##### 任务块
- block任务块
- 通过block关键字,将多个任务组合到一起
- 将整个block任务组,一起控制是否要执行
```shell
# 判断webservers主机组内主机系统发行版为Rocky的主机,安装nginx并启动服务
- name: block tasks
hosts: webservers
tasks:
- name: group tasks
block:
- name: install nginx
yum:
name: nginx
state: present
- name: start nginx
service:
name: nginx
state: started
enabled: true
when: ansible_distribution == "Rocky" #条件作用与整组任务
```
- rescue和always
- 用于补充block任务
- block中的任务都执行成功则rescue中的任务不执行
- block中的任务出现失败则执行rescue中的任务
- always中的任务总会执行
```shell
# 测试block任务执行成功
- name: test block/rescue/always
hosts: webservers
tasks:
- name: test
block:
- name: touch file1
file:
path: /tmp/test1.txt
state: touch
rescue:
- name: touch file2
file:
path: /tmp/test2.txt
state: touch
always:
- name: touch file3
file:
path: /tmp/test3.txt
state: touch
```
##### loop循环
- 批量数值载入变量时使用loop循环,等同于for循环
- 特点是loop中的变量名固定为:item
```shell
## 变量定义方法
简单变量:单个元素赋值给item
loop: [a,b,c,d]
#或
loop:
- a
- b
- c
复杂变量:整体赋值给item,可以用item.key获取指定value
loop:
- {"key": "value", "key": "value"}
- name: create dir
hosts: webservers
tasks:
- name: create dir with loop
file:
path: /tmp/{{item}}
state: directory
loop:
- aa
- bb
- cc
- name: create users
hosts: webservers
tasks:
- name: create user with loop
user:
name: "{{item.iname}}"
password: "{{item.ipass|password_hash('sha512')}}"
state: present
loop:
- {"iname":"test01", "ipass":"123456"}
- {"iname":"test02", "ipass":"654321"}
```
#### 二、Ansible角色
> playbook局限在于大量文件无法管理的情况,编写后的大量Playbook文件以及调用文件,如此海量、无序的文件只有使用"角色"管理yml文件
- roles是ansible自1.2版本引入的新特性,用于层次性、结构化地组织playbook
- roles能够根据层次型结构自动装载变量文件、tasks以及handlers等
- 要使用roles只需要在playbook中使用include指令引入即可
- roles分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include
- roles一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中
<img src="19901269-0375cab5a41cada6.jpeg" style="zoom:50%;" />
```shell
roles: #角色必须放在roles目录下,可以自定义位置,默认/etc/ansible/roles/
project: #角色项目名称
files: #用于存放静态文件,如copy或script模块需要调用的文件
templates: #用于存放动态文件,即jinja2模板,template模块会自动到此目录下寻找模板文件
tasks: #定义任务列表的地方
main.yml #任务列表内容编写在此文件中
handlers: #定义触发器的地方
main.yml #触发器内容编写在此文件中
vars: #定义变量的地方(优先级高)
main.yml #变量定义在此文件中
defaults: #定义变量缺省值的地方(优先级低)
main.yml
meta: #定义作者、版本等描述信息、依赖关系等
main.yml
README.md #整个角色的描述信息
```
##### Roles使用方法
```shell
# 修改ansible.cfg配置文件
[defaults]
inventory = inventory
host_key_checking = false
module_name = shell
nocows = true
roles_path = ./roles
# 查看现有角色
ansible-galaxy list
# 创建角色
ansible-galaxy init roles/motd
## 配置角色三部曲
# 在templates目录下---创建模板文件
vim roles/motd/templates/motd.j2
Hostname: "{{ansible_hostname}}"
Date: "{{ansible_date_time.date}}"
Contact to: "{{admin}}"
# 在vars目录下---创建变量
vim roles/motd/vars/main.yml
---
# vars file for roles/motd
admin: "test@tedu.cn"
# 在tasks目录下---创建任务
vim roles/motd/tasks/main.yml
## 使用角色
vim role_motd.yml
- name: modify motd with role
hosts: webservers
roles:
- motd
ansible-playbook role_motd.yml
```
##### Roles练习
```shell
## 创建一个角色用于安装指定软件
# 创建角色
ansible-galaxy init roles/pkgs
## 配置角色三部曲
# 创建模板文件、创建变量文件、创建任务文件
vim roles/pkgs/tasks/main.yml
- name: install pkg
yum:
name: "{{pkg}}"
state: present
vim roles/pkgs/defaults/main.yml
pkg: nginx
```
#### 三、Ansible加密解密文件
#### ansible-vault命令
> 该命令用于实现数据加密/解密
```shell
## 常用选项
encrypt:加密
decrypt:解密
view:查看
rekey:重置密码
# 加密文件
ansible-vault encrypt hello.txt
# 解密文件
ansible-vault decrypt hello.txt
# 重置密码
ansible-vault rekey hello.txt
# 不解密文件查看内容
ansible-vault view hello.txt
# 使用密码文件
ansible-vault encrypt --vault-password-file=pass.txt data.txt #pass对data文件加密
ansible-vault decrypt --vault-password-file=pass.txt data.txt #pass对data文件解密
ansible-vault view --vault-password-file=pass.txt data.txt #不解密查看文件内容
# 加密剧本
ansible-vault encrypt user_test.yml
# 执行加密剧本
ansible-playbook --ask-vault-password user_test.yml
```
#### 四、sudo提权
##### sudo提权测试
sudo提权配置文件:/etc/sudoers
- 修改授权方法
- visudo(带语法检查,默认没有颜色提示)
- vim /etc/sudoers(不带语法检查,默认有颜色提示)
- 授权格式
```
用户名或组名(%groupname) 在集中认证域中有效,单机忽略 可以执行的命令列表
用户/组 ALL=(ALL) NOPASSWD: ALL
```
##### Ansible配置sudo提权
```shell
# 被控节点创建用户并配置sudo提权
- name: sudo user
hosts: all
tasks:
- name: create sudo user
user:
name: alice
password: "{{'123456'|password_hash('sha512')}}"
state: present
- name: config sudo
lineinfile:
path: /etc/sudoers
line: "alice ALL=(ALL) NOPASSWD: ALL"
state: present
# 修改ansible配置文件
[root@pubserver ansible]# vim ansible.cfg
[defaults]
...
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
```
#### 五、特殊的主机清单变量
> 如某个被控节点不能免密登录、ssh服务端口不是标准22端口等情况,则需要配置特殊的主机清单变量
```shell
## 常用配置
ansible_ssh_host:指定被控节点服务器IP地址
ansible_ssh_user:指定登陆远程主机的用户名
ansible_ssh_pass:指定登陆远程主机的密码
ansible_ssh_port:指定登陆远程主机的端口号
# 配置特殊的主机清单变量
vim inventory
[group]
web1
web2
db1 ansible_ssh_host=192.168.88.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass=a
```