ansible-playbook
1 目标
最终:根据服务使用流程,书写出对应的剧本.
2 剧本
2.1 剧本
- playbook 文件,用于长久保存并且实现批量管理,维护,部署的文件. 类似于脚本存放命令和变量,剧本中存放的时候?模块..
- 剧本yaml格式,yaml格式的文件: 空格,冒号.
- 剧本未来我们批量管理,运维必会的内容.
ans剧本 |
ans ad-hoc(命令行) -m -a | |
共同点 |
批量管理,使用模块 | 批量管理,使用模块 |
区别 |
重复调用,加上变量. | 不是很方便,不容易重复 |
应用建议(应用场景) |
部署服务,多个步骤的任务 | 测试模块,临时性任务 |
2.2 剧本书写格式
2.2.1 剧本核心概念:
角色 play 通过hosts部分指定的 (指定你要管理的主机(主机清单里面的)
任务 tasks 具体要执行的模块(根据你的步骤转换)
模块(根据你的操作流程,步骤选择模块)
2.2.2 基本格式
# 1. 顶格---开头(可以不写)
# 2. 以.yml或.yaml结尾
---
- hosts: all
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
黄色字体说明文件等有改动,绿色字体说明没改动,红色字体是报错
2.2.3 书写Ans playbook注意事项:⭐ ⭐ ⭐ ⭐ ⭐
同一个层级的内容对齐的.
不同层级的通过2个空格对齐
不能使用tab键
3 剧本案例
3.1 创建目录并分发文件
02_distribute.yaml
[root@m01 /server/ans/playbook]# cat 02_distribute.yaml
---
- hosts: all
tasks:
- name: touch directory
file:
path: /server/files
state: directory
- name: mv hosts
copy:
src: /etc/hosts
dest: /server/files
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 02_distribute.yaml
PLAY [all] ****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
ok: [172.16.1.69]
ok: [172.16.1.67]
TASK [touch directory] ****************************************************************************************************************************************************
changed: [172.16.1.67]
changed: [172.16.1.69]
changed: [172.16.1.68]
TASK [mv hosts] ***********************************************************************************************************************************************************
changed: [172.16.1.67]
changed: [172.16.1.69]
changed: [172.16.1.68]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.67 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.68 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible all -i /server/ans/playbook/hosts -a 'tree -F /server/files'
172.16.1.68 | CHANGED | rc=0 >>
/server/files
└── hosts
0 directories, 1 file
172.16.1.67 | CHANGED | rc=0 >>
/server/files
└── hosts
0 directories, 1 file
172.16.1.69 | CHANGED | rc=0 >>
/server/files
└── hosts
0 directories, 1 file
[root@m01 /server/ans/playbook]#
3.2 批量添加定时任务
3.2.1 删除之前的定时任务
sed -ri '/sync|ntpdate/d' /var/spool/cron/root
[root@m01 /server/ans/playbook]# ansible all -i /server/ans/playbook/hosts -a "sed -r /sync|ntpdate/d /var/spool/cron/root"
172.16.1.67 | CHANGED | rc=0 >>
172.16.1.69 | CHANGED | rc=0 >>
172.16.1.68 | CHANGED | rc=0 >>
[root@m01 /server/ans/playbook]# ansible all -i /server/ans/playbook/hosts -a "sed -ri /sync|ntpdate/d /var/spool/cron/root"
172.16.1.69 | CHANGED | rc=0 >>
172.16.1.67 | CHANGED | rc=0 >>
172.16.1.68 | CHANGED | rc=0 >>
[root@m01 /server/ans/playbook]# ansible all -i /server/ans/playbook/hosts -a "crontab -l"
172.16.1.67 | CHANGED | rc=0 >>
172.16.1.69 | CHANGED | rc=0 >>
172.16.1.68 | CHANGED | rc=0 >>
3.2.2 添加定时任务
03_sync_date.yaml
#添加脚本
[root@m01 /server/ans/playbook]# cat 03_sync_date.yaml
---
- hosts: all
tasks:
- name: sync time
cron:
name: update date
minute: "*/5"
job: "/sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1 "
state: present
[root@m01 /server/ans/playbook]#
# 批量执行脚本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 03_sync_date.yaml
PLAY [all] ****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
ok: [172.16.1.67]
ok: [172.16.1.68]
TASK [sync time] **********************************************************************************************************************************************************
changed: [172.16.1.67]
changed: [172.16.1.68]
changed: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.67 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.68 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# 批量查看结果
[root@m01 /server/ans/playbook]# ansible all -i hosts -a 'crontab -l'
172.16.1.69 | CHANGED | rc=0 >>
#Ansible: update date
*/5 * * * * /sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1
172.16.1.67 | CHANGED | rc=0 >>
#Ansible: update date
*/5 * * * * /sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1
172.16.1.68 | CHANGED | rc=0 >>
#Ansible: update date
*/5 * * * * /sbin/ntpdate ntp.aliyun.com >/dev/null 2>&1
[root@m01 /server/ans/playbook]# cd
3.3 nfs服务
3.3.1 要求:
nfs服务端:在xxx上部署nfs服务,共享/backup-nfs目录,all_squash,匿名用户:www-ans uid 2999 2999
nfs客户端:web挂载 /ans-upload目录挂载nfs服务端共享的/backup-nfs(永久挂载)
3.3.2 根据步骤流程-->模块
# 查看nfs server 配置
[root@nfs01 ~]# showmount -e
Export list for nfs01:
/data 172.16.1.0/24
/nfsdata 172.16.1.0/24
[root@nfs01 ~]#
[root@nfs01 ~]# hostname -I
10.0.0.68 172.16.1.68
[root@nfs01 ~]# cat /etc/exports
/nfsdata/ 172.16.1.0/24(rw,all_squash)
/data/ 172.16.1.0/24(rw,all_squash,anonuid=3999,anongid=3999)
[root@nfs01 ~]
# 新的服务端配置文件
[root@m01 /server/ans/playbook]# cat exports
/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]#
#1.nfs server
- hosts: nfs01
tasks:
- name: 1.安装 nfs
- name: 2.配置 /etc/exports
- name: 3.添加用户组 add group www-ans 4999
- name: 4.添加用户 add user www-ans
- name: 5.创建并更改目录属组/主 chown dir /nfs01_ans
- name: 6.启动rpc
- name: 7.启动 nfs
#2.nfs client
- hosts: web01
tasks:
- name: 1.安装nfs
- name: 2.添加用户组 add group 4999
- name: 3.添加用户 add user
- name: 4.创建目录 dir /data_ans
- name: 5.挂载 mount
3.3.3 书写剧本
04_nfs_server_client.yaml
[root@m01 /server/ans/playbook]# cat 04_nfs_server_client.yaml
# 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
- 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
systemd:
name: rpcbind
state: restarted
- name: 7.启动 nfs
systemd:
name: nfs
state: restarted
# 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]#
# 测试 -C 模拟运行剧本并不会真的运行
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C 04_nfs_server_client.yaml
# 实际执行
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 04_nfs_server_client.yaml
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=8 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
4 项目小结
1. 理清服务作用,服务使用流程.
2. 书写剧本核心: 列出步骤-->根据步骤找出对应的ansible模块
3. 书写剧本.
4. 调试剧本 ansible-playbook -i 主机清单文件 -C模拟运行 剧本(-C, --check)
5. 书写剧本前拍摄快照,边书写剧本边测试,最后测试完成,恢复快照,重新跑一次.(分步测试,联合测试)
5 Ansible中的变量
变量无处不在,在ans中大部分地方都可以定义变量.
比较常用的创建变量的地方:剧本中,类似于``功能,共用的变量文件.
可以定义变量的地方 |
说明 |
在剧本文件中定义 |
比较常用. 仅仅限于当前的play使用. |
register变量(注册变量) |
ip=`hostname -I` 实现脚本中反引号的功能,可以获取命令结果 |
变量文件,**根据主机清单分分组进行定义变量** |
如果多个剧本,使用相同的变量,大型的剧本roles |
inventory主机清单中定义变量 |
未来可以用于批量修改主机使用,其他很少用了 |
命令行中 |
几乎不用 |
facts变量 |
一般用于获取主机基本信息:ip,主机名,系统(centos/ubuntu) 如果不需要可以关闭,用于加速剧本的执行 |
5.1 剧本中使用变量⭐⭐⭐⭐⭐
ansible 变量命名规则:
- 与shell类似,不能以数字开头.
- 变量中仅包含_下划线即可.不要包含其他特殊符号.
05_vars.yaml
[root@m01 /server/ans/playbook]# cat 05_vars.yaml
# vars : variables 变量的内容,变量.
---
- hosts: web01
vars:
dir: /xk/test/upload
file: 1.txt
tasks:
- name: 01.mkdir
file:
path: "{{ dir }}"
state: directory
- name: 02.touch
file:
path: "{{ dir }}/{{ file }}"
state: touch
- name : 输出结果
debug:
msg: "目录名字:{{ dir }} 文件名字:{{ file }}"
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 05_vars.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [01.mkdir] ***********************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [02.touch] ***********************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [输出结果] ***********************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "目录名字:/xk/test/upload 文件名字:1.txt"
}
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible web01 -i hosts -a 'tree -F /xk/test'
172.16.1.69 | CHANGED | rc=0 >>
/xk/test
└── upload/
└── 1.txt
1 directory, 1 file
⚠ 温馨提示:
使用变量的时候如果变量是某个选项的开头,则变量引用的时候需要加上双引号
变量是开头加""
- hosts: web01
vars:
dir: /xk/test/upload
file: 1.txt
tasks:
- name: 01.mkdir
file:
path: "{{ dir }}" # 这种要添加"",变量是开头.
state: directory
- name: 02.touch
file:
path: "{{ dir }}/{{ file }}" # 这种要添加"",变量是开头.
state: touch
- name : 输出结果
debug:
msg: "目录名字:{{ dir }} 文件名字:{{ file }}" # 这种可以不加引号,变量不是开头.
在剧本play中定义变量应用:
- 仅仅在当前play生效.
- 一般用来存放路径,用户名,ip地址,类似于之前使用的脚本.
- 注意引号使用.
- 优势:使用简单,在剧本开头(play和tasks之间)创建即可.
- 缺点:只能在当前的play中生效,其他play中要使用变量,需要重新定义.
- 使用建议: 简单剧本,只有1个play可以使用.(一个hosts部分)
5.2 共用变量-变量文件
把变量写到1个文件中,在剧本play中通过vars_files指定变量文件
06_vars_file.yaml
[root@m01 /server/ans/playbook]# cat vars.yml
dir: /server/ans-test-01/
file: test.txt
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# cat 06_vars_file.yaml
- hosts: web01
vars_files:
- ./vars.yml
tasks:
- name: mkdir
file:
path: "{{ dir }}" #类似于 $dir 变量是开头就要加上引号.
state: directory
- name: touch
file:
path: "{{ dir }}{{ file }}" #类似于 $dir 变量是开头就要加上引号.
state: touch
- hosts: nfs01
vars_files:
- ./vars.yml
tasks:
- name: mkdir
file:
path: "{{ dir }}" #类似于 $dir 变量是开头就要加上引号.
state: directory
- name: touch
file:
path: "{{ dir }}{{ file }}" #类似于 $dir 变量是开头就要加上引号.
state: touch
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 06_vars_file.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [mkdir] **************************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [touch] **************************************************************************************************************************************************************
changed: [172.16.1.69]
PLAY [nfs01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
TASK [mkdir] **************************************************************************************************************************************************************
changed: [172.16.1.68]
TASK [touch] **************************************************************************************************************************************************************
changed: [172.16.1.68]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@m01 /server/ans/playbook]# ansible web01 -i hosts -a 'tree -F /server/ans-test-01'
172.16.1.69 | CHANGED | rc=0 >>
/server/ans-test-01
└── test.txt
0 directories, 1 file
[root@m01 /server/ans/playbook]# ansible nfs01 -i hosts -a 'tree -F /server/ans-test-01'
172.16.1.68 | CHANGED | rc=0 >>
/server/ans-test-01
└── test.txt
0 directories, 1 file
- 优点:相对于vars方法,通过vars_files指定共享变量文件.
- 缺点:每次使用还需要在Play中指定vars_files
- 使用建议,能够理解变量文件作用即可,一般使用下面的方法
5.3 共用变量-根据主机组使用变量 ⭐⭐⭐⭐⭐
- 这种方案本质:还是变量文件,多了个组功能.
- group_vars根据主机清单的分组去匹配变量文件.
- 主机组有变量用组机组的,没有去all里面找
- 主机组创建变量文件.
group_vars
主机组变量文件存放位置
[root@m01 /server/ans/playbook]# tree -F /server/ans/playbook/
/server/ans/playbook/
├── 01_test.yaml # 剧本
├── 02_distribute.yaml # 剧本
├── 03_sync_date.yaml # 剧本
├── group_vars/
│ ├── all/
│ │ └── vars.yml # 所有主机公有的变量文件
│ └── web01/
│ └── vars.yml # web01组私有的变量文件
└── hosts # 主机清单
3 directories, 16 files
[root@m01 /server/ans/playbook]# cat group_vars/all/vars.yml
dir: /server/ans-test-01/
file: test.txt
创建目录和文件
web01和nfs01
- hosts: web01
tasks:
- name: mkdir
file:
path: "{{ dir }}" .
state: directory
- name: touch
file:
path: "{{ dir }}{{ file }}"
state: touch
- hosts: nfs01
tasks:
- name: mkdir
file:
path: "{{ dir }}"
state: directory
- name: touch
file:
path: "{{ dir }}{{ file }}"
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 07_vars_group_all.yaml
[root@m01 /server/ans/playbook]# cat group_vars/all/vars.yml
dir: /server/ans-test-01/
file: test.txt
[root@m01 /server/ans/playbook]# cat group_vars/web01/vars.yml
dir: /server/ans-test-02/
file: 1.txt
[root@m01 /server/ans/playbook]# ansible all -i hosts -a 'tree -F /server'
172.16.1.68 | CHANGED | rc=0 >>
/server
├── ans-test-01/
│ └── test.txt
├── files/
└── hosts
172.16.1.69 | CHANGED | rc=0 >>
/server
├── ans-test-02/
└── 1.txt
5.4 变量定义小结
5.5 facts变量
Ansible定义变量方式 |
应用场景 |
⭐ 剧本文件中定义vars定义 |
变量仅在1个play中使用.(1个剧本中只有1个-hosts:) 常用 |
变量文件,剧本文件中通过vars_files调用 |
同1个剧本中多个play使用,别人使用你能理解含义. |
⭐ 变量文件 (组),group_vars |
自动读取group_vars/all/vars.yml内容. 未来用于书写大型剧本. |
facts变量相当于是ansible内置变量,存放被管理机器的基本信息.运行剧本的时候会运行:Gathering Facts task任务.
Gathering Facts :ansible收集被管理端基本信息.cpu,内存,磁盘,网络,系统.
我们在剧本中使用facts变量,未来如果不用可以关闭gather facts功能,加速剧本运行效果.
- ans内置变量,ans运行剧本的时候会有一个默认的task(Gathering Facts),这个背后在收集每个主机的基本信息.(eg:ip信息,主机名,磁盘,这个主机的各种基本信息)
- 这些基本信息就称为facts变量.
5.5.1 facts变量setup模块获取
-
- setup模块被用来收集目标主机的系统信息。setup模块是Ansible的一个核心模块,它不需要额外的安装,用于收集主机的各种事实(facts),
比如操作系统类型、内存大小、磁盘空间等。
- setup模块被用来收集目标主机的系统信息。setup模块是Ansible的一个核心模块,它不需要额外的安装,用于收集主机的各种事实(facts),
setup模块收集主机信息
[root@m01 /server/ans/playbook]# ansible -i hosts 172.16.1.68 -m setup >facts.yaml
#文件内容700多行,只看一些关键信息
"ansible_facts": {
"ansible_all_ipv4_addresses": [
"172.16.1.68",
"10.0.0.68"
],
"ansible_date_time": {
"date": "2024-10-17",
...
},
"ansible_hostname": "nfs01",
"ansible_default_ipv4": {
"address": "10.0.0.68",
"alias": "ens33",
"broadcast": "10.0.0.255",
"gateway": "10.0.0.2",
"interface": "ens33",
"macaddress": "00:50:56:2c:73:be",
"mtu": 1500,
"netmask": "255.255.255.0",
"network": "10.0.0.0",
"type": "ether"
},
"ansible_distribution": "Kylin Linux Advanced Server",
"ansible_distribution_file_path": "/etc/os-release",,
"ansible_distribution_version": "V10",
"ansible_dns": {
"nameservers": [
"223.5.5.5",
"223.6.6.6"
]
},
"ansible_machine": "x86_64",
"ansible_machine_id": "59ee89b9aaee492f86c8f945a2228acf",
"ansible_memfree_mb": 1335,
"ansible_memory_mb": {
"nocache": {
"free": 1602,
"used": 354
},
"real": {
"free": 1335,
"total": 1956,
"used": 621
},
"swap": {
"cached": 0,
"free": 2047,
"total": 2047,
"used": 0
}
},
"ansible_memtotal_mb": 1956,
"ansible_processor_cores": 2, # 核心
"ansible_processor_count": 1,
"ansible_processor_nproc": 2,
"ansible_processor_threads_per_core": 1,
"ansible_processor_vcpus": 2, # cpu核心总数量
"ansible_selinux": {
"status": "disabled"
},
}
5.5.2 常用fact变量
常用fact变量
ansible_hostname #主机名
ansible_memtotal_mb #内存大小(总计) 单位mb
ansible_processor_vcpus #cpu核心总数数量
ansible_default_ipv4.address #默认的网卡ip eth0
ansible_distribution #系统发行版本名字 CentOS Ubuntu Debian ...
ansible_distribution_version #系统的版本
ansible_date_time.date # 年-月-日
5.5.3 输出常用基本信息到屏幕,系统基本信息写入到/opt/facts.txt中.
08_facts.yaml
[root@m01 /server/ans/playbook]# cat 08_facts.yaml
- hosts: all
tasks:
- name: 调试变量
debug:
msg: |
"主机名:{{ ansible_hostname }}"
"内存大小:{{ ansible_memtotal_mb }}"
"cpu核数:{{ ansible_processor_vcpus }}"
- name: 保存到文件中
lineinfile:
path: /opt/facts.txt
create: true
line: |
主机名:{{ ansible_hostname }}
内存大小:{{ ansible_memtotal_mb }}
cpu核数:{{ ansible_processor_vcpus }}
系统: {{ ansible_distribution }}
系统版本:{{ ansible_distribution_version }}
[root@m01 /server/ans/playbook]#
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 08_facts.yaml
PLAY [all] ****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.68]
ok: [172.16.1.69]
ok: [172.16.1.87]
TASK [调试变量] ***********************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "\"主机名:web01\"\n\"内存大小:1956\"\n\"cpu核数:2\"\n"
}
ok: [172.16.1.68] => {
"msg": "\"主机名:nfs01\"\n\"内存大小:1956\"\n\"cpu核数:2\"\n"
}
ok: [172.16.1.87] => {
"msg": "\"主机名:backup\"\n\"内存大小:1927\"\n\"cpu核数:2\"\n"
}
TASK [保存到文件中] *******************************************************************************************************************************************************
changed: [172.16.1.87]
changed: [172.16.1.68]
changed: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.68 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
172.16.1.69 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
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 all -i hosts -a 'cat /opt/facts.txt'
[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 >>
主机名:backup
内存大小:1927
cpu核数:2
系统: Ubuntu
系统版本:22.04
172.16.1.68 | CHANGED | rc=0 >>
主机名:nfs01
内存大小:1956
cpu核数:2
系统: Kylin Linux Advanced Server
系统版本:V10
172.16.1.69 | CHANGED | rc=0 >>
主机名:web01
内存大小:1956
cpu核数:2
系统: Kylin Linux Advanced Server
系统版本:V10
[root@m01 /server/ans/playbook]#
说明:
debug模块用于在剧本中输出与调试,一般用于输出变量内容.
| 表示下面的内容是多行,用于输出或写入多行到文件中,注意索引对齐.
5.5.4 ans-facts 变量与判断
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 [all] ****************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
ok: [172.16.1.68]
ok: [172.16.1.87]
TASK [输出系统发行版本] ***************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "发行版本 Kylin Linux Advanced Server"
}
ok: [172.16.1.68] => {
"msg": "发行版本 Kylin Linux Advanced Server"
}
ok: [172.16.1.87] => {
"msg": "发行版本 Ubuntu"
}
TASK [if Kylin|CentOS] ****************************************************************************************************************************************************
skipping: [172.16.1.87]
ok: [172.16.1.69]
ok: [172.16.1.68]
TASK [if Ubuntu|Debian] ***************************************************************************************************************************************************
skipping: [172.16.1.69]
skipping: [172.16.1.68]
changed: [172.16.1.87]
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]#
facts变量实际应用案例:
- 通过facts变量获取系统的基本信息
- 通过facts变量获取信息并进行判断
- 如果不需要可以进行关闭,加速剧本的运行( gather_facts: false )
- 修改ansible.cfg #gathering = implicit去掉注释,永久关闭,后期剧本中需要开启gather_facts: true
- 布尔类型的数据:
真:yes,True,true (开启,启动)
假:no,False,false 假(关闭).
- hosts: all
gather_facts: false
tasks: ...
默认开启,不使用的时候临时关闭: gather_facts: false hosts: tasks之间
彻底关闭,使用的时候在剧本中临时开启 gather_facts: true
ansible.cfg
cat>/etc/ansible/ansible.cfg<<EOF
[defaults]
gathering = explicit
host_key_checking = False
deprecation_warnings = False
interpreter_python = /usr/bin/python3
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
EOF
gathering = explicit #彻底关闭facts,如果需要开启需要在剧本中设置,gather_facts: true
gathering = implicit ##开启facts变量 默认就是开启 如果需要关闭gather_facts: false
facts变量小结
- 需要通过变量获取主机的基本信息,ip或主机名...
- 使用的时候一般搭配when进行判断. 判断主机名,判断发行版本 when : xxx is match("Kylin")
- 如果不使用facts变量可以在剧本中关闭. gather_facts: false
5.6 register变量注册变量 ⭐⭐
本质上就是用来实现脚本中的反引号功能. ip=`hostname -I`
用户通过命令获取的内容都存放到Register变量中.
应用场景:获取命令执行结果或获取模块执行的结果.
5.6.1. 获取register变量信息
get_register_info
[root@m01 /server/ans/playbook]# cat 10_register_ip.yaml
- hosts: web01
tasks:
- name: get ip
shell: hostname -I | awk '{print $1}'
register: ip
- name: use ip
debug:
msg: "ip: {{ ip }}"
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 10_register_ip.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
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-17 17:02:54.378986', 'end': '2024-10-17 17:02:54.384595', 'delta': '0:00:00.005609', '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
变量格式
json形式数据. key: value
"msg": "ip: {
'changed': True,
'stdout': '10.0.0.69',
'stderr': '',
'rc': 0,
'cmd': \"hostname -I | awk '{print $1}'\",
'start': '2024-10-17 17:02:54.378986',
'end': '2024-10-17 17:02:54.384595',
'delta': '0:00:00.005609',
'msg': '',
'stdout_lines': ['10.0.0.69'],
'stderr_lines': [],
'failed': False
}"
5.6.2 使用register变量信息
[root@m01 /server/ans/playbook]# cat 10_register_ip.yaml
- hosts: web01
tasks:
- name: get ip
shell: hostname -I | awk '{print $1}'
register: ip
- name: use ip
debug:
msg: "ip: {{ ip.stdout }}"
- name: touch dir
file:
path: /opt/{{ ip.stdout }}
state: directory
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 10_register_ip.yaml
PLAY [web01] **************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************
ok: [172.16.1.69]
TASK [get ip] *************************************************************************************************************************************************************
changed: [172.16.1.69]
TASK [use ip] *************************************************************************************************************************************************************
ok: [172.16.1.69] => {
"msg": "ip: 10.0.0.69"
}
TASK [touch dir] **********************************************************************************************************************************************************
ok: [172.16.1.69]
PLAY RECAP ****************************************************************************************************************************************************************
172.16.1.69 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
符号说明
msg:中的|表示下面的内容是多行. |也可以用于其他模块中.
5.7 总结
Ansible定义变量方式 |
应用场景 |
⭐ 剧本文件中定义vars定义 |
变量仅在1个play中使用.(1个剧本中只有1个- hosts:) 常用 |
变量文件,剧本文件中通过vars_files调用 |
同1个剧本中多个play使用. |
⭐ 变量文件group_vars |
自动读取group_vars/all/vars.yml内容. 未来用于书写大型剧本. |
facts变量(ansible运行收集的信息) |
获取基本信息,未来一般与判断一起用. 如果不用可以关闭,加速剧本运行 |
register(注册变量) 创建变量存放命令的结果,命令行反引号
|
可以用于替代部分facts功能.一般与判断一起使用. |
官网:https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html
6 案例
6.1 nfs 存储
6.1.1 nfs_server剧本
nfs_server_playbook
# 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
6.1.2 nfs_client剧本
nfs_client_playbook
# 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
6.1.3 配置文件 /etc/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)
6.1.4 运行与调试
# nfs_server
# 调试
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C nfs_server_playbook.yaml
# 执行
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts nfs_server_playbook.yaml
# nfs_cleint
# 调试
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C nfs_client_playbook.yaml
# 执行
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts nfs_client_playbook.yaml
6.2 rsync 定时备份
根据shell 脚本书写playbook步骤
列出剧本任务
# rsync_server
- hosts:backup
tasks:
- name: 1.安装rsync
- name: 2.添加用户
- name: 3.创建备份目/nfs01backup录且更改权限rsync
- name: 4.修改配置文件/etc/rsyncd.conf
- name: 5.创建密码文件,修改权限600
- name: 6.rsync重启
- name: 7.文件校验(shell脚本实现) ans_bak_file_server.sh
- name: 8.备份数据(shell脚本实现) ans_bak_file_server.sh
- name: 9.将shell脚本分发到rsync_server
- name: 10.将脚本加入定时任务
# rsync_client
- hosts:nfs01
tasks:
- name: 1.创建备份目录 /nfs01backup
- name: 2.创建密码文件,修改权限600
- name: 3.打包数据(shell脚本实现) ans_bak_file_client.sh
- name: 4.数据加密 md5(shell脚本实现) ans_bak_file_client.sh
- name: 5.远程备份(shell脚本实现) ans_bak_file_client.sh
- name: 6.清理7天前数据(shell脚本实现) ans_bak_file_client.sh
- name: 7.将shell脚本分发到rsync_client
- name: 8.将脚本加入定时任务
6.2.1 rsync_server 剧本
21_rsync_server.yaml
- hosts: backup
gather_facts: true
tasks:
- 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
dest: /etc/rsyncd.conf
backup: yes
- 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: 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")
- name: 8.分发脚本
copy:
src: ./ans_bak_file_server.sh
dest: /server/scripts
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
6.2.2 rsync _client 剧本
22_rsync_client.yaml
#rsync_client
- hosts: nfs01
tasks:
- 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.分发脚本
copy:
src: ./ans_bak_file_client.sh
dest: /server/scripts
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
6.2.3 配置文件 /etc/rsyncd.conf
rsyncd.conf
# 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
6.2.4 rsync_server_shell脚本
ans_bak_file_server.sh
#!/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
6.2.5 rsync_client _shell脚本
ans_bak_file_client.sh
[root@nfs01 ~]# cat /server/scripts/ans_bak_file_client.sh
#!/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
6.2.6 运行与调试
调试
# 1.测试服务端剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C 21_rsync_server.yaml
# 2.测试客户端剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts -C 22_rsync_client.yaml
# 3.运行服务端剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 21_rsync_server.yaml
# 4.运行客户端剧本
[root@m01 /server/ans/playbook]# ansible-playbook -i hosts 22_rsync_client.yaml
# 5.手动运行客户端(存储)脚本
[root@nfs01 ~]# bash -x /server/scripts/ans_bak_file_client.sh
[root@nfs01 ~]# tree -F /nfs01backup/
/nfs01backup/
└── 10.0.0.68/
├── 2024-10-23_3.tar.gz
└── bak.md5
1 directory, 2 files
[root@nfs01 ~]# cat /nfs01backup/10.0.0.68/bak.md5
326a8de19879d1fabd2ce4330461c242 /nfs01backup/10.0.0.68/2024-10-23_3.tar.gz
[root@nfs01 ~]#
# 6.手动运行服务端(备份)脚本
[root@backup ~]# bash -x /server/scripts/ans_bak_file_server.sh
[root@backup ~]# tree -F /nfs01backup
/nfs01backup
├── 10.0.0.68/
│ ├── 2024-10-23_3.tar.gz
│ └── bak.md5
└── md5.txt
1 directory, 3 files
[root@backup ~]# cat /nfs01backup/md5.txt
/nfs01backup/10.0.0.68/2024-10-23_3.tar.gz: 成功
注意:
在 Linux 中,普通用户以 root
权限执行脚本,sudo
是最常用的方法,可以让普通用户以 root
权限执行特定命令或脚本。
1. 确保用户在 sudoers
文件中有权限。username ALL=(ALL) ALL
2. 然后 sudo bash 脚本名