ansible进阶与自动化
1. 集群批量管理
# 关闭掉麒麟系统中每次提示的: 自动发现的python问题.
ansible_python_interpreter: /usr/bin/python3
# 关闭麒麟或其他系统,对python3.7不支持的警告提示.
sed -i 's@#deprecation_warnings = True@deprecation_warnings =False@g' /etc/ansible/ansible.cfg
# facts变量如果不需要可以进行关闭,加速剧本的运行
修改ansible.cfg #gathering = implicit去掉注释,永久关闭,后期剧本中需要开启gather_facts: true
- hosts: web01
gather_facts: true
tasks:
- name: xxx
# 温馨提示: ubuntu默认禁用了root远程登录需要修改sshd配置文件开启,并记得配置Root密码. 操作流程与centos一致.
PermitRootLogin yes
1.1 流程控制
- ⭐ 循环:loop/with_items
- 判断: when
- ⭐ handler触发器
1.1.1 循环 ⭐️⭐️⭐️⭐️⭐️
应用场景:批量开启服务,重启服务,创建文件,目录,添加用户.
- with_* 系列: with_items
- loop
1.1.1.1 最常用的1种循环形式-1个变量
11_with_items_loop.yaml
[root@m01 /server/ans/playbook]# cat 11_with_items_loop.yaml
- hosts: backup
tasks:
- name: touch dir
file:
path: "{{ item }}"
state: directory
with_items:
- /opt/ans_test01
- /opt/ans_test02
- name: touch files
file:
path: "{{ item }}"
state: touch
loop:
- /opt/ans_test01/1.txt
- /opt/ans_test02/1.txt
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 11_with_items_loop.yaml
PLAY [backup] *************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.87]
TASK [touch dir] **********************************************************************************************************************************************************
ok: [172.16.1.87] => (item=/opt/ans_test01)
ok: [172.16.1.87] => (item=/opt/ans_test02)
TASK [touch files] ********************************************************************************************************************************************************
changed: [172.16.1.87] => (item=/opt/ans_test01/1.txt)
changed: [172.16.1.87] => (item=/opt/ans_test02/1.txt)
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.87 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible backup -i hosts -a 'tree -F /opt/'
172.16.1.87 | CHANGED | rc=0 >>
/opt//
├── ans_test01/
│ └── 1.txt
├── ans_test02/
│ └── 1.txt
└── facts.txt
2 directories, 3 files
[root@m01 /server/ans/playbook]#
- 类似于shell中的for循环.
- with_items或loop,变量名字item.
- 启动/重启服务,添加用户,文件,目录....
1.1.1.2 每次循环创建多个变量
12_add_user_for.yaml
[root@m01 /server/ans/playbook]# cat 12_add_user_for.yaml
- hosts: backup
tasks:
- name: add user
user:
name: "{{ item.name }}"
uid: "{{ item.uid }}"
state: present
loop:
- { name: "test01" , uid: "1801"}
- { name: "test02" , uid: "1802"}
- { name: "test03" , uid: "1803"}
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 12_add_user_for.yaml
PLAY [backup] *************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.87]
TASK [add user] ***********************************************************************************************************************************************************
ok: [172.16.1.87] => (item={'name': 'test01', 'uid': '1801'})
ok: [172.16.1.87] => (item={'name': 'test02', 'uid': '1802'})
ok: [172.16.1.87] => (item={'name': 'test03', 'uid': '1803'})
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.87 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible backup -i hosts -a 'grep -i test /etc/passwd'
[DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.9 (default, Jun 10 2022, 11:25:35) [GCC
7.3.0]. This feature will be removed from ansible-core in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
172.16.1.87 | CHANGED | rc=0 >>
test01:x:1801:1801::/home/test01:/bin/sh
test02:x:1802:1802::/home/test02:/bin/sh
test03:x:1803:1803::/home/test03:/bin/sh
[root@m01 /server/ans/playbook]#
1.1.1.3 小结
- with_items/loop循环
- 单个变量,item.
- 多个变量,
- 创建 item={'name': 'test01', 'uid': '1801'}
- 使用 item.user item.uid
循环链接:https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_loops.html
1.1.2 handlers触发器 ⭐️⭐️⭐️⭐️⭐️
- 需求:分发nfs服务配置文件,然后重启nfs.
- 实现步骤:
- copy/template分发
- systemd: restarted/reloaded
- 发现的问题:
- 按照之前所写的剧本,目前只能完成分发配置和重启服务,并且两个步骤之间没有关联.
- 我们希望只有配置发生了变化然后再去重启服务.
- 实现方案: handler与notify 触发器
- 应用场景:
- 一般用于分发配置文件的时候与重启服务.
- 如果配置文件发生变化则重启服务,如果没有变化则重启.
13_nfs_handlers.yaml
[root@m01 /server/ans/playbook]# cat 13_nfs_handlers.yaml
# nfs_server
- hosts: nfs01
tasks:
- name: 1.cfg_exports
copy:
src: ./exports
dest: /etc/exports
backup: yes
notify:
- 2.restart_nfs
- name : 3.result
shell: echo test handlers
handlers:
- name: 2.restart_nfs
systemd:
name: nfs
state: reloaded
[root@m01 /server/ans/playbook]#
#配置文件有变动(加了注释)
[root@m01 /server/ans/playbook]# vim exports
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# cat exports
# nfs_server_cfg
/nfsdata/ 172.16.1.0/24(rw,all_squash)
/data/ 172.16.1.0/24(rw,all_squash,anonuid=3999,anongid=3999)
/nfs01_ans/ 172.16.1.0/24(rw,all_squash,anonuid=4999,anongid=4999)
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 13_nfs_handlers.yaml
- 触发器小结:
- handlers触发器,应用场景:配置文件发生变化,然后重启服务(或做其他).
- 格式: 埋雷:设置绊雷(notify: 写个名字) , handlers设置名字和模块.
- 注意事项: handlers放在剧本的最后,否则都会被识别为handlers.
1.1.3 when判断
- when判断应用场景:用于给ans运行的task(模块)设置条件,满足或不满足条件在运行对应的模块.
- 应用建议: when进行判断,一般与变量一起使用.
- when条件一般与facts变量或register变量一起使用.
- when条件还可以和ansible语句一起使用(判断文件,判断目录,判断是否存在,比较大小).
- when: 给模块加上个条件
- failed_when:自定义执行失败,条件为真时后续操作不执行
When判断中使用的符号 |
说明 |
== |
等于 |
!= |
不等于 |
is match(''正则'') |
ansible_hostname is match("web|backup") 类似于egrep,正则. |
is not match |
ansible_hostname is not match("web|backup") 取反,排除 |
> |
大于 |
>= |
大于等于 |
< |
小于 |
<= | 小于等于 |
如果系统是centos或kylin则 安装sl,cowsay,如果是ubuntu 则安装cmatrix
09_check_os.yaml
[root@m01 /server/ans/playbook]# cat 09_check_os.yaml
- hosts: all
tasks:
- name: 输出系统发行版本
debug:
msg: "发行版本 {{ ansible_distribution }}"
- name: if Kylin|CentOS
yum:
name: cowsay
state: present
when: ansible_distribution is match ("Kylin|CentOS")
- name: if Ubuntu|Debian
apt:
name: cmatrix
state: present
when: ansible_distribution is match ("Ubuntu|Debian")
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 09_check_os.yaml
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
172.16.1.69 : ok=3 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
172.16.1.87 : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
failed-when
20_faild_when.yaml
[root@m01 /server/ans/playbook]# cat 20_faild_when.yaml
- hosts: web01
tasks:
- name: 1.check
shell: ping -c1 -W1 qq.com
register: ping
failed_when: ping.rc != 0
- name: 2. yum_install
yum:
name: tree
state: latest
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook 20_faild_when.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [1.check] ************************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [2. yum_install] *****************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
小结:
- when用于进行判断,满足/不满足条件就执行对应的模块(不满足条件的主机提示skip).
- when一般与变量一起使用.
- 符号 == != is match is not match
- (条件1) and (条件2)
- (条件1) or (条件2)
1.1.4 流程控制小结
项目 |
应用场景 |
⭐ ⭐ handler触发器 |
xxx配置变化,要做xxxx事情 |
when判断 |
给模块/剧本执行的时候加个条件. 判断系统版本,判断主机名. |
⭐ ⭐ ⭐ ⭐ 循环 |
loop,with_items 进行批量的操作,用户,目录,复制. |
1.2 剧本调试
- debug流程.
- 目标:通过注释,等等方法定位问题.
- 剧本单步执行
- tag标签
- 忽略错误
1.2.1 检查语法与单步执行
-C --check 模拟运行,不作出改变,一些变量可能会提示报错,因为-C没有真正运行剧本. register变量无法使用(目前使用pip安装的是OK的).
ansible-playbook -i hosts -C 10_register_ip.yaml
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C 10_register_ip.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [get ip] *************************************************************************************************************************************************************
skipping: [172.16.1.69]
TASK [use ip] *************************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "ip: {'changed': True, 'stdout': '', 'stderr': '', 'rc': 0, 'cmd': \"hostname -I | awk '{print $1}'\", 'start': None, 'end': None, 'delta': None, 'msg': 'Command would have run if not in check mode', 'skipped': True, 'stdout_lines': [], 'stderr_lines': [], 'failed': False}"
}
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=2 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
--syntax-check 只做语法检查,不运行.
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --syntax-check 10_register_ip.yaml
playbook: 10_register_ip.yaml
[root@m01 /server/ans/playbook]#
高级:--step 单步运行. y执行这个task,n忽略这个task,c自动运行
ansible-playbook -i hosts --step 10_register_ip.yaml
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --step 10_register_ip.yaml
PLAY [web01] **************************************************************************************************************************************************************
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: y
Perform task: TASK: Gathering Facts (N)o/(y)es/(c)ontinue: ****************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
Perform task: TASK: get ip (N)o/(y)es/(c)ontinue: c
Perform task: TASK: get ip (N)o/(y)es/(c)ontinue: *************************************************************************************************************************
TASK [get ip] *************************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [use ip] *************************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "ip: {'changed': True, 'stdout': '10.0.0.69', 'stderr': '', 'rc': 0, 'cmd': \"hostname -I | awk '{print $1}'\", 'start': '2024-10-21 16:18:42.942040', 'end': '2024-10-21 16:18:42.949379', 'delta': '0:00:00.007339', 'msg': '', 'stdout_lines': ['10.0.0.69'], 'stderr_lines': [], 'failed': False}"
}
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
1.2.2 从指定任务开始运行 ⭐️⭐️⭐️⭐️⭐️
--start-at-task 从指定任务运行一致运行到剧本结束.
--list-tasks&&--start-at-task
# 一般先用--list-tasks查看剧本中tasks名字
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --list-tasks 04_nfs_server_client.yaml
playbook: 04_nfs_server_client.yaml
play #1 (nfs01): nfs01 TAGS: []
tasks:
1.安装 nfs TAGS: []
2.配置 /etc/exports TAGS: []
3.添加用户组 add group www-ans 4999 TAGS: []
4.添加用户 add user www-ans TAGS: []
5.创建并更改目录属组/主 chown dir /nfs01_ans TAGS: []
6.启动rpc TAGS: []
7.启动 nfs TAGS: []
play #2 (web01): web01 TAGS: []
tasks:
1.安装nfs TAGS: []
2.添加用户组 add group 4999 TAGS: []
3.添加用户 add user TAGS: []
4.创建目录 dir /data_ans TAGS: []
5.挂载 mount TAGS: []
# 然后--start-at-task "任务名字" 从指定任务开始运行.
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --start-at-task "5.创建并更改目录属组/主 chown dir /nfs01_ans" 04_nfs_server_client.yaml
PLAY [nfs01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [5.创建并更改目录属组/主 chown dir /nfs01_ans] ***********************************************************************************************************************
ok: [172.16.1.68]
TASK [6.启动rpc] **********************************************************************************************************************************************************
changed: [172.16.1.68]
TASK [7.启动 nfs] *********************************************************************************************************************************************************
changed: [172.16.1.68]
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [1.安装nfs] **********************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [2.添加用户组 add group 4999] ***************************************************************************************************************************************
ok: [172.16.1.69]
TASK [3.添加用户 add user] ************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [4.创建目录 dir /data_ans] *******************************************************************************************************************************************
ok: [172.16.1.69]
TASK [5.挂载 mount] *******************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
1.2.3 tag标签⭐️⭐️⭐️⭐️⭐️
tag标签类似于超市物品的分类,只不过tag标签是给ansible中的task进行分类.加上标记.
运行剧本的时候运行指定的tag标签或排除某些tag
运行剧本的时候
--list-tasks # 查看任务名字和标签名
-t --tags # 运行的标签,如果多个标签通过","分割
--skip-tags # 排除指定的tags,如果多个标签通过","分割
14_nfs_server_client_tags.yaml
[root@m01 /server/ans/playbook]# cat 14_nfs_server_client_tags.yaml
# 1.nfs server
- hosts: nfs01
tasks:
- name: 1.安装 nfs
yum:
name: rpcbind, nfs-utils
state: installed
tags:
- nfs_server_install
- nfs_server_cfg
- name: 2.配置 /etc/exports
copy:
src: exports
dest: /etc/exports
backup: yes
tags:
- nfs_server_cfg
- name: 3.添加用户组 add group www-ans 4999
group:
name: www-ans
gid: 4999
state: present
- name: 4.添加用户 add user www-ans
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 5.创建并更改目录属组/主 chown dir /nfs01_ans
file:
path: /nfs01_ans
state: directory
owner: www-ans
group: www-ans
- name: 6.启动rpc nfs
systemd:
name: "{{ item }}"
state: restarted
loop:
- rpcbind
- nfs
tags:
- nfs_rpc_nfs_restart
# 2.nfs client
- hosts: web01
tasks:
- name: 1.安装nfs
yum:
name: rpcbind, nfs-utils
state: installed
- name: 2.添加用户组 add group 4999
group:
name: www-ans
gid: 4999
state: present
- name: 3.添加用户 add user
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 4.创建目录 dir /data_ans
file:
path: /data_ans
state: directory
- name: 5.挂载 mount
mount:
src: 172.16.1.68:/nfs01_ans
path: /data_ans
fstype: nfs
state: mounted
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --list-tasks 14_nfs_server_client_tags.yaml
playbook: 14_nfs_server_client_tags.yaml
play #1 (nfs01): nfs01 TAGS: []
tasks:
1.安装 nfs TAGS: [nfs_server_cfg, nfs_server_install]
2.配置 /etc/exports TAGS: [nfs_server_cfg]
3.添加用户组 add group www-ans 4999 TAGS: []
4.添加用户 add user www-ans TAGS: []
5.创建并更改目录属组/主 chown dir /nfs01_ans TAGS: []
6.启动rpc nfs TAGS: [nfs_rpc_nfs_restart]
play #2 (web01): web01 TAGS: []
tasks:
1.安装nfs TAGS: []
2.添加用户组 add group 4999 TAGS: []
3.添加用户 add user TAGS: []
4.创建目录 dir /data_ans TAGS: []
5.挂载 mount TAGS: []
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --tags "nfs_server_cfg,fs_server_install,nfs_rpc_nfs_restart" 14_nfs_server_client_tags.yaml
PLAY [nfs01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [1.安装 nfs] *********************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [2.配置 /etc/exports] ************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [6.启动rpc nfs] ******************************************************************************************************************************************************
changed: [172.16.1.68] => (item=rpcbind)
changed: [172.16.1.68] => (item=nfs)
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --skip-tags "nfs_server_cfg,fs_server_install,nfs_rpc_nfs_restart" 14_nfs_server_client_tags.yaml
PLAY [nfs01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [3.添加用户组 add group www-ans 4999] ********************************************************************************************************************************
ok: [172.16.1.68]
TASK [4.添加用户 add user www-ans] ****************************************************************************************************************************************
ok: [172.16.1.68]
TASK [5.创建并更改目录属组/主 chown dir /nfs01_ans] ***********************************************************************************************************************
ok: [172.16.1.68]
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [1.安装nfs] **********************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [2.添加用户组 add group 4999] ***************************************************************************************************************************************
ok: [172.16.1.69]
TASK [3.添加用户 add user] ************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [4.创建目录 dir /data_ans] *******************************************************************************************************************************************
ok: [172.16.1.69]
TASK [5.挂载 mount] *******************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
1.2.4 忽略错误
- 运行剧本的时候,因为重复运行导致的错误提示,并非是真的错误.
- 比如:目录已经存在,用户已经存在.
- 在这种情况下,我们可以通过ignore_errors: true 忽略错误,让剧本可以继续运行
16_ignore_errors.yaml
[root@m01 /server/ans/playbook]# cat 16_ignore_errors.yaml
- hosts: web01
tasks:
- name: touch directory
file:
path: /server/files
state: directory
ignore_errors: true
- name: print messages
debug:
msg: "即使上个任务(创建目录失败),这个任务依然执行 "
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 16_ignore_errors.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [touch directory] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [print messages] *****************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "即使上个任务(创建目录失败),这个任务依然执行 "
}
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
1.2.5 剧本调试小结
- ansible剧本书写建议:使用变量,给每个任务加上tag标签.
- 常见: 一般有密钥认证问题.
- 常见问题:剧本本身
- -vvv
- 检查语法-C --syntax-check
- tags标签
- --start-at-task
- 单行执行:--step
- 忽略错误 ignore_errors: true
1.3 Jinja2模版
- template模块与xxx.j2文件
- 应用场景:
- 进行分发配置文件或文件的时候,需要在文件中使用变量,需要使用jinja2,文件 nginx.conf.j2,需要使用template模块进行分发.
- 进行判断
- 进行循环
1.3.1 基本使用 ⭐️⭐️⭐️⭐️⭐️
分发文件,文件中包含ans变量(目标文件是/opt/template_facts.txt)
15_facts_template.yaml
[root@m01 /server/ans/playbook]# cat 15_facts_template.yaml
- hosts: web01
gather_facts: true
tasks:
- name: 调试变量
debug:
msg: |
"主机名:{{ ansible_hostname }}"
"内存大小:{{ ansible_memtotal_mb }}"
"cpu核数:{{ ansible_processor_vcpus }}"
- name: 分发模版文件
template:
src: ./template_facts.txt.j2
dest: /opt/template_facts.txt
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 15_facts_template.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [调试变量] ***********************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "\"主机名:web01\"\n\"内存大小:1956\"\n\"cpu核数:2\"\n"
}
TASK [分发模版文件] *******************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]# ansible web01 -i hosts -a "cat /opt/template_facts.txt"
172.16.1.69 | CHANGED | rc=0 >>
主机名:web01
内存大小:1956
cpu核数:2
系统: Kylin Linux Advanced Server
系统版本:V10
1.3.2 判断使用
- 应用场景:
- 未来某一个服务,主备,在主备2个节点上,配置文件几乎是一模一样的.(主:master, 备:backup)
- 根据主机名或ip或其他条件,生成不同的配置文件
# 目前有个配置文件叫keepalived.conf,文件中的内容根据lb01或lb02有所区别.
# 如果是lb01则配置文件内容是
keepalived-master.conf
state MASTER
# 如果是lb02则配置文件内容是
keepalived-backup.conf
state BACKUP
实现流程
详情
# jinja2模版
[root@m01 /server/ans/playbook]# cat /server/ans/templates/keepalived.conf.j2
# this is keepalived.conf
{% if ansible_hostname == "lb01" %}
state 主节点
{% elif ansible_hostname == "lb02" %}
state 备节点
{% endif %}
其他配置都是相同的,这里先不写
# 分发配置文件剧本
[root@m01 /server/ans/playbook]# cat 17_jinja2_if.yaml
- hosts: lb
tasks:
- name: 分发配置文件
template:
src: /server/ans/templates/keepalived.conf.j2
dest: /tmp/keepalived.conf
[root@m01 /server/ans/playbook]#
# 主机清单
[root@m01 /server/ans/playbook]# cat hosts
[backup]
#172.16.1.67
172.16.1.87
[nfs01]
172.16.1.68
[web01]
172.16.1.69 ansible_user=root ansible_password=Liuxiaoke123 ansible_port=22
#172.16.1.70
[lb]
172.16.1.75
172.16.1.76
[data:children]
nfs01
backup
# 执行剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 17_jinja2_if.yaml
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.76]
ok: [172.16.1.75]
TASK [分发配置文件] *******************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 查看结果
[root@m01 /server/ans/playbook]# ansible lb -i hosts -a "cat /tmp/keepalived.conf"
172.16.1.75 | CHANGED | rc=0 >>
# this is keepalived.conf
state 主节点
其他配置都是相同的,这里先不写
172.16.1.76 | CHANGED | rc=0 >>
# this is keepalived.conf
state 备节点
其他配置都是相同的,这里先不写
[root@m01 /server/ans/playbook]#
1.3.3 循环
语法
{% for ip in [1,2,3,4,5,6] %}
10.0.0.{{ ip }}
{% endfor %}
#range(2,11) 生成数字序列 2表示从2开始,到10结束
#顾头不顾腚
{% for ip in range(2,11) %}
10.0.0.{{ ip }}
{%endfor%}
{% for ip in ["lidao","oldwang"] %}
10.0.0.{{ ip }}
{%endfor%}
在上个实例(判断)的基本上加上循环,给主备节点加上主机名
详情
# jinja2模版
[root@m01 /server/ans/playbook]# cat /server/ans/templates/server.conf.j2
# this is server.conf
{% if ansible_hostname == "lb01" %}
state 主节点
{% for ip in range(2,5) %}
10.0.0.{{ ip }}
{%endfor%}
{% elif ansible_hostname == "lb02" %}
state 备节点
{% for ip in [6,7,8] %}
10.0.0.{{ ip }}
{%endfor%}
{% endif %}
# 分发剧本
[root@m01 /server/ans/playbook]# cat 18_jinja2_if_for.yaml
- hosts: lb
tasks:
- name: 分发配置文件
template:
src: /server/ans/templates/server.conf.j2
dest: /tmp/server.conf
[root@m01 /server/ans/playbook]#
# 检测剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C 18_jinja2_if_for.yaml
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.76]
ok: [172.16.1.75]
TASK [分发配置文件] *******************************************************************************************************************************************************
changed: [172.16.1.76]
changed: [172.16.1.75]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 执行剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 18_jinja2_if_for.yaml
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.76]
ok: [172.16.1.75]
TASK [分发配置文件] *******************************************************************************************************************************************************
changed: [172.16.1.76]
changed: [172.16.1.75]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 检查结果
[root@m01 /server/ans/playbook]# ansible lb -i hosts -a "cat /tmp/server.conf"
172.16.1.75 | CHANGED | rc=0 >>
# this is server.conf
state 主节点
10.0.0.2
10.0.0.3
10.0.0.4
172.16.1.76 | CHANGED | rc=0 >>
# this is server.conf
state 备节点
10.0.0.6
10.0.0.7
10.0.0.8
[root@m01 /server/ans/playbook]#
1.3.4 小结
- 核心:使用.j2结尾+template分发带有变量的文件即可.
- 研究jinja2的判断与循环
2. Ansible-进阶
2.1 Vault ⭐️
- 加密指定的文件: ansible-vault用于加密敏感信息
- 剧本
- 主机清单,
- 变量文件
- 文件
2.1.1 语法
#1.进行加密
ansible-vault encrypt 文件 #enable
#进行使用
ansible或ansible-playbook --ask-vault-pass 即可
--ask-vault-pass 交互
--vault-password-file 密码文件
#彻底解密
ansible-vault decrypt hosts#
2.1.2 主机清单加密
详情
# 加密主机清单
[root@m01 /server/ans/playbook]# ansible-vault encrypt hosts
New Vault password:
Confirm New Vault password:
Encryption successful
[root@m01 /server/ans/playbook]#
# 查看加密后的内容
[root@m01 /server/ans/playbook]# cat hosts
$ANSIBLE_VAULT;1.1;AES256
61643763353339333963383064316439656432376530626333333039663130623136323738653861
3731363336653062383464336631383361326164366138300a376461636531343037626239393162
36343964356136643163626363613331383361323463343338643661363166363732346561623033
3934316634366533640a656263663965393966653264343138643361666362343263333432373932
39643439396637636262626366623533646163656234663236376337656638323764633266616463
39356631396366333366366463383131373861636666373334346662393535623032336561663765
64366532316662323239386235373638306664376632333265656635313235626230393030636232
36326463303561333934353466376333366635346332326231366230623634356432366166376435
37656663366638333534636637383662623733363563613839386265326634623330313266653762
32323932363961383839333463326637366333616163353838363163366364356537613534326534
66316534616666336534663932633435613565656632313730346434373237633032613464363235
32326531623962643539386230343465636431323437373639616534313635366264306239356531
38616439386135643837613966356234633430393831383065626663313231323463333763643965
39353066643834623738643765626337396362313737666538613138366564623039313437653033
326365643564636662383262396330313532
# 查看剧本内容
[root@m01 /server/ans/playbook]# cat 01_test.yaml
---
- hosts: lb
tasks:
- name: 01 走到门前
shell: echo 01 >>/tmp/house.log
- name: 02 小心将鲜花放到门口
shell: echo 02 >>/tmp/house.log
- name: 03 默默祈祷
shell: echo 03 >>/tmp/house.log
- name: 04 扭头就跑
shell: echo 04 >>/tmp/house.log
# 执行剧本报错
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 01_test.yaml
[WARNING]: * Failed to parse /server/ans/playbook/hosts with yaml plugin: Attempting to decrypt but no vault secrets found
[WARNING]: * Failed to parse /server/ans/playbook/hosts with ini plugin: Attempting to decrypt but no vault secrets found
[WARNING]: Unable to parse /server/ans/playbook/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [all] ****************************************************************************************************************************************************************
skipping: no hosts matched
PLAY RECAP ****************************************************************************************************************************************************************
# 使用交互式密码执行剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --ask-vault-pass 01_test.yaml
Vault password:
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.76]
ok: [172.16.1.75]
TASK [01 走到门前] ********************************************************************************************************************************************************
changed: [172.16.1.76]
changed: [172.16.1.75]
TASK [02 小心将鲜花放到门口] **********************************************************************************************************************************************
changed: [172.16.1.76]
changed: [172.16.1.75]
TASK [03 默默祈祷] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [04 扭头就跑] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 创建vault密码文件
[root@m01 /server/ans/playbook]# vim vault.password
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# cat vault.password
1
[root@m01 /server/ans/playbook]#
# 使用密码文件执行剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts --vault-password-file vault.password 01_test.yaml
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.76]
ok: [172.16.1.75]
TASK [01 走到门前] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [02 小心将鲜花放到门口] **********************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [03 默默祈祷] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [04 扭头就跑] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.1.3 主机清单解密
解密主机清单
# 解密主机清单
[root@m01 /server/ans/playbook]# ansible-vault decrypt hosts
Vault password:
Decryption successful
# 查看主机清单内容
[root@m01 /server/ans/playbook]# cat hosts
[backup]
#172.16.1.67
172.16.1.87
[nfs01]
172.16.1.68
[web01]
172.16.1.69 ansible_user=root ansible_password=Liuxiaoke123 ansible_port=22
#172.16.1.70
[lb]
172.16.1.75
172.16.1.76
[data:children]
nfs01
backup
[root@m01 /server/ans/playbook]#
2.2 Roles ⭐️⭐️⭐️⭐️⭐️
2.2.1 roles详解
- 没有使用roles的问题:
- 增加剧本可读性,规范性.
- 剧本需要的文件,我们目前随处存放.
- 随着我们书写的剧本越来越复杂,我们发现,剧本使用到的文件,配置文件,j2文件...都放在与剧本同一层目录下.不方便后期维护.
- 剧本使用到的变量文件(group_vars/all/vars.yml),普通文件(copy),模板配置文件(template),handlers(触发器.)
- Roles本质让我们书写剧本的时候有个目录规范.
- 把我们完整的剧本拆分若干部分,有的专门存放tasks部分(剧本),存放变量,
- 存放普通文件,存储变量文件,handlers内容.
roles使用架构图
2.2.2 创建roles环境
创建目录
[root@m01 ~]# cd /server/ans/
[root@m01 /server/ans]# mkdir -p roles/{nfs_server,nfs_client}/{files,tasks,templates,handlers}
[root@m01 /server/ans]# mkdir -p roles/group_vars/all/
[root@m01 /server/ans]# tree -F roles/
roles/
├── group_vars/
│ └── all/
├── nfs-client/
│ ├── files/
│ ├── handlers/
│ ├── tasks/
│ └── templates/
└── nfs-server/
├── files/
├── handlers/
├── tasks/ #<--从这里开始书写.
└── templates/
2.2.3 准备nfs-server的roles(无变量版)
2.2.3.1 nfs-server剧本文件
nfs_server
# 1.nfs server
- hosts: nfs01
tasks:
- name: 1.安装 nfs
yum:
name: rpcbind, nfs-utils
state: installed
- name: 2.配置 /etc/exports
copy:
src: exports
dest: /etc/exports
backup: yes
notify:
- 7.启动 nfs
- name: 3.添加用户组 add group www-ans 4999
group:
name: www-ans
gid: 4999
state: present
- name: 4.添加用户 add user www-ans
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 5.创建并更改目录属组/主 chown dir /nfs01_ans
file:
path: /nfs01_ans
state: directory
owner: www-ans
group: www-ans
handlers:
- name: 6.启动rpc
systemd:
name: rpcbind
state: restarted
- name: 7.启动 nfs
systemd:
name: nfs
state: reloaded
2.2.3.2 tasks/main.yaml
nfs_server/tasks/main.yaml
[root@m01 /server/ans/roles]# cat nfs_server/tasks/main.yaml
- name: 1.安装 nfs
yum:
name: rpcbind, nfs-utils
state: installed
- name: 2.配置 /etc/exports
copy:
src: exports
dest: /etc/exports
backup: yes
notify:
- 6.启动rpc
- 7.启动 nfs
- name: 3.添加用户组 add group www-ans 4999
group:
name: www-ans
gid: 4999
state: present
- name: 4.添加用户 add user www-ans
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 5.创建并更改目录属组/主 chown dir /nfs01_ans
file:
path: /nfs01_ans
state: directory
owner: www-ans
group: www-ans
2.2.3.3 template/files下的main.yaml文件
nfs_server/files/exports
[root@m01 /server/ans/roles]# cat nfs_server/files/exports
# nfs_server_cfg
/nfsdata/ 172.16.1.0/24(rw,all_squash)
/data/ 172.16.1.0/24(rw,all_squash,anonuid=3999,anongid=3999)
/nfs01_ans/ 172.16.1.0/24(rw,all_squash,anonuid=4999,anongid=4999)
2.2.3.4 handlers文件
nfs_server/handlers/main.yaml
[root@m01 /server/ans/roles]# cat nfs_server/handlers/main.yaml
- name: 6.启动rpc
systemd:
name: rpcbind
state: restarted
- name: 7.启动 nfs
systemd:
name: nfs
state: reloaded
[root@m01 /server/ans/roles]#
2.2.3.5 变量文件
2.2.3.6 hosts文件
使用之前的即可
hosts
[root@m01 /server/ans/roles]# cat hosts
[backup]
172.16.1.67
#172.16.1.87
[nfs01]
172.16.1.68
[web01]
172.16.1.69
[lb]
172.16.1.75
172.16.1.76
[data:children]
nfs01
backup
[root@m01 /server/ans/roles]#
2.2.3.7 运行与调试 top.yaml
书写入口文件,top.yaml,文件名可以改变.
top.yaml
[root@m01 /server/ans/roles]# cat top.yaml
# 部署nfs_server
- hosts: nfs01
roles:
- role: nfs_server
[root@m01 /server/ans/roles]# ansible-playbook -C top.yaml
[root@m01 /server/ans/roles]# ansible-playbook top.yaml
PLAY [nfs01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [nfs_server : 1.安装 nfs] ********************************************************************************************************************************************
ok: [172.16.1.68]
TASK [nfs_server : 2.配置 /etc/exports] ***********************************************************************************************************************************
changed: [172.16.1.68]
TASK [nfs_server : 3.添加用户组 add group www-ans 4999] *******************************************************************************************************************
ok: [172.16.1.68]
TASK [nfs_server : 4.添加用户 add user www-ans] ***************************************************************************************************************************
ok: [172.16.1.68]
TASK [nfs_server : 5.创建并更改目录属组/主 chown dir /nfs01_ans] **********************************************************************************************************
ok: [172.16.1.68]
RUNNING HANDLER [nfs_server : 6.启动rpc] **********************************************************************************************************************************
changed: [172.16.1.68]
RUNNING HANDLER [nfs_server : 7.启动 nfs] *********************************************************************************************************************************
changed: [172.16.1.68]
172.16.1.68 : ok=8 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.2.4 准备nfs-client的roles(无变量版)
流程与nfs-server一致,更加简单一些.
2.2.4.1 nfs客户端剧本
nfs_client
# 2.nfs client
- hosts: web01
tasks:
- name: 1.安装nfs
yum:
name: rpcbind, nfs-utils
state: installed
- name: 2.添加用户组 add group 4999
group:
name: www-ans
gid: 4999
state: present
- name: 3.添加用户 add user
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 4.创建目录 dir /data_ans
file:
path: /data_ans
state: directory
- name: 5.挂载 mount
mount:
src: 172.16.1.68:/nfs01_ans
path: /data_ans
fstype: nfs
state: mounted
2.2.4.2 tasks文件
nfs_client/tasks/main.yaml
[root@m01 /server/ans/roles]# cat nfs_client/tasks/main.yaml
- name: 1.安装nfs
yum:
name: rpcbind, nfs-utils
state: installed
- name: 2.添加用户组 add group 4999
group:
name: www-ans
gid: 4999
state: present
- name: 3.添加用户 add user
user:
name: www-ans
uid: 4999
group: www-ans
shell: /sbin/nologin
create_home: no
state: present
- name: 4.创建目录 dir /data_ans
file:
path: /data_ans
state: directory
- name: 5.挂载 mount
mount:
src: 172.16.1.68:/nfs01_ans
path: /data_ans
fstype: nfs
state: mounted
2.2.4.3 变量文件
2.2.4.4 运行与调试:修改top.yml
top
[root@m01 /server/ans/roles]# cat top.yaml
# 部署nfs_server
#- hosts: nfs01
# roles:
# - role: nfs_server
# 部署nfs_client
- hosts: web01
roles:
- role: nfs_client
[root@m01 /server/ans/roles]# ansible-playbook -C top.yaml
[root@m01 /server/ans/roles]# ansible-playbook top.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [nfs_client : 1.安装nfs] *********************************************************************************************************************************************
ok: [172.16.1.69]
TASK [nfs_client : 2.添加用户组 add group 4999] **************************************************************************************************************************
ok: [172.16.1.69]
TASK [nfs_client : 3.添加用户 add user] ***********************************************************************************************************************************
ok: [172.16.1.69]
TASK [nfs_client : 4.创建目录 dir /data_ans] ******************************************************************************************************************************
ok: [172.16.1.69]
TASK [nfs_client : 5.挂载 mount] ******************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=6 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
2.2.5 联调测试
top.yaml
[root@m01 /server/ans/roles]# cat top.yaml
# 部署nfs_server
- hosts: nfs01
roles:
- role: nfs_server
# 部署nfs_client
- hosts: web01
roles:
- role: nfs_client
[root@m01 /server/ans/roles]# ansible-playbook -C top.yaml
[root@m01 /server/ans/roles]# ansible-playbook top.yaml
最终目录结构
tree -F
[root@m01 /server/ans/roles]# tree -F
.
├── hosts
├── nfs_client/
│ ├── files/
│ ├── handlers/
│ ├── tasks/
│ │ └── main.yaml
│ └── templates/
├── nfs_server/
│ ├── files/
│ │ └── exports
│ ├── handlers/
│ │ └── main.yaml
│ ├── tasks/
│ │ └── main.yaml
│ └── templates/
└── top.yaml
2.2.6 rsync(变量版)
2.2.6.1 rsync_server
tasks/main.yaml
server_playbook
- name: 1.安装rsync
yum:
name: rsync
state: present
when: ansible_distribution is match("Kylin|CentOS")
- name: 1.安装rsync
apt:
name: rsync
state: present
when: ansible_distribution is match("Debian|Ubuntu")
- name: 2.添加用户
user:
name: rsync
shell: /sbin/nologin
create_home: no
state: present
- name: 3.创建备份目录/nfs01backup且更改权限rsync
file:
path: /nfs01backup
state: directory
owner: rsync
group: rsync
- name: 4.修改配置文件/etc/rsyncd.conf
template:
src: ./rsyncd.conf.j2
dest: /etc/rsyncd.conf
backup: yes
notify:
- 7.rsync重启
- name: 5.创建密码文件,写入内容
ansible.builtin.lineinfile:
path: /etc/rsync.password
line: "rsync_backup:Xk123456"
state: present
- name: 6.修改权限600
file:
path: /etc/rsync.password
mode: "0600"
- name: 8.分发脚本
template:
src: ./ans_bak_file_server.sh.j2
dest: /server/scripts/ans_bak_file_server.sh
backup: yes
- name: 9.将脚本加入定时任务
cron:
name: bak_data
minute: "00"
hour: "00"
job: "/bin/bash /server/scripts/ans_bak_file_server.sh >/dev/null 2>&1"
state: present
handlers/main.yaml
埋雷
- name: 7.rsync重启
systemd:
name: rsyncd
state: restarted
when: ansible_distribution is match("Kylin|CentOS")
- name: 7.rsync重启
systemd:
name: rsync
state: restarted
when: ansible_distribution is match("Debian|Ubuntu")
group_vars/all/vars.yaml
变量文件
# rsyncd_conf_vars
auth_users: rsync_backup
secrets_file: /etc/rsync.password
module1: nfs01backup
module1_path: /nfs01backup
module2: nfs01backup2
module2_path: /nfs01backup2
template/rsyncd.conf.j2
jinja2 rsyncd服务端配置文件模版
# rsyncd_conf_start
fake super =yes
uid = rsync
gid = rsync
use chroot = no
max connections = 2000
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
#hosts allow = 10.0.0.0/24
#hosts deny = 0.0.0.0/32
auth users = {{ auth_users }}
secrets file = {{ secrets_file }}
#####################################
[data]
comment = www by xk 14:18 2024-1-13
path = /data
[{{ module1 }}]
comment = www by xk 14:18 2024-1-13
path = {{ module1_path }}
[{{ module2 }}]
comment = www by xk 14:18 2024-1-13
path = {{ module2_path }}
template/rans_bak_file_server.sh.j2
jinja2备份检验脚本模版
#!/bin/bash
##############################################################
# File Name:ans_bak_file_server.sh
# Version:V1.0
# Author:xk
# Organization:
# Desc:
##############################################################
#rsync_server
# vars
dir="{{ module1_path }}"
log_file=/var/log/bak.log
check_res(){
ret="$?"
params="$*"
if [ $ret -eq 0 ];then
echo "$params 执行成功" >> $log_file
else
echo "$params 执行失败" >> $log_file
fi
}
# 校验
find $dir -type f -name *.md5 | xargs md5sum -c > $dir/md5.txt
check_res md5sum --check
#备份检查脚本,清理旧的备份(超过180天,不包含每周一的备份),通过邮件方式发给领导
find $dir -type f -name *.tar.gz ! *_1.tar.gz -mtime +180 | rm -f
check_res rm bak
2.2.6.2 rsync_client
tasks/main.yaml
rsync客户端配置
- name: 1.创建备份目录 /nfs01backup
file:
path: /nfs01backup
state: directory
- name: 2.创建密码文件
lineinfile:
path: /etc/rsync.client
line: "Xk123456"
state: present
- name: 3.修改权限
file:
path: /etc/rsync.client
mode: "0600"
- name: 4.分发脚本
template:
src: ./ans_bak_file_client.sh.j2
dest: /server/scripts/ans_bak_file_client.sh
backup: yes
- name: 5.将脚本加入定时任务
cron:
name: ans_data
minute: "00"
hour: "00"
job: "/bin/bash /server/scripts/ans_bak_file_client.sh >/dev/null 2>&1"
state: present
templates/ans_bak_file_client.sh.j2
jinja2 创建备份文件模版
#!/bin/bash
##############################################################
# File Name:ans_bak_file_client.sh
# Version:V1.0
# Author:xk
# Organization:
# Desc:
##############################################################
# rsync_client
# vars
dir="{{ module1_path }}"
module=nfs01backup
ip=`hostname -I | awk '{print $1}'`
# dst_ip="$1"
dst_ip="172.16.1.67"
time=`date +%F_%w`
path=$dir/$ip
bak_file=$path/$time.tar.gz
log_file=/var/log/bak.log
#secret="/etc/rsync.client"
check_res(){
ret="$?"
params="$*"
if [ $ret -eq 0 ];then
echo "$params 执行成功" >> $log_file
else
echo "$params 执行失败" >> $log_file
fi
}
# 创建备份目录
mkdir $path
# tar
tar zcf $bak_file /etc/
check_res tar
# md5sum
md5sum $bak_file > $path/bak.md5
check_res md5sum
# rsync $dir后面加上/
rsync -av $dir/ rsync_backup@$dst_ip::$module --password-file=/etc/rsync.client
check_res rsync
# 清理7天之前的文件
find /backup -type f -name *.tar.gz -mtime +7 | xargs rm -f
check_res rm bak +7
2.2.6.3 hosts
hosts解析文件
[backup]
172.16.1.67
#172.16.1.87
[nfs01]
172.16.1.68
[web01]
172.16.1.69
#172.16.1.69 ansible_user=root ansible_password=Liuxiaoke123 ansible_port=22
#172.16.1.70
[lb]
172.16.1.75
172.16.1.76
[data:children]
nfs01
backup
2.2.6.4 top.yaml
剧本入口文件
# 部署rsync_server
- hosts: backup
gather_facts: true
roles:
- role: rsync_server
# 部署rsync_client
- hosts: nfs01
gather_facts: true
roles:
- role: rsync_client
2.2.6.5 目录结构
tree -F
[root@m01 /server/ans/roles]# tree -F
.
├── group_vars/
│ └── all/
│ └── vars.yaml
├── hosts
├── rsync_client/
│ ├── tasks/
│ │ └── main.yaml
│ └── templates/
│ └── ans_bak_file_client.sh.j2
├── rsync_server/
│ ├── handlers/
│ │ └── main.yaml
│ ├── tasks/
│ │ └── main.yaml
│ └── templates/
│ ├── ans_bak_file_server.sh.j2
│ └── rsyncd.conf.j2
└── top.yaml
2.2.6.6 测试与运行
[root@m01 /server/ans/roles]# ansible-playbook -C top.yaml
[root@m01 /server/ans/roles]# ansible-playbook top.yaml
# 注意:
定时任务执行时间是每天凌晨00:00,测试时可临时修改定时任务时间,完成后再改回来。
2.2.6.7 结果查看
check_result
# 定时任务
[root@m01 /server/ans/roles]# ansible nfs01 -i hosts -a "crontab -l"
172.16.1.68 | CHANGED | rc=0 >>
#Ansible: update date
*/5 * * * * /sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1
#Ansible: ans_data
00 00 * * * /bin/bash /server/scripts/ans_bak_file_client.sh >/dev/null 2>&1
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "crontab -l"
172.16.1.67 | CHANGED | rc=0 >>
#Ansible: update date
*/5 * * * * /sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1
#Ansible: bak_data
00 00 * * * /bin/bash /server/scripts/ans_bak_file_server.sh >/dev/null 2>&1
# 配置文件
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "cat /etc/rsyncd.conf"
172.16.1.67 | CHANGED | rc=0 >>
# rsyncd_conf_start
fake super =yes
uid = rsync
gid = rsync
use chroot = no
max connections = 2000
timeout = 600
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
ignore errors
read only = false
list = false
#hosts allow = 10.0.0.0/24
#hosts deny = 0.0.0.0/32
auth users = rsync_backup
secrets file = /etc/rsync.password
#####################################
[data]
comment = www by xk 14:18 2024-1-13
path = /data
[nfs01backup]
comment = www by xk 14:18 2024-1-13
path = /nfs01backup
[nfs01backup2]
comment = www by xk 14:18 2024-1-13
path = /nfs01backup2
[root@m01 /server/ans/roles]#
# 脚本文件
[root@m01 /server/ans/roles]# ansible nfs01 -i hosts -a "cat /server/scripts/ans_bak_file_client.sh"
172.16.1.68 | CHANGED | rc=0 >>
#!/bin/bash
##############################################################
# File Name:ans_bak_file_client.sh
# Version:V1.0
# Author:xk
# Organization:
# Desc:
##############################################################
# rsync_client
# vars
dir="/nfs01backup"
module=nfs01backup
ip=`hostname -I | awk '{print $1}'`
# dst_ip="$1"
dst_ip="172.16.1.67"
time=`date +%F_%w`
path=$dir/$ip
bak_file=$path/$time.tar.gz
log_file=/var/log/bak.log
#secret="/etc/rsync.client"
check_res(){
ret="$?"
params="$*"
if [ $ret -eq 0 ];then
echo "$params 执行成功" >> $log_file
else
echo "$params 执行失败" >> $log_file
fi
}
# 创建备份目录
mkdir $path
# tar
tar zcf $bak_file /etc/
check_res tar
# md5sum
md5sum $bak_file > $path/bak.md5
check_res md5sum
# rsync $dir后面加上/
rsync -av $dir/ rsync_backup@$dst_ip::$module --password-file=/etc/rsync.client
check_res rsync
# 清理7天之前的文件
find /backup -type f -name *.tar.gz -mtime +7 | xargs rm -f
check_res rm bak +7
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "cat /server/scripts/ans_bak_file_server.sh"
172.16.1.67 | CHANGED | rc=0 >>
#!/bin/bash
##############################################################
# File Name:ans_bak_file_server.sh
# Version:V1.0
# Author:xk
# Organization:
# Desc:
##############################################################
#rsync_server
# vars
dir="/nfs01backup"
log_file=/var/log/bak.log
check_res(){
ret="$?"
params="$*"
if [ $ret -eq 0 ];then
echo "$params 执行成功" >> $log_file
else
echo "$params 执行失败" >> $log_file
fi
}
# 校验
find $dir -type f -name *.md5 | xargs md5sum -c > $dir/md5.txt
check_res md5sum --check
#备份检查脚本,清理旧的备份(超过180天,不包含每周一的备份),通过邮件方式发给领导
find $dir -type f -name *.tar.gz ! *_1.tar.gz -mtime +180 | rm -f
check_res rm bak
# 备份结果
[root@m01 /server/ans/roles]# ansible nfs01 -i hosts -a "tree -F /nfs01backup"
172.16.1.68 | CHANGED | rc=0 >>
/nfs01backup
└── 10.0.0.68/
├── 2024-10-23_3.tar.gz
├── 2024-10-24_4.tar.gz
└── bak.md5
1 directory, 3 files
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "tree -F /nfs01backup"
172.16.1.67 | CHANGED | rc=0 >>
/nfs01backup
├── 10.0.0.68/
│ ├── 2024-10-23_3.tar.gz
│ ├── 2024-10-24_4.tar.gz
│ └── bak.md5
└──md5.txt
1 directory, 4 files
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "cat /nfs01backup/10.0.0.68/bak.md5"
172.16.1.67 | CHANGED | rc=0 >>
4f9bed94022968cd63c9432e3531c543 /nfs01backup/10.0.0.68/2024-10-24_4.tar.gz
[root@m01 /server/ans/roles]#
[root@m01 /server/ans/roles]# ansible backup -i hosts -a "cat /nfs01backup/md5.txt"
172.16.1.67 | CHANGED | rc=0 >>
/nfs01backup/10.0.0.68/2024-10-24_4.tar.gz: 成功
[root@m01 /server/ans/roles]#
2.2.7 lsync(变量版)
2.2.7 roles小结
书写剧本的时候通过roles方式实现.
roles详解
mkdir -p /server/roles/
cd /server/roles/
[root@m01 /server/roles]# tree -F
.
├── hosts
|---group_vars/all/vars.yml
└── nfs-server/
├── files/ #存储普通文件,压缩包,配置文件,copy.
├── handlers/
│ └── main.yml #剧本中handlers的部分.
├── tasks/
│ └── main.yml #存放剧本中tasks部分。
├── templates/ #.j2结尾的文件通过template模块调用.
2.3 include文件包含
- 目标: 放在配置文件过大(剧本过大.) 拆分成多个子剧本.
- 在我们书写剧本的时候,会涉及到多个步骤,还会涉及到服务端和客户端.
- 发现剧本越来越大,不容易进行分析与阅读.
- 把剧本拆分开,分成2个文件服务端,客户端.
- 这时候可以通过include_tasks的功能把多个剧本文件合并在一起,让剧本变成多个方便阅读与维护.
- include_tasks
- roles
tasks file for nfs-server
# tasks file for nfs-server
- name: 1. 安装nfs
yum:
name: nfs-utils,rpcbind
state: present
tags:
- install_nfs_server
- name: 2. 配置nfs/etc/exports
template:
src: exports.j2
dest: /etc/exports
notify:
- restart_nfs_server
tags:
- config_nfs_server
- nfs_server_config_file
- name: 3. 创建共享目录并修改所有者 /ans-data/
file:
path: /ans-data/
owner: nfsnobody
group: nfsnobody
state: directory
tags:
- config_nfs_server
- nfs_server_dir
- name: 4. 启动(重启)
systemd:
name: rpcbind
enabled: yes
state: started
- name: 5. 启动(重启)
systemd:
name: nfs
enabled: yes
state: started
nfs-server/tasks/main.yml
main.yml
[root@m01 /server/roles]# cat nfs-server/tasks/main.yml
- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: start.yml
nfs-server/tasks/install.yml
install.yml
[root@m01 /server/roles]# cat nfs-server/tasks/install.yml
- name: 1. 安装nfs
yum:name: nfs-utils,rpcbind
state: present
tags:
- install_nfs_server
nfs-server/tasks/config.yml
config.yml
[root@m01 /server/roles]# cat nfs-server/tasks/config.yml
- name: 2. 配置nfs/etc/exports
template:
src: exports.j2
dest: /etc/exports
notify:
- restart_nfs_server
tags:
- config_nfs_server
- nfs_server_config_file
- name: 3. 创建共享目录并修改所有者 /ans-data/
file:
path: /ans-data/
owner: nfsnobody
group: nfsnobody
state: directory
tags:
- config_nfs_server
- nfs_server_dir
nfs-server/tasks/start.yml
start.yml
[root@m01 /server/roles]# cat nfs-server/tasks/start.yml
- name: 4. 启动
systemd:
name: "{{ item }}"
enabled: yes
state: started
loop:
- rpcbind
- nfs
[root@m01 /server/roles]# cat top.yml
- hosts: backup
roles:
- role: nfs-server
#- hosts: web
# roles:
# - role: nfs-client
运行
[root@m01 /server/ans/roles]# ansible-playbook top.yaml
如何在1个剧本中使用include
nfs01
---
- hosts: nfs01
tasks:
- include_tasks: install.yml
- include_tasks: config.yml
- include_tasks: start.yml
include功能小结: 防止我们剧本过大,对剧本进行拆分.
2.4 Galaxy
其他人写的的roles
官网:https://galaxy.ansible.com/ui/
2.5 优化
2.5.1 hosts操作优化
执行剧本无需加上 -i 选项
# 配置文件里加上主机清单路径
[root@m01 /server/ans/playbook]# vim /etc/ansible/ansible.cfg
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# egrep -nv '^$|^#' /etc/ansible/ansible.cfg
10:[defaults]
12:interpreter_python=/usr/bin/python3
15:inventory = /server/ans/playbook/hosts
38:gathering = implicit
73:host_key_checking = False
182:deprecation_warnings = False
329:[inventory]
342:[privilege_escalation]
348:[paramiko_connection]
372:[ssh_connection]
433:[persistent_connection]
447:[accelerate]
462:[selinux]
471:[colors]
487:[diff]
# 全局配置文件里定义主机清单全局变量
[root@m01 /server/ans/playbook]# vim /etc/profile
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# tail -1 /etc/profile
export ANSIBLE_INVENTORY=./hosts
# 重新加载配置文件
[root@m01 /server/ans/playbook]# source /etc/profile
[root@m01 /server/ans/playbook]#
# 执行剧本无需加上 -i 选项
[root@m01 /server/ans/playbook]# ansible-playbook 01_test.yaml
PLAY [lb] *****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.75]
ok: [172.16.1.76]
TASK [01 走到门前] ********************************************************************************************************************************************************
changed: [172.16.1.76]
changed: [172.16.1.75]
TASK [02 小心将鲜花放到门口] **********************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [03 默默祈祷] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
TASK [04 扭头就跑] ********************************************************************************************************************************************************
changed: [172.16.1.75]
changed: [172.16.1.76]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.75 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.76 : ok=5 changed=4 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
2.5.2 ansible安全优化-sudo ⭐️⭐️⭐️⭐️⭐️
整体流程
禁用root远程登录,ansible使用普通用户(具有sudo权限)
配置ansible普通用户sudo权限流程 |
说明 |
被管理端:添加普通用户ans,设置密码 |
|
被管理端:配置sudo权限 |
修改/etc/sudoers 添加 ans ALL=(ALL) NOPASSWD: ALL |
被管理端:修改ssh配置文件禁止root远程登录 |
修改/etc/sshd/sshd_config #PermitRootLogin yes 修改为 PermitRootLogin no 最后再做 |
管理端-->被管理端分发密钥 |
ssh-copy-id 可以使用脚本 |
修改ansible管理端配置文件 |
/etc/ansible/ansible.cfg 修改配置文件使用sudo+普通用户 |
调试测试 |
需要Root权限的操作,安装软件 |
被管理端使用ansible实现,未来没有配置 ans,那就用脚本
19_useradd_sudo.yaml
[root@m01 /server/ans/playbook]# cat 19_useradd_sudo.yaml
- hosts: all
vars:
username: ans
password: "Xk123456"
gather_facts: false
tasks:
- name: 01.添加用户设置密码
user:
name: "{{ username }}"
shell: /bin/bash
password: "{{ password | password_hash('sha512','xk123') }}"
state: present
- name: 02.配置sudo权限
lineinfile:
path: /etc/sudoers
line: "{{ username }} ALL=(ALL) NOPASSWD: ALL"
#regexp: ^xk123
state: present
- name: 03.修改sshd_config配置文件
replace:
path: /etc/ssh/sshd_config
#目标 #PermitRootLogin yes
#目标 PermitRootLogin yes
#regexp: "^(#PermitRootLogin yes)|(PermitRootLoginyes)"
regexp: "^#?PermitRootLogin yes"
replace: "PermitRootLogin no"
notify:
- 04.重启sshd
handlers:
- name: 04.重启sshd
systemd:
name: sshd
state: reloaded
[root@m01 /server/ans/playbook]#
分发密钥(修改ansible配置文件后再执行)
ssh_rsa_dispense_ans.sh
[root@m01 /server/ans/playbook]# cat /server/scripts/ssh_rsa_dispense_ans.sh
#!/bin/bash
##############################################################
# File Name:/server/scripts/ssh_rsa_dispense_ans.sh
# Version:V1.0
# Author:xk
# Organization:
# Desc:
##############################################################
# 1.vars
key=/root/.ssh/id_rsa
ips="67 68 75 76"
# ips="67 68 69 70 71 72 75 76 81"
pass=Xk123456
user=ans
#ips="`cat /server/files/ip.txt`"
#2. 一键创建秘钥对
if [ ! -f $key ];then
ssh-keygen -f $key -P '' &>/dev/null
fi
if [ $? -eq 0 ];then
echo "秘钥对创建成功"
else
echo "密钥对创建失败"
exit 1
fi
#3. 一键分发公钥
echo "分发公钥-开始"
for ip in $ips
do
sshpass -p$pass ssh-copy-id -o StrictHostKeyChecking=no $user@10.0.0.$ip
#这里也可以通过$? + if判断公钥分发是否成功
done
echo "分发公钥-完成"
#4. 一键检查
echo "检查-开始"
for ip in $ips
do
ssh -o StrictHostKeyChecking=no $user@10.0.0.$ip
hostname -I
#这里也可以通过$? + if执行是否成功
done
echo "检查-结束"
[root@m01 /server/ans/playbook]#
修改ansible配置文件
[root@m01 /server/ans/playbook]# egrep -vn '^$|#' /etc/ansible/ansible.cfg |grep -v '\['
12:interpreter_python=/usr/bin/python3
15:inventory = /server/ans/playbook/hosts
24:sudo_user = ans
28:remote_port = 22
38:gathering = implicit
73:host_key_checking = False
109:remote_user = ans
113:log_path = /var/log/ansible.log
182:deprecation_warnings = False
343:become=True
344:become_method=sudo
345:become_user=root
[root@m01 /server/ans/playbook]#
配置文件详解
egrep -v '^$|#' /etc/ansible/ansible.cfg
[root@m01 /server/ans/playbook]# egrep -v '^$|#' /etc/ansible/ansible.cfg
[defaults]
interpreter_python=/usr/bin/python3 # 关闭掉麒麟系统中每次提示的: 自动发现的pyhont问题.
inventory = /server/ans/playbook/hosts
sudo_user = ans # 被管理端上具有sudo权限的用户 nopasswd: ALL
remote_port = 22 # 被管理端ssh端口号
gathering = implicit # 关闭facts
host_key_checking = False
remote_user = ans # 被管理端使用的用户,不指定默认是当前用户/root
log_path = /var/log/ansible.log
deprecation_warnings = False # 关闭麒麟或其他系统,对python3.7不支持的警告提示.
[inventory]
[privilege_escalation]
become=True # 开启sudo功能
become_method=sudo # 使用sudo命令
become_user=root # 普通用户切换为root
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
调试
ansible all -i hosts -m ping
[root@m01 /server/ans/playbook]# ansible all -i hosts -m ping
172.16.1.67 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.1.68 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.1.75 | SUCCESS => {
"changed": false,
"ping": "pong"
}
172.16.1.76 | SUCCESS => {
"changed": false,
"ping": "pong"
}
2.5.3 其他优化
性能
- ssh连接速度优化,关闭UseDNS,GSSAPIAuthcation ....
- 不要让ansible运行交互式的命令,非要用使用命令的非交互模式.
- 需要使用ans,yum安装软件,可以自建本地yum仓库,然后ans安装.(自建yum源,自己制作的rpm包)
- 调整ansible并发数量( -f 调整并发数量 默认是5 ansible.cfg forks=5 ,实际调整根据负载情况.)
- 给ansible配置缓存(redis),队列.缓存facts给主机进行分组操作与管理.
- 关闭gather_facts,如果不用facts变量可以关闭, 剧本中: gather_facts:false 配置文件:` gathering = explicit`
- 关闭host,key,check 一般使用密码认证的时候需要关闭,如果不关闭`ansible配置文件 host_key_checking = False`
安全⭐
- ⭐ 配置sudo用户 ans ALL=(ALL) NOPASSWD: ALL 密码是1,ssh端口是22
- 配合vpn,jms一起使用
- 用户--->vpn---->jms(跳板机)---->ansible
- 用户的密码,进行加密( hash, ansible-vault)
配置sudo
- 所有被管理节点上添加ans用户 ,设置密码.
- 所有备管理节点上配置ans sudo权限 ans ALL=(ALL) NOPASSWD: ALL
- 管理端与被管理端密钥认证:分发密钥发到ans用户.
- 管理端: ansible.cfg配置,通过ans用户连接,远程连接端口号,使用sudo
3. Ansible与自动化
总结:https://www.processon.com/view/link/61addd266376896056c1b1b2