Playbook 基础
Playbook 的定义
在 ansible 中,我们写好 playbook,服务器作演员,由服务器根据我们编排的剧本,完成环境安装,服务部署,系统搭建,状态检测等各种各样的功能。
在 ansible 中,较简单的任务,我们可以直接调用单个模块来完成,但是,如果遇到复杂的需求,需要 调用大量模块才能完成一个需求,或多个任务间有依赖的时候,使用单条命令就特别不方便,这种情况 下,我们就可以使用 playbook 来实现这种需求
module (模块) 与 Playbook 的区别
-
Playbook 是对多个 AD-Hoc 的一种编排组合的实现方式
-
Playbook 能控制任务执行的先后顺序
-
Playbook 可以持久保存到文件中从而方便多次调用运行,而 Ad-Hoc 只能临时运行
-
Playbook 适合复杂的重复性的任务,而 Ad-Hoc 适合做快速简单的一次性任务
playbook 文件规范
-
扩展名为 yaml 或 yml
-
第一行用 “---” (英文输入法下的中划线) 表示 yaml 的开始,一般不写,如果有多个 yaml 文件合 并,则可用此标识每个 yaml 文件内容
-
使用#作为注释
-
大小写敏感
-
缩进符要统一,用空格键缩进,不要用 tab 缩进空格的数量不重要,但是,相同层级的左边缩进,要保持一致,要对齐,就是说,同样的缩 进,代表同样的级别
-
使用 “-”(英文输入法下的中划线)+一个空格来表示单个列表项
-
使用 ”:”(冒号)+空格来表示一个键值对
-
使用“{}”(花括号) 来表示一个键值表
-
一个 name 只能有一个 task
YAML 语言
YAML 语言基础和特性
YAML: YAML Ain't Markup Languag,YAML不是一种标记性语言,实际上在开发这种语言的时候, YAML 的意思其实是:Yet Another Markup Language (YAML仍然是一种标记性语言)。
YAML 是一个可读性高的用来表达资料序列的格式。是目前较流行的配置文件格式,很多新的项目或者 软件都采用 yaml 文件来保存配置信息,例如 ubuntu,ansible,doker,kubernets 等。
YAML 语言特点
-
YAML的可读性好
-
YAML和脚本语言的交互性好
-
YAML使用实现语言的数据类型
-
YAML有一个一致的信息模型
-
YAML易于实现
-
YAML可以基于流来处理
-
YAML表达能力强,扩展性好
YAML 语言语法
-
在单一文件第一行,用连续三个连字号 "-" 开始,还有选择性的连续三个点号( ... )用来表示文件的结尾
-
次行开始正常写 Playbook 的内容,一般建议写明该 Playbook 的功能
-
使用#号注释代码
-
缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
-
缩进不支持 tab,必须使用空格进行缩进
-
缩进的空格数不重要,只要相同层级的元素左对齐即可
-
YAML文件内容是区别大小写的,key/value 的值均需大小写敏感
-
多个 key/value 可同行写也可换行写,同行使用,分隔
-
key 后面冒号要加一个空格 比如 key: value
-
value 可是个字符串,也可是另一个列表
-
YAML 文件扩展名通常为 yml 或 yam
YAML 中的数据类型
YAML 支持以下常用几种数据类型
数据类型 | 备注 |
---|---|
标量 | 单个的、不可再分的值 |
对象 | 键值对的集合,又称为 字典(dictionary)/ 哈希(hashes) / 映射(mapping) |
数组 | 一组按次序排列的值,又称为 列表(list)/ 序列(sequence) |
scalar 标量
标量是最基本的,不可再分的值,包括 字符串,布尔值,整数,浮点数,Null,时间,日期等类型
#两种写法
#第一种
name: tom
age: 18
#第二种
name:
tom
age:
18
name,tom,age,18 都是标量
Dictionary 字典
-
一个字典是由一个或多个key与value构成
-
key 和 value 之间用冒号 :分隔
-
冒号 : 后面有一个空格
-
所有 k/v 可以放在一行,每个 k/v 之间用逗号分隔
-
所有每个 k/v 也可以分别放在不同行,一对 k/v 放在独立的一行
#单行写法
cat: { name: tom, age: 18 }
#多行缩进写法
cat:
name: tom
age: 18
List 列表
-
列表由多个元素组成
-
每个元素放在不同行,每个元素一行,且元素前均使用中横线 - 开头,并且中横线 - 和元素之间有 一个空格
-
也可以将所有元素用 [ ] 括起来放在同一行每个元素之间用逗号分隔
#单行写法
baidu: [linux,golang,python]
#多行写法
baidu:
- linux
- golang
- python
三种常见的数据格式
-
XML:Extensible Markup Language,可扩展标记语言,可用于数据交换和配置
-
JSON:JavaScript Object Notation,JavaScript 对象表记法,主要用来数据交换或配置,不支持注释
-
YAML:YAML Ain't Markup Language,YAML 不是一种标记语言, 主要用来配置,大小写敏感,不支持 tab
Playbook 的构成
playbook 是由一个或多个 “play” 组成的列表。playbook 的主要功能在于,将多个 play 组织在一个 playbook 文件中,让多台预定义的主机按照 playbook 中编排的内容来完成一系列复杂的功能。
一个 playbook 至少要包含 name 和 tasks 两部份。
主要有以下几部份构成
-
facts 默认会自动调用的模块,获取远程主机的一些信息,可以在下面的任务中使用,相当于构造函数,可以禁用;
-
hosts 指定要执行任务的远程主机,其值可以是通配符,主机或组,但一定是要在主机清单中定义 过的(/etc/ansible/hsots),可以用 -i 选项指定自定义的主机清单文件;
-
remote_user 指定任务在远程主机上执行时,所使用的用户,可以是任意用户,也可以 sudo,但前提是用户是存在的,默认 root,可以不写;
-
variables 定义 playbook 运行时需要的使用的变量,有多种定义方式;
-
templates 模板模块,配合变量,模板文件,可以实现批量执行时,在不同主机上用同一个模板生 成不同配置文件的功能;
-
tasks 定义要在远程主机上执行的任务列表,各任务按顺序在 hosts 中指定的主机上执行,即所有主机做完当前任务,才会开始下一个任务。task 的模式是执行指定模块,后面跟上预定的参数,参数中可以使用变量,模块的执行是幂等的,这意味着多次执行是安全的,因为其结果均一致,如果在执行过程中发生错误,则会全部回滚(包括前面己执行成功的);每个task 都应该定义name,用于执行结果的输出,如果没有指定 name ,则 action 的结果将用于输出;
-
tags 定义哪些代码内容可以被忽略,就是用 tags 跳过部份代码;
-
notify/handlers 一般配合使用, 可以达到一种触发调用的效果,(类似于函数调用或触发器)。
#默认yes,会收集远程主机信息,在最开始调用,后面的task 中可以使用此处收集的信息
- gather_facts: no
#hosts 必须是己在主机清单中定义的主机或IP
- hosts: 10.0.0.206 #IP写法
- hosts: node.linux-baidu.com #主机名写法
- hosts: group1 #分组写法
- hosts: group1:group2 #分组写法,或者关系,两个分组并集
- hosts: group1:&group2 #分组写法,与关系,两个分组交集
- hosts: group1:!group2 #分组写法,非关系,两个分组差集
#remote_user 可以全局指定,也可以在特定 task 中指定,默认是在远程主机上以 root 身份执行,默认不写此项,切换用户执行需要先完成登录校验或者用 -k 选项手动输入ssh 密码
- hosts: group1 #指定主机分组
gather_facts: no #不收集主机信息
remote_user: tom #远程执行用户
tasks: #task 列表
- name: task1 #task 名称,此 task 以 tom 身份认行
shell: id #具体执行的模块 和参数
- name: task2 #task 名称,此 task 以 jerry 身份连接主机执行
shell: id #具体执行的模块 和参数
remote_user: jerry
#task 两种定义方式
#action: module arguments
#module: arguments
#如果是 shell 模块或 command 模块,后面是跟命令,而不是 key=val 写法
- hosts: group1 #指定主机分组
gather_facts: no #不收集主机信息
tasks: #task 列表
- name: task1 #task 名称
action: shell id #具体执行的模块和参数,执行shell 模块,参数是id
- name: task2 #task 名称
command: id #具体执行的模块和参数,执行 command 模块,参数是 id
- name: task3 #task 名称
debug: msg="task3" #非 shell,非 command 模块,后面是 key=val 格式
Playbook 命令
ansible-playbook 命令
ansible-playbook <filename.yml> ... [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 #列出plabook中所有 task
-v--verbose #显示详细信息,最多可以写 vvvvv
[root@ubuntu24 ~]# cat hello.yaml
- hosts: 10.0.0.161 #指定主机或分组
gather_facts: no #不收集主机信息
remote_user: root #远程执行用户
tasks: #task 列表
- name: task-cmd #task 名称
command: echo "hello ansible" #具体执行的模块 和参数
- name: task-shell #task 名称
shell: id #具体执行的模块和参数
remote_user: tom #指定模块的执行用户
#语法检查
[root@ubuntu24 ~]# ansible-playbook --syntax-check hello.yaml
playbook: hello.yaml
[root@ubuntu24 ~]# echo $?
0
#模拟执行
[root@ubuntu24 ~]# ansible-playbook -C hello.yaml
PLAY [10.0.0.161] ***********************************************************************************************************************************************************************
TASK [task-cmd] *************************************************************************************************************************************************************************
skipping: [10.0.0.161]
TASK [task-shell] ***********************************************************************************************************************************************************************
skipping: [10.0.0.161]
PLAY RECAP ******************************************************************************************************************************************************************************
10.0.0.161 : ok=0 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
#OK=0 #0个task 执行成功
#change=0 #0个task 都导致了系统状态发生了改变,如果是查询类task,可以在playbook文件中加上 changed_when:false
#unreachable=0 #0个task不可达
#failed=0 #0个task执行失败
#skipped=2 #跳过2个task
#rescued=0 #0个task被拒绝执行
#ignored=0 #忽略0个task
ansible-vault 文档加解密命令
ansible-vault [-h] [--version] [-v]
{create,decrypt,edit,view,encrypt,encrypt_string,rekey} ...
#子命令
create #新建加密文件
decrypt #去掉加密文件密码
edit #编辑
view #查看
encrypt #加密文件
rekey #修改口令
#创建新文件
[root@ubuntu ~]# ansible-vault create test2.yaml
New Vault password:
Confirm New Vault password:
#无法直接查看
[root@ubuntu ~]# cat test2.yaml
$ANSIBLE_VAULT;1.1;AES256
32376637343036353361616236333233393536366138633265616564646132373734323431666162
3531666333393065656234656563386133356237623030300a663663363263643130323335333065
38383663643465363136653634383431336566663435656631343339373666383839353233323863
6636306237343863610a636431616533333361393365646537396332383239326135363339323666
32346335626563336538353134303861313566336163643136343830356537386362346438643561
35316234326364653232393763633234313565313062373437663733356539383737616436336233
63646361343936656231613862323332633739396632373036393161313730383133386430313061
33646532343663613664
#输入密码后查看
[root@ubuntu ~]# ansible-vault view test2.yaml
Vault password:
- name: vault-test
hosts: localhost
tasks:
- name: task-1
shell: echo "hello"
#输入密码后编辑
[root@ubuntu ~]# ansible-vault edit test2.yaml
Vault password:
#去掉密码保护
[root@ubuntu ~]# ansible-vault decrypt test2.yaml
Vault password:
Decryption successful
#加密执行,指定密码文件
[root@ubuntu ~]# ansible-playbook --vault-password-file pwd.txt test2.yaml
创建用户和组
[root@ubuntu ~]# cat mysql_user.yaml
--- #create mysql group and user
- hosts: rocky,ubuntu
gather_facts: no
tasks:
- name: create group
group: name=mysql system=yes gid=306
- name: create user
user: name=mysql system=yes group=mysql uid=306 shell=/sbin/nologin home=/data/mysql create_home=no
#指定主机执行
[root@ubuntu ~]# ansible-playbook -l 10.0.0.150 mysql_user.yaml
安装 nginx
[root@ubuntu ~]# cat install_nginx.yaml
--- #install nginx
- hosts: rocky
gather_facts: no
tasks:
- name: install nginx
yum:
name: nginx
state: present
- name: set page
copy:
src: ./test.html
dest: /usr/share/nginx/html/index.html
- name: start service
service: name=nginx state=started enabled=yes
[root@ubuntu ~]# cat test.html
<h1>this page from ansible</h1>
#执行
[root@ubuntu ~]# ansible-playbook -l 10.0.0.151 ./install_nginx.yaml
#升级版
[root@ubuntu ~]# cat nginx_v2/install_nginx_v2.yaml
--- #install nginx -v2
- hosts: rocky
gather_facts: no
tasks:
- name: install nginx
yum: name=nginx state=present
- name: config file
copy: src=/root/nginx_v2/linux.baidu.com.conf dest=/etc/nginx/conf.d/
- name: create dir
file: path=/usr/share/nginx/html/linux.baidu.com/ state=directory owner=nginx group=nginx
- name: set page
copy: src=/root/nginx_v2/index.html dest=/usr/share/nginx/html/linux.baidu.com/ owner=nginx group=nginx
- name: start service
service: name=nginx state=restarted enabled=yes
#域名配置文件
[root@ubuntu ~]# cat nginx_v2/linux.baidu.com.conf
server{
listen 80;
server_name linux.baidu.com;
root /usr/share/nginx/html/linux.baidu.com;
}
[root@ubuntu ~]# ansible-playbook -l 10.0.0.213 ./nginx_v2/install_nginx_v2.yaml
#修改本地 hosts 文件
[root@ubuntu ~]# echo '10.0.0.213 linux.baidu.com' >> /etc/hosts
#测试
[root@ubuntu ~]# curl linux.baidu.com
Playbook 中的 nofify 和 handlers
notify 和 handlers
Handlers 本质上也是 task list,也定义了一系列的 task,每个 task 中同样调用指定模块执行操作,只 不过 Handlers 中定义的 task,不会主动执行,需要配合 notify,让 notify 通知相应的 Handers 中的 task,该 task 才会执行,而且,Handers 中的 task,是在 playbook的 tasks 中所有的 task 都执行完成 之后才调用,这样是为了避免多次触发同一个 Hander 导致多次调用。
notify 配合 handlers,可以实现在特定条件下触发某些操作,特别适用于类似于服务重启,重载等场景。
注意
-
如果多个 task 通知了相同的 handlers, 此 handlers 仅会在所有 task 结束后运行一 次。
-
只有 notify 对应的 task 发生改变了才会通知 handlers, 没有改变则不会触发 handlers
-
handlers 是在所有前面的 tasks 都成功执行才会执行,如果前面任何一个 task 失败,会导致 handler 跳过执行
示例:当文件发生变化时,重启服务
[root@ubuntu ~]# cat nginx_v2/notify.yaml
--- #install nginx -v2
- hosts: rocky
gather_facts: no
tasks:
- name: config file
copy: src=/root/nginx_v2/linux.baidu.com.conf dest=/etc/nginx/conf.d/
notify: restart service #当配置文件发生了变化时,通知重启服务
handlers: #handlers中的操作,要等到所有 task 执行完成之后才会被调用,而且对于同一个handler,多个notify,也只会执行一次
- name: restart service
service: name=nginx state=restarted
一个 task 中可以调用多个 handler,但多处调用同一个 handler,该 handler 只会执行一次
force_handlers 强制执行 handlers
在 task 中使用 notify 来调用 handlers 中的任务,如果该 task 执行失败,或者在该 task 之前的其它 task 执行失败,则会导致 notify 通知的 handlers 中的任务不会被调用,想要保证 handlers 中的 task 一定会被调用,则可以用 force_handlers 强制指定。
注意:force_handlers 是以整个 playbook 的角度来理解的,在 playbook 中,如果有 task 执行失败, 那整个 playbook 也执行失败,即使有部份 task 执行成功,这部份 task 对应的 handlers 也不会被执 行,force_handlers 保证的是己成功执行的 task 对应的 handlers 一定会被执行。
#force_handlers 可以保证 handlers-1 被执行
[root@ubuntu ~]# cat force_handlers-v3.yaml
--- #force_handlers-v3
- hosts: localhost
gather_facts: no
force_handlers: yes
tasks:
- name: task-1
shell: echo "task-1"
notify: handlers-1
- name: task-2
shell: echoooooo "task-2"
notify: handlers-2
handlers:
- name: handlers-1
debug: msg="handlers-1"
- name: handlers-2
debug: msg="handlers-2"
忽略错误 ignore_erros
在同一个 playbook中,如果一个 task 出错,则默认不会再继续执行后续的其它 task,利用 ignore_errors: yes 可以忽略此 task 的错误,继续执行其它 task,此项也可以配置为全局选项。
[root@ubuntu ~]# cat ignore_errors.yaml
--- #ignore err
- hosts: rocky
gather_facts: no
tasks:
- name: task-1
shell: echo "task-1"
- name: task-2
shell: echoooo "task-2"
ignore_errors: yes #忽略此 task 错误
- name: task-3
shell: echo "task-3"
#也可以直接配置全局忽略
- hosts: rocky
gather_facts: no
ignore_errors: yes #配置全局忽略
Playbook 中的 tags
默认情况下, Ansible 在执行一个 playbook 时,会执行 playbook 中所有的任务,在 playbook 文件 中,可以利用 tags 组件,为特定 task 指定标签,当在执行 playbook 时,可以只执行特定 tags 的 task,而非整个 playbook 文件。
可以一个 task 对应多个 tag,也可以多个 task 对应同一个 tag
还有三个内置的 tag,all 表示所有任务,tagged 表示所有被 tag 标记的任务,untagged 表示所有没有 被标记的任务。
tags 主要用于调试环境
[root@ubuntu ~]# cat tags.yaml
--- #tags
- hosts: 127.0.0.1
gather_facts: no
tasks:
- name: task-1-tag1-tag11
shell: echo "task-1"
tags: [tag1,tag11]
- name: task-2-tag1-tag2
shell: echo "task-2"
tags: [tag1,tag2]
- name: task-3-tag3
shell: echo "task-3"
tags: [tag3]
- name: task-4-no-tags
shell: echo "task-4"
#执行特定 tags
[root@ubuntu ~]# ansible-playbook tags.yaml -t tag1
#跳过特定tag
[root@ubuntu ~]# ansible-playbook tags.yaml --skip-tags tag1
#执行所有任务,相当于 ansible-playbook tags.yaml
[root@ubuntu ~]# ansible-playbook tags.yaml -t all
#不执行任何任务
[root@ubuntu ~]# ansible-playbook tags.yaml --skip-tags all
#只执行有 tag 的 task
[root@ubuntu ~]# ansible-playbook tags.yaml -t tagged#只执行有 tag 的 task
#跳过所有有 tag 的 task
[root@ubuntu ~]# ansible-playbook tags.yaml --skip-tags tagged
#只执行没有 tag 的 task
[root@ubuntu ~]# ansible-playbook tags.yaml -t untagged
#跳过所有没有 tag 的 task
[root@ubuntu ~]# ansible-playbook tags.yaml --skip-tags untagged
Playbook 中的变量
playbook 支持变量的定义与引用
playbook 中的变量名由数字字母下划线组成,区分大小写,且只能以字母开头;
#变量定义
var1=value
var2: value
#示例
http_port=80
ssh_port: 22
使用变量
通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,在某些情况下需要加双引号,写成 "{{ variable_name }}" 才生效
变量来源
-
使用 setup facts 获取的远程主机的信息都是放在变量中的,可以直接使用
-
在命令行执行 ansible-playbook 时,可以使用 -e 选项设置变量,这种变量的优先级最高
-
在 playbook 文件中定义变量
-
在单独的变量文件中定义变量,再在 playbook 中引用该文件
-
在主机清单文件中定义,当单独主机的变量与分组的变量有冲突时,单独定义的主机的变量,优先级更高
-
在主机变量目录(host_vars)和主机分组目录(group_vars)中创建以主机名或分组名为文件名的文 件,在该文件中定义
-
使用 register 将其它 task 或模块的执行的输出内容保存到变量中,供别的 task 来使用
-
在 role 中定义
变量优先级
-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名 文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组 变量
使用 setup 模块中的变量
在命令行下,可以通过指定 setup 模块的方式获取目标主机信息
ansible 127.0.0.1 -m setup
在 playbook 中,可以使用 gather_facts 选项来获得目标主机的信息,该选项默认是 yes ,每次执行都 需要消耗一定的资源和时间,在不需要时可以禁用该项来加快 playbook 的执行效率,另外,目标主机 的信息也可以保存在本地做缓存,以便在频繁执行时减少资源消耗。
[root@ubuntu ~]# cat facts-v1.yaml
--- #get facts
- hosts: rocky
gather_facts: yes
tasks:
- name: show-facts
debug: msg={{ ansible_facts }}
- name: show-facts-hostname
debug: msg={{ ansible_hostname }}
- name: show-facts-ipv4-A
debug: msg={{ ansible_facts["eth0"]["ipv4"]["address"] }}--{{ ansible_facts.eth0.ipv4.address }}
- name: show-facts-ipv4-B
debug: msg={{ ansible_eth0["ipv4"]["address"] }}--{{ ansible_eth0.ipv4.address }}
- name: show-facts-ipv4-C
debug: msg={{ ansible_default_ipv4["address"] }}--{{ ansible_default_ipv4.address }}
#多种写法
{{ ansible_facts["eth0"]["ipv4"]["address"] }}
{{ ansible_facts.eth0.ipv4.address }}
{{ ansible_eth0["ipv4"]["address"] }}
{{ ansible_eth0.ipv4.address }}
{{ ansible_default_ipv4["address"] }}
{{ ansible_default_ipv4.address }}
#分组内的主机网卡名称要保持一致
facts 配置说明
在 ansible-playbook 中,facts 信息收集默认是开启的,如果不需要,则要在 playbook 中显式指定, 关闭后执行性能更好
- hosts: all
gather_facts: no
#如果需要收集远程主机的信息,那么合理的配置 facts 信息的本地缓存策略,也能加速性能
[root@ubuntu ~]# cat /etc/ansible/ansible.cfg
[defaults]
gathering = smart|implicit|explicit #facts 策略,默认 smart,新版默认implicit
fact_caching_timeout = 86400 #本地缓存时长,默认86400S
fact_caching = memeory|jsonfile|redis #缓存类型,默认 memory,如果是jsonfile,则需要指定文件路径
fact_caching_connection = /path/to/cachedir #本地缓存路径
#smart 远程主机信息如果有本地缓存,则使用缓存,如果没有,就去抓取,再存到缓存中,下次就直接使用缓存信息
#implicit 不使用缓存,每次都抓取新的
#explicit 不收集主机信息,除非在playbook 中用 gather_facts: yes 显式指定
#fact_caching=memory,表示只在当前有效,下次还是要重新抓取,是默认值,所以如果需要缓存相关内容,需要指定 josnfile 或 redis
#fact_caching=redis 时,fact_caching_connection=REDIS_IP:REDIS_PORT:REDIS_DB_NUMBER[:REDIS_PASSWORD]
#fact_caching_connection=10.0.0.100:6379:0
#fact_caching_connection=10.0.0.100:6379:0:123456
#配置 facts 信息本地缓存
[root@ubuntu ~]# cat /etc/ansible/ansible.cfg
gathering=smart
fact_caching=jsonfile
fact_caching_connection=/tmp/ansible-facts/
fact_caching_timeout=30
[root@ubuntu ~]# cat facts.yaml
--- #get facts
- hosts: rocky
tasks:
- name: show-facts
debug: msg={{ ansible_hostname }}
[root@ubuntu ~]# ansible-playbook facts.yaml
#缓存了当前主机的相关信息
[root@ubuntu ~]# tree /tmp/ansible-facts/
/tmp/ansible-facts/
├── 10.0.0.150
└── 10.0.0.213
在命令行中定义变量
[root@ubuntu ~]# cat var1.yaml
--- #var1
- hosts: rocky
gather_facts: no
tasks:
- name: show-val
debug: msg={{ uname }}--{{ age }}
- name: notify
shell: echo "123"
notify: handler-1
handlers:
- name: handler-1
debug: msg={{ gender }}
#直接在命令行中指定
[root@ubuntu ~]# ansible-playbook -e uname=tom -e age=18 -e gender=M var1.yaml
#多个变量一次定义
[root@ubuntu ~]# ansible-playbook -e "uname=tom age=18 gender=M" var1.yaml
#从文件中读取
[root@ubuntu ~]# cat var.txt
uname: jerry
age: 20
gender: F
#文件前面要加 @
[root@ubuntu ~]# ansible-playbook -e "@/root/var.txt" var1.yaml
在 playbook 文件中定义变量
在 playbook 文件中定义的变量,只能在当前 playbook 中使用,属于私有变量
[root@ubuntu ~]# cat var2.yaml
--- #var2
- hosts: rocky86
gather_facts: no
vars:
uname: tom
age: 20
gender: F
tasks:
- name: show-val
debug: msg={{ uname }}--{{ age }}
- name: notify
shell: echo "123"
notify: handler-1
handlers:
- name: handler-1
debug: msg={{ gender }}
#命令行中变量的优先级最高,会替换文件中的变量
[root@ubuntu ~]# ansible-playbook -e "uname=jerry age=30 gender=M" var2.yaml
在单独文件中定义变量
在单独的变量文件中定义变量,再在 playbook 中引用该文件,在单独文件中定义的变量优先级比在 playbook 中定义的变量优先级高
- hosts: 127.0.0.1
gather_facts: no
vars_files:
- var4_file_start.yaml #相对路径写法
- /root/var4_file_end.yaml #绝对路径写法
#命令行变量优先级最高,变量文件次之
在主机清单中定义变量
[all:vars]
var1=all-var1
var2=all-var2
var3=all-var3
[group1:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_password='123456'
var2=group1-var2
var3=group1-var3
[root@ubuntu ~]# cat var5.yaml
--- #var5
- hosts: all
gather_facts: no
tasks:
- name: show-vars
debug: msg={{ var1 }}---{{ var2 }}---{{ var3 }}
#测试
ok: [10.0.0.166] => {
"msg": "all-var1---group1-var2---group1-var3" #分组变量优先级更高
在项目目录中定义变量
在不同的项目中添加 host_vars,group_vars 目录,在 host_vars 目录下添加主机名或 ip 命名的文 件,将该主机的变量写在此文件中,在 group_vars 目录中添加以分组命名的文件,将该组的变量写在 此文件中。
在host_vars 目录中定义的变量优先, group_vars 次之,hosts 最次之
register 注册变量
在 playbook 中可以使用 register 将捕获命令的输出保存在临时变量中,方便后续调用此变量。
[root@ubuntu 0209]#cat var8.yaml
- hosts: 10.0.0.166
gather_facts: no
tasks:
- name: register
shell: hostname
register: hostname_rs
- name: reg-rs-all
debug: msg={{ hostname_rs }}
- name: reg-rs
debug: msg={{ hostname_rs.stdout }}
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Ansible 中的 Playbook
发表评论 取消回复