Ansible的Playbook快速入门指南
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
目录
一.Playbook概述
1.什么是Playbook
在ansible中,比较简单的任务,我们可以直接调用单个模块来完成,但遇到比较复杂的场景,需要调用大量模块才能完成一个需求,或者多个任务间有依赖的时候,使用单条命令就特别不方便,这种情况下我们就需要Playbook剧本来实现。
Playbook字面意思是剧本,演员按照剧本来演戏,运维人员编写Playbook剧本内容,而后ansible按照我们编写的剧本去执行任务。
2.模块(module)和剧本(playbook)的区别
- Playbook是对多个AD-Hoc(module)的一种编排组合的实现方式;
- Playbook能控制任务执行的先后顺序;
- Playbook可以持久保存到文件从而方便多次调用运行,而Ad-Hoc(module)只能临时运行;
- Playbook适合复杂的重复性的任务,而Ad-Hoc(module)适合做快速简单的一次性任务;
温馨提示:
AD-Hoc指的是使用模块的一种方式,比如: " ansible -m '模块名称' -a '参数信息' "
3.playbook文件规范
playbook文件规范:
- 扩展名称为yaml或者yml;
- 第一行使用"---"表示yaml的开始,一般不写,如果多个yaml文件合并才会使用此标识;
- 使用"#"作为注释;
- 大小写敏感;
- 缩进符要统一,用空格键缩进,不要用tab;
- 缩进空格数量不重要,但是,相同层级的左边缩进,要对齐,保持一致;
- 使用"- "表示单个列表项目;
- 使用": "表示一个键值对;
- 使用"{}"表示一个键值表;
- 一个name只能有一个task;
4.Playbook的组成
Playbook是由一个或多个"play"组成的列表,Playbook的主要功能在于,将多个play组织在一个Playbook文件中,让多台预定义的主机按照Playbook中编排的内容完成一系列复杂的功能。
一个Playbook至少要包含hosts和tasks两部分,主要由以下几部分组成:
- hosts:
指定要执行任务的远程主机,其值可以是通配符,主机或组。
但一定要在主机清单中定义过的(/etc/ansible/hosts),可以用-i选项指定自定义的主机清单文件。
- tasks:
定义要在远程主机上执行的任务列表。
各任务按顺序在hosts中指定主机上执行,即所有主机当做完当前任务,才会开始下一个任务。
task的模式是执行指定模块,后面跟上预定的参数,参数中可以使用变量,模块的执行是幂等的。
这意味着多次执行是安全的,因为其结果均一致。
如果在执行过程中发生错误,则会全部回滚(包括前面已执行成功的)。
每个task都应该定义name,用于执行结果的输出,如果没有指定name,则action的结果将用于输出。
- remote_user:
指定任务在远程主机上执行时,所使用的用户,可以是任意用户。
也可以sudo,但前提是用户是存在的,可以不写,默认root。
- tags:
定义哪些代码内容可与被忽略,就是用tags跳过部分代码。
标记应用于任务或包含的任务,这允许从命令行中选择任务的子集。
- notify|handlers:
一般配合使用,可以达到一种触发调用高度效果,类似于函数调用或触发器。
- gather_facts:
默认会自动调用的模块。
获取远程主机的一些信息,可以在下面的任务重使用,相当于构造函数,可以禁用。
- environment:
定义Playbook运行时需要使用的变量,有多种定义方式。
一个被转换为环境变量的字典,在执行时为任务提供。这只能与模块一起使用。
任何其他类型的插件、Ansible本身及其配置都不支持此功能,它只是为负责执行任务的代码设置变量。
这不是传递机密数据的推荐方式。
所有组成可以参考官方文档:
https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html
5.playbook示例
1.编写配置文件
[root@worker232 ~]# cat ping.yaml
- hosts: all
remote_user: root
tasks:
- name: t1
ping:
- name: t2
shell: "ifconfig"
[root@worker232 ~]#
2.加载Playbook示例
[root@worker232 ~]# ansible-playbook ping.yaml
PLAY [all] ***********************************************************************************************************************************************
TASK [Gathering Facts] ***********************************************************************************************************************************
ok: [10.0.0.232]
ok: [10.0.0.233]
ok: [10.0.0.231]
TASK [t1] ************************************************************************************************************************************************
ok: [10.0.0.232]
ok: [10.0.0.233]
ok: [10.0.0.231]
TASK [t2] ************************************************************************************************************************************************
changed: [10.0.0.233]
changed: [10.0.0.231]
changed: [10.0.0.232]
PLAY RECAP ***********************************************************************************************************************************************
10.0.0.231 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.232 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
10.0.0.233 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@worker232 ~]#
二.YAML语言
1.什么是YAML
yaml是"Yet Another Markup Language"的简称,YAML是一种人性化的数据序列化。
和HTML,XML,JSON类似,又是一款标记性语言,但你看它官网还会很傲娇的说" YAML Ain't Markup Language"。
YAML是一个可读性高的用来表达资料序列的格式,是目前比较流行的配置文件格式,很多新的项目或者软件都采用yaml文件来保存配置信息,比如ubuntu,ansible,docker,kubernetes,ElasticStack等。
官网地址:
https://yaml.org
2.YAML的数据类型及特点
| 数据类型 | 描述 | 示例 |
|---|---|---|
| scalar(标量) | 单个的,不可再分的值。 包括但不限于字符串,布尔值,整数,浮点数,时间,日期,Null等。 |
name: "Jason Yin" age: 18 |
| object(对象) | 键值对的集合,又称为字典(dictionary)|哈希(hashes)|映射(mapping) | labels: apps: xiuxian version: v1 |
| array(数组) | 一组按次序排列的值,又称为列表(list)|序列(sequence) | command: - tail - -f - /etc/hosts |
YAML中的数据类型如上表所示。
YAML语言特点:
- yaml的可读性好;
- yaml和脚本语言交互性强;
- yaml使用实现语言的数据类型;
- yaml有一个一致的信息模型;
- yaml易于实现;
- yaml可以基于流来处理;
- yaml表达能力强,扩展性好;
三.ansible-playbook命令
1.ansible-playbook命令格式
1.1 语法格式
ansible-playbook [options] <filename.yaml>
常见的选项[options]:
--syntax-check|--syntax
语法检查。
-C|--check:
执行模拟,只检测可能会发生的改变,但不真正执行操作。
-i|--inventory|--inventory-file:
指定主机清单文件。
-l|--limit:
单位指定主机列表去执行。
-k|--ask-pass:
远程连接密码。
-T|--timeout:
连接超时时长,默认10s。
-e|--extra-vars:
定义变量。
--become-user:
指定用户执行。
--flush-cache:
刷新facts。
--list-hosts:
列出所有主机。
--list-tags:
列出Playbook中所有tag。
-skip-tags:
跳过指定tags。
-t|--tags:
只执行特定tag对应的task。
--start-at-task:
从指定task开始执行。
--list-tasks:
列出Playbook中所有task。
-v|--verbose:
显示详细信息,最多可以写5个v。
1.2 ansible-playbook选项示例
1.编写主机清单文件
[root@worker232 ~]# cat /etc/ansible/hosts
[k8s]
10.0.0.23[1:3]
[k8s:vars]
ansible_ssh_password=1
[root@worker232 ~]#
2.查看主机列表
[root@worker232 ~]# ansible-playbook --list-hosts demo.yaml
playbook: demo.yaml
play #1 (all): all TAGS: []
pattern: ['all']
hosts (3):
10.0.0.233
10.0.0.232
10.0.0.231
[root@worker232 ~]#
3.检查配置文件语法
[root@worker232 ~]# ansible-playbook --syntax -vvvvv demo.yaml
ansible-playbook [core 2.12.0]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible-playbook
python version = 3.10.12 (main, Nov 6 2024, 20:22:13) [GCC 11.4.0]
jinja version = 3.0.3
libyaml = True
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
1 plays in demo.yaml
playbook: demo.yaml
[root@worker232 ~]#
2.ansible-playbook执行结果
2.1 编写剧本
[root@worker232 ~]# cat demo.yaml
# 指定主机分组【支持主机的匹配模式】
- hosts: all
# 不收集主机信息,以提升运行速度
gather_facts: no
# 定义远程执行的用户,如果不写,默认就是root用户。
# 如果在主机清单中定义了"ansible_ssh_user"参数则无视此配置,下同。
remote_user: root
# 定义任务列表
tasks:
# 定义任务的名称
- name: t1
# 具体的模块和参数
command: id
# 指定模块的执行用户,会覆盖掉上面的root用户
remote_user: yinzhengjie
# 对于查询类任务,我们就不让他改变系统
changed_when: false
- name: t2
shell: "echo 10+20|bc"
changed_when: false
- name: t3
copy: 'content=#!/usr/bin/python3.10\n\nprint("杰哥讲运维")\nprint("https://www.cnblogs.com/yinzhengjie") dest=/tmp/yinzhengjie.py'
[root@worker232 ~]#
2.2 运行剧本
[root@worker232 ~]# ansible-playbook demo.yaml -l 10.0.0.231 -v
Using /etc/ansible/ansible.cfg as config file
PLAY [all] ***********************************************************************************************************************************************
TASK [t1] ************************************************************************************************************************************************
ok: [10.0.0.231] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "cmd": ["id"], "delta": "0:00:00.003250", "end": "2025-01-12 08:53:55.392259", "msg": "", "rc": 0, "start": "2025-01-12 08:53:55.389009", "stderr": "", "stderr_lines": [], "stdout": "uid=1000(yinzhengjie) gid=1000(yinzhengjie) groups=1000(yinzhengjie),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)", "stdout_lines": ["uid=1000(yinzhengjie) gid=1000(yinzhengjie) groups=1000(yinzhengjie),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd)"]}
TASK [t2] ************************************************************************************************************************************************
ok: [10.0.0.231] => {"changed": false, "cmd": "echo 10+20|bc", "delta": "0:00:00.003885", "end": "2025-01-12 08:53:55.626574", "msg": "", "rc": 0, "start": "2025-01-12 08:53:55.622689", "stderr": "", "stderr_lines": [], "stdout": "30", "stdout_lines": ["30"]}
TASK [t3] ************************************************************************************************************************************************
changed: [10.0.0.231] => {"changed": true, "checksum": "2ff8189035b80ea1a00758c53d6adb24eae663bf", "dest": "/tmp/yinzhengjie.py", "gid": 0, "group": "root", "md5sum": "9c969b0ba5be0a78c437540b16be8243", "mode": "0644", "owner": "root", "size": 92, "src": "/tmp/ansible-tmp-1736643235.0918655-37397-238348265580265/source", "state": "file", "uid": 0}
PLAY RECAP ***********************************************************************************************************************************************
10.0.0.231 : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@worker232 ~]#
PLAY RECAP执行结果说明:
ok=3
3个task执行成功。
changed=1
1个task导致了系统状态发生了变化。
unreachable=0
0个task不可达。
failed=0
0个task执行失败。
skipped=0
0个task被跳过。
rescued=0
0个task被拒绝。
ignored=0
0个task被忽略。
3.ansible-vault文件加密解密
3.1 创建新文件剧本【文件不能存在】
[root@worker232 ~]# ansible-vault create yinzhengjie.yaml
New Vault password:
Confirm New Vault password:
[root@worker232 ~]#
[root@worker232 ~]# file yinzhengjie.yaml
yinzhengjie.yaml: Ansible Vault, version 1.1, encryption AES256
[root@worker232 ~]#
[root@worker232 ~]# cat yinzhengjie.yaml # 无法查看文件内容
$ANSIBLE_VAULT;1.1;AES256
65373965353531316232383462303362313735326632333664353038656164623539663337373934
6164383661333862643366386665626664663632393838370a303532623834613264393730636665
63643134393263663835333666656138383132373636353130353134386532303837333535323838
3932636564663661350a643261313265636333326161373365363762646639663764383238306464
6261
[root@worker232 ~]#
3.2 解密剧本文件内容
[root@worker232 ~]# ansible-vault view yinzhengjie.yaml
Vault password: # 输入密码后才能查看
- hosts: all
tasks:
- name: t1
shell: id
[root@worker232 ~]#
3.3 编辑加密剧本文件
[root@worker232 ~]# ansible-vault edit yinzhengjie.yaml
Vault password: # 编辑时也需要输入密码
3.4 执行加密剧本文件
[root@worker232 ~]# echo 1 > /tmp/pwd.log
[root@worker232 ~]# ansible-playbook --vault-password-file /tmp/pwd.log yinzhengjie.yaml
3.5 删除密码保护
[root@worker232 ~]# file yinzhengjie.yaml
yinzhengjie.yaml: Ansible Vault, version 1.1, encryption AES256
[root@worker232 ~]#
[root@worker232 ~]# ansible-vault decrypt yinzhengjie.yaml
Vault password:
Decryption successful
[root@worker232 ~]#
[root@worker232 ~]# file yinzhengjie.yaml
yinzhengjie.yaml: ASCII text
[root@worker232 ~]#
四.Playbook案例
1.创建用户和组
1.编写剧本
[root@worker232 yinzhengjie]# cat bigdata_user.yaml
- hosts: 10.0.0.231
gather_facts: no
tasks:
- name: create hadoop group
group: name=hadoop system=yes gid=666
- name: create hdfs user
user: name=hdfs system=yes group=hadoop uid=777 shell=/sbin/nologin home=/home/hdfs create_home=no
[root@worker232 yinzhengjie]#
2.检查剧本语法
[root@worker232 yinzhengjie]# ansible-playbook --syntax-check bigdata_user.yaml
playbook: bigdata_user.yaml
[root@worker232 yinzhengjie]#
3.执行剧本
[root@worker232 yinzhengjie]# ansible-playbook -l 10.0.0.231 bigdata_user.yaml
4.远程服务器验证用户
[root@master231 ~]# id hdfs
uid=777(hdfs) gid=666(hadoop) groups=666(hadoop)
[root@master231 ~]#
[root@master231 ~]# getent passwd hdfs
hdfs:x:777:666::/home/hdfs:/sbin/nologin
[root@master231 ~]#
[root@master231 ~]# ll /home/
total 20
drwxr-xr-x 5 root root 4096 Jan 10 00:28 ./
drwxr-xr-x 20 root root 4096 Jan 11 12:14 ../
drwxr-x--- 3 2026 2026 4096 Jan 10 00:28 hanpaopao/
drwxrwxrwx 4 1002 jasonyin2020 4096 Jan 5 23:53 jasonyin2020/
drwxr-x--- 6 yinzhengjie yinzhengjie 4096 Jan 5 22:47 yinzhengjie/
[root@master231 ~]#
2.安装nginx服务
1.编写剧本
[root@worker232 yinzhengjie]# cat install_nginx.yaml
- hosts: 10.0.0.233
gather_facts: no
tasks:
- name: install nginx
apt:
name: nginx=1.18.0-6ubuntu14.5
state: present
- name: set nginx index page
copy:
src: ./blog.txt
# dest: /usr/share/nginx/html/index.html
# 我的Ubuntu22.04 LTS系统安装nginx默认站点放在了/var/www/html
dest: /var/www/html/index.html
- name: restart nginx service
service:
name: nginx
state: restarted
enabled: yes
[root@worker232 yinzhengjie]#
2.准备测试页面
[root@worker232 yinzhengjie]# echo https://www.cnblogs.com/yinzhengjie > blog.txt
[root@worker232 yinzhengjie]#
[root@worker232 yinzhengjie]# cat blog.txt
https://www.cnblogs.com/yinzhengjie
[root@worker232 yinzhengjie]#
3.运行剧本
[root@worker232 yinzhengjie]# ansible-playbook -l 10.0.0.233 install_nginx.yaml
4.访问测试
[root@worker232 yinzhengjie]# curl 10.0.0.233
https://www.cnblogs.com/yinzhengjie
[root@worker232 yinzhengjie]#
3.其他案例
有了上面的知识点,就可以完成我留的课堂作业了。
比如完成zookeeper,kafka,ElasticSearch,Prometheus,Ceph,K8S等集群的一键部署。
五.Playbook中的nofify和handlers
1.nofify和handlers概述
handlers本质上就是任务列表(task list),也定义了一系列task,每个task中同样调用指定模块执行操作。
只不过handlers中定义的task,不会主动执行,需要配合notify,让notify通知相应的handlers中的task,该task才会执行。
在Playbook中,如果有task执行失败,那整个Playbook也执行失败,即便有部分task执行成功,这部分task对饮高度handlers也不会被执行,force_handlers保证的是已成功执行的task对应的handlers一定会被执行。
nofify配合handlers,可以实现在特定条件下触发某些操作,例如服务器重启 ,服务重载等场景。
温馨提示:
- 1.如果多个task通知了相同的handlers,此handlers仅会在所有task结束后运行一次;
- 2.只有notify对应的task发生改变了才会通知handlers,没有改变则不会触发handlers;
- 3.handlers是在所有前面的tasks都执行成功才会执行,如果前面任何一个task失败,会导致handlers跳过执行;
2.单个notify和handlers示例
1.编写剧本
[root@worker232 yinzhengjie]# cat single-notify.yaml
- hosts: 10.0.0.233
gather_facts: no
tasks:
- name: set nginx index page
copy:
src: ./blog.txt
dest: /usr/share/nginx/html/index.html
- name: set nginx config
copy: src=./nginx-sites.conf dest=/etc/nginx/conf.d
# 当拷贝的文件发生变化时,就会触发handlers
notify: reload nginx svc
# handlers等到所有task执行完成之后才会被调用
# 而且对于同一个handler,多个notify,也只会执行一次
handlers:
- name: reload nginx svc
service: name=nginx state=restarted
[root@worker232 yinzhengjie]#
2.准备配置文件
[root@worker232 yinzhengjie]# cat nginx-sites.conf
server {
listen 81;
server_name www.yinzhengjie.com;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
[root@worker232 yinzhengjie]#
3.执行剧本
[root@worker232 yinzhengjie]# ansible-playbook -l 10.0.0.233 single-notify.yaml
4.访问测试
[root@worker232 yinzhengjie]# curl -H "host: www.yinzhengjie.com" 10.0.0.233:81
https://www.cnblogs.com/yinzhengjie
[root@worker232 yinzhengjie]#
3.多个notify和handlers示例
1.编写剧本
[root@worker232 yinzhengjie]# cat multiple-notify.yaml
- hosts: 10.0.0.233
gather_facts: no
tasks:
- name: t1
shell: echo "task 01"
notify: [h1,h2]
- name: t2
shell: echo "task 02"
notify:
- h1
- h2
handlers:
- name: h1
shell: echo h1
- name: h2
shell: echo h2
[root@worker232 yinzhengjie]#
2.执行剧本【2和task同时调用了多个handlers,但最终只会执行一次】
[root@worker232 yinzhengjie]# ansible-playbook multiple-notify.yaml
4.force_handlers示例
1.编写剧本
[root@worker232 yinzhengjie]# cat force_handlers.yaml
- hosts: 10.0.0.231
gather_facts: no
# 表示成功执行的task,其调用的handlers肯定会执行成功
force_handlers: yes
tasks:
- name: t1
shell: echo "task01"
notify: h1
- name: t2
# 故意让t2任务执行失败,因为我主机上并没有myecho命令哟~
shell: myecho "task02"
notify: h2
- name: t3
shell: echo "task01"
notify: h3
handlers:
- name: h1
debug: msg="in h1 handlers"
- name: h2
debug: msg="in h2 handlers"
- name: h3
debug: msg="in h3 handlers"
[root@worker232 yinzhengjie]#
2.执行剧本【由于第2个task失败,导致后续的handlers均无法调用】
[root@worker232 yinzhengjie]# ansible-playbook force_handlers.yaml
六.ignore_errors忽略错误
1.ignore_errors概述
在同一个Playbook中,如果一个task出错,则默认不会再继续执行后续的其他task。
利用"ignore_errors: yes"可以忽略此错误,继续执行其他task,此项可以配置为全局选项。
2.ignore_errors示例
1.编写剧本
[root@worker232 yinzhengjie]# cat ignore_errors.yaml
- hosts: 10.0.0.231
gather_facts: no
force_handlers: yes
# 如果任务执行失败,则可以忽略错误继续向下执行任务。
ignore_errors: yes
tasks:
- name: t1
shell: echo "task01"
notify: h1
- name: t2
shell: myecho "task02"
notify: h2
- name: t3
shell: echo "task01"
notify: h3
handlers:
- name: h1
debug: msg="in h1 handlers"
- name: h2
debug: msg="in h2 handlers"
- name: h3
debug: msg="in h3 handlers"
[root@worker232 yinzhengjie]#
2.执行剧本【尽管t2任务执行失败,但t3依旧是可以正常执行的】
[root@worker232 yinzhengjie]# ansible-playbook ignore_errors.yaml
七.Playbook的tags
1.tags概述
ansible在执行一个Playbook时,会执行Playbook中所有的任务,可以利用tag标记特定task而非整个Playbook文件。
一个task可以定义多个tags,也可以多个task对应同一个tag。
tags主要用于调试环境,内置有三个特殊的tags:
- all:
表示所有任务。
- tagged:
表示所有被tag标记的任务。
- untagged:
表示所有没有被标记的任务。
2.tags示例
1.编写剧本
[root@worker232 yinzhengjie]# cat tags.yaml
- hosts: 10.0.0.231
gather_facts: no
tasks:
- name: t1
shell: echo "in t1 task"
tags: [k8s,ceph]
- name: t2
shell: echo "in t2 task"
tags: [k8s,docker]
- name: t3
shell: echo "in t3 task"
tags: [elasticstack]
- name: t4
shell: echo "in t4 task"
[root@worker232 yinzhengjie]#
2.查看tags信息
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml --list-tags
playbook: tags.yaml
play #1 (10.0.0.231): 10.0.0.231 TAGS: []
TASK TAGS: [ceph, docker, elasticstack, k8s]
[root@worker232 yinzhengjie]#
3.查看任务信息
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml --list-tasks
playbook: tags.yaml
play #1 (10.0.0.231): 10.0.0.231 TAGS: []
tasks:
t1 TAGS: [ceph, k8s]
t2 TAGS: [docker, k8s]
t3 TAGS: [elasticstack]
t4 TAGS: []
[root@worker232 yinzhengjie]#
4.执行指定tags案例
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t k8s
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t docker
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t elasticstack
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t ceph,docker
5.使用内置的tags案例
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t untagged
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t tagged
[root@worker232 yinzhengjie]# ansible-playbook tags.yaml -t all
八.Playbook的变量
1.playbook变量概述
Playbook支持变量的定义与引用,变量有数字,字母下划线组成,区分大小写且只能以字母开头。
变量定义的两种方式:
方式一:
KEY=VALUE,例如: name=yinzhengjie
方式二:
KEY: VALUE,例如: age: 18
引用变量的方式:
通过"{{ 变量名称 }}"来调用,例如: "{{ name }}"
变量的来源:
- 1.使用setup facts获取的远程主机信息都是放在变量中的,可以直接使用;
- 2.在命令行执行ansible-playbook时,可以使用-e选项设置变量,这种变量的优先级最高;
- 3.在Playbook文件中定义变量;
- 4.在单独的变量文件中定义变量,在Playbook中引用该文件;
- 5.在主机清单中定义,当单独主机的变量与分组的变量有冲突时,单独定义的主机变量,优先级更高;
- 6.在主机变量目录(host_vars)和主机分组目录(group_vars)中创建以主机名或分组名为文件名的文件,在该文件中定义;
- 7.使用register将其他task或模块执行的输出内容保存到变量中,供别的task来使用;
- 8.在role中定义;
变量的优先级:
- 1"-e"选项定义变量;
- 2.Playbook中vars_files;
- 3.Playbook中vars变量定义;
- 4.host_vars/主机名文件;
- 5.主机清单中主机变量;
- 6.group_vars/主机组名文件;
- 7.group_vars/all 文件;
- 8.主机清单组变量;
2.使用setup模块中的变量
2.1 setup模块概述
在命令行中,可以通过指定setup模块的方式获取目标主机信息。在Playbook中,可以使用gather_facts选项来获得目标主机的信息。
gather_facts选项默认是yes,次执行都需要消耗一定的资源和时间,在不需要时可以禁用该项来加快Playbook的执行效率。
如果需要收集远程主机的信息,合理的配置“ansible.cfg”中facts相关的本地缓存策略,以便在频繁执行时减少资源消耗。
gathering=implicit
facts策略,有效值为: implicit(the default),explicit,smart。
implicit:
不使用缓存,每次都抓取新的。
explicit:
不收集主机信息,除非在playbook中用"gather_facts: yes"显式指定。
smart:
远程主机信息如果有本地缓存,则使用缓存,如果没有,就去抓取,在存到缓存中,下次就直接使用缓存信息。
fact_caching_timeout=86400
本地缓存时长,默认86400s
fact_caching=memory
缓存类型,默认是memory,如果jsonfile,需要指定文件,如果redis,需要指定redis地址。
fact_caching_connection=/path/to/cachedir
本地缓存路径
2.2 开启gather_facts实战案例
1.编写剧本
[root@worker232 yinzhengjie]# cat setup-facts.yaml
- hosts: 10.0.0.231
gather_facts: yes
tasks:
- name: show-facts
debug: msg={{ ansible_facts }}
- name: show-facts-hostname
debug: msg={{ ansible_hostname }}
- name: show-facts-ipv4-xixi
debug: msg={{ ansible_facts["eth0"]["ipv4"]["address"] }}-----{{ ansible_facts.eth0.ipv4.address }}
- name: show-facts-ipv4-haha
debug: msg={{ ansible_eth0["ipv4"]["address"] }}@@@@@{{ ansible_eth0.ipv4.address }}
- name: show-facts-ipv4-hehe
debug: msg={{ ansible_default_ipv4["address"] }}#####{{ ansible_default_ipv4.address }}
[root@worker232 yinzhengjie]#
2.执行剧本
[root@worker232 yinzhengjie]# ansible-playbook setup-facts.yaml
3 在命令行传递环境变量
3.1 编写剧本
[root@worker232 yinzhengjie]# cat facts-custom-variables.yaml
- hosts: 10.0.0.231
gather_facts: no
tasks:
- name: t1
debug: msg={{ name }}:{{ hobby }}
- name: t2
shell: echo "https://www.cnblogs.com/yinzhengjie"
notify: h1
handlers:
- name: h1
debug: msg={{ gender }}
[root@worker232 yinzhengjie]#
3.2 执行剧本
1.在命令行中指定
[root@worker232 yinzhengjie]# ansible-playbook -e name=yinzhengjie -e hobby=K8S -e gender=boy facts-custom-variables.yaml -v
2.多个变量一次定义
[root@worker232 yinzhengjie]# ansible-playbook -e "name=yinzhengjie hobby=K8S gender=boy" facts-custom-variables.yaml -v
3.从文件中加载变量
[root@worker232 yinzhengjie]# cat ./variables.txt
name: JasonYin2020
hobby: 象棋
gender: boy
[root@worker232 yinzhengjie]#
[root@worker232 yinzhengjie]# ansible-playbook -e "@./variables.txt" facts-custom-variables.yaml -v
4.在Playbook文件中定义变量
4.1 Playbook文件变量概述
在Playbook文件中定义的变量,只能在当前Playbook中使用,属于私有变量。
4.2 Playbook文件变量案例
1.编写剧本
[root@worker232 yinzhengjie]# cat variables-playbook.yaml
- hosts: 10.0.0.231
gather_facts: yes
vars:
name: 尹正杰
hobby: kubernetes
gender: boy
ip: "{{ ansible_facts.eth0.ipv4.address }}"
tasks:
- name: t1
debug: msg={{ name }}:{{ hobby }}
- name: t2
shell: echo "https://www.cnblogs.com/yinzhengjie"
notify: h1
- name: t3
debug: msg="变量支持互相调用 ---> {{ ip }}"
handlers:
- name: h1
debug: msg={{ gender }}
[root@worker232 yinzhengjie]#
2.执行剧本
2.1 使用Playbook定义的变量
[root@worker232 yinzhengjie]# ansible-playbook variables-playbook.yaml
2.2 命令行传递的变量可以覆盖Playbook的变量
[root@worker232 yinzhengjie]# ansible-playbook -e "name=JasonYin" variables-playbook.yaml
5.在单独文件中定义变量
5.1 文件定义变量的优先级概述
在单独的变量文件中定义变量的优先级比在Playbook本身定义的变量优先级更高。
在Playbook引用变量使用"vars_files"来定义,而"vars"在Playbook内置的变量,命令行传参使用"-e"来指定。
5.2 文件定义变量案例
1.定义变量文件
[root@worker232 yinzhengjie]# cat var01.txt
name: JasonYin
age: 18
[root@worker232 yinzhengjie]#
[root@worker232 yinzhengjie]# cat var02.txt
address: BeiJing
[root@worker232 yinzhengjie]#
2.Playbook引用变量文件
[root@worker232 yinzhengjie]# cat ref-variables.yaml
- hosts: 10.0.0.231
gather_facts: no
vars_files:
- var01.txt
- /root/yinzhengjie/var02.txt
vars:
name: 尹正杰
age: 30
address: 北京
hobby: "Kubernetes"
tasks:
- name: t1
debug: msg="{{ name }}---{{ age }}---{{ address }}---{{ hobby }}"
[root@worker232 yinzhengjie]#
3.执行剧本
3.1 验证vars_files优先级高于vars
[root@worker232 yinzhengjie]# ansible-playbook ref-variables.yaml
3.2 验证命令行变量优先级更高,vars_files次之,vars最低
[root@worker232 yinzhengjie]# ansible-playbook -e "name=杰哥讲运维" ref-variables.yaml
6.在主机清单中定义变量
6.1 在主机清单定义变量
[root@worker232 yinzhengjie]# cat /etc/ansible/hosts
[k8s]
# 给分组的特定主机添加变量
10.0.0.23[1:3] hobby="k8s"
10.0.0.14[1:3]
# 给整个分组定义变量
[k8s:vars]
ansible_ssh_password=1
name="yinzhengjie"
age=35
[root@worker232 yinzhengjie]#
6.2 添加主机清单
1.添加主机
[root@worker232 yinzhengjie]# cat ref-hosts-variables.yaml
- hosts: 10.0.0.231
gather_facts: no
vars:
address: 北京
tasks:
- name: t1
debug: msg="{{ name }}---{{ age }}---{{ address }}---{{ hobby }}"
[root@worker232 yinzhengjie]#
2.执行脚本
[root@worker232 yinzhengjie]# ansible-playbook ref-hosts-variables.yaml
7.在项目目录中定义变量
7.1 项目中定义变量概述
在不同的项目中添加"host_vars","group_vars"目录。
在"host_vars"目录下添加主机名或IP命名的文件,将该主机的变量写在此文件中。
在group_vars目录中添加以分组命名的文件,将改组的变量写在此文件中。
7.2
1.创建存放主机和组变量的目录
[root@worker232 yinzhengjie-apps]# mkdir group_vars host_vars
[root@worker232 yinzhengjie-apps]#
[root@worker232 yinzhengjie-apps]# ll
total 16
drwxr-xr-x 4 root root 4096 Jan 14 00:17 ./
drwxr-xr-x 3 root root 4096 Jan 14 00:17 ../
drwxr-xr-x 2 root root 4096 Jan 14 00:17 group_vars/
drwxr-xr-x 2 root root 4096 Jan 14 00:17 host_vars/
[root@worker232 yinzhengjie-apps]#
2.查看主机清单
[root@worker232 yinzhengjie-apps]# cat /etc/ansible/hosts
[k8s]
10.0.0.23[1:3]
[root@worker232 yinzhengjie-apps]#
3.定义组变量【远程主机清单存在的组】
[root@worker232 yinzhengjie-apps]# tree
.
├── group_vars
│ └── k8s
├── host_vars
│ └── 10.0.0.231
├── my-variables.yaml
└── ref-project-vars.yaml
2 directories, 4 files
[root@worker232 yinzhengjie-apps]#
[root@worker232 yinzhengjie-apps]# cat group_vars/k8s
ansible_ssh_password: 1
name: "yinzhengjie"
age: 35
[root@worker232 yinzhengjie-apps]#
4.定义主机变量【远程主机清单存在的主机】
[root@worker232 yinzhengjie-apps]# cat host_vars/10.0.0.231
hobby: "k8s"
[root@worker232 yinzhengjie-apps]#
5.自定义变量
[root@worker232 yinzhengjie-apps]# cat my-variables.yaml
address: 北京
[root@worker232 yinzhengjie-apps]#
6.引用自定义变量
[root@worker232 yinzhengjie-apps]# cat ref-project-vars.yaml
- hosts: 10.0.0.231
gather_facts: no
vars_files:
- my-variables.yaml
tasks:
- name: t1
debug: msg="{{ name }}---{{ age }}---{{ address }}---{{ hobby }}"
[root@worker232 yinzhengjie-apps]#
7.运行剧本
[root@worker232 yinzhengjie-apps]# ansible-playbook ref-project-vars.yaml
8.register注册变量
8.1 register注册变量概述
在Playbook中可以使用register将捕获命令的输出保存在临时变量中,方便后续调用此变量。
说白了,就是让前一个task的结果保存为一个变量,让后一个task去使用该变量。
8.2 register注册变量案例
1.编写剧本
[root@worker232 yinzhengjie]# cat register-variables.yaml
- hosts: 10.0.0.231
gather_facts: no
tasks:
- name: t1
shell: hostname
# 使用关键字定义一个名称为"server_name"的变量,将执行结果放在该变了中
register: server_name
- name: t2
# 调用变量
debug: msg={{ server_name }}
- name: t3
# 调用变量的多个字段
debug: msg={{ server_name.stdout }}---{{ server_name.start }}---{{ server_name.end }}
[root@worker232 yinzhengjie]#
2.运行变量
[root@worker232 yinzhengjie]# ansible-playbook register-variables.yaml -k
本文来自博客园,作者:尹正杰,转载请注明原文链接:https://www.cnblogs.com/yinzhengjie/p/18673986,个人微信: "JasonYin2020"(添加时请备注来源及意图备注,有偿付费)
当你的才华还撑不起你的野心的时候,你就应该静下心来学习。当你的能力还驾驭不了你的目标的时候,你就应该沉下心来历练。问问自己,想要怎样的人生。

浙公网安备 33010602011771号