7.1 变量来源
- inventoryfile中定义
- playbook中定义
- include文件和角色中定义变量
- 系统facts:ansible hostname -m setup
- local facts
7.2 变量的使用
复杂变量可以像字典或者数字一样访问。效果一样
{{ ansible_eth0["ipv4"]["address"] }} 或者 {{ ansible_eth0.ipv4.address }}
7.3 本地变量
ansible hostname -m setup 可以获取固定的系统facts, 在playbook中设置gather_facts:yes,playbook会自动获取远程机器的facts。
但是ansible也支持用户自定义facts,例如:
vim /etc/ansible/facts.d/preferences.fact: [general] asdf=1 bar=2
则可以使用变量 {{ ansible_local.preferences.general.asdf }},如:
7.4 魔法变量(内置变量)
- hostvars:可以让你调用其他host的变量和facts,即使你没有在这个机器上执行过playbook,你仍然可以访问变量,但是不能访问facts。例如: {{ hostvars['test.example.com']['ansible_distribution'] }}
- group_names:当前host所在的group的组名列表,包括其父组
- groups:所有组包括组中的hosts
- inventory_hostname:配置在inventory文件中当前机器的hostname
- play_hosts:执行当前playbook的所有机器的列表
- inventory_dir:inventory文件的路径
- inventory_file:inventory文件的路径和文件名
- role_path:当前role的路径
7.5 变量作用域
变量的作用域可以分为四种:
- 作用于全局的变量
- 作用于play的变量
- 作用于task的变量
- 作用于host的变量
7.5.1 作用于全局的变量
1)配置文件变量
ansible配置文件会定义一些变量信息,主要是对执行环境、连接信息变量的定义。例如inventory目录、library目录、与目的主机连接方式、越权信息、连接超时时间等等。
2)系统环境变量
在ansible连接到目的主机时,会以non-login shell登陆到目的主机,此时目的主机的/etc/bashrc和~/.basrc的环境变量会被加载,所以这两个文件中设置的环境变量会作用于playbook全局。
3)命令行变量
我们可以在执行playbook的命令行指定变量,需要注意的是,命令行指定的变量在所有其他变量中优先级是最高的。也就是说如果命令行指定的变量和其他地方指定的变量有冲突时,那么ansible最终会采用命令行定义的变量。
7.5.2 作用于play的变量
1)playbook中的变量
vars语句定义全局变量:我们可以在playbook中使用「vars」语句定义变量,该变量作用于整个play。例如:
- hosts: node1 vars: http_port: 80
引用变量文件:除了将变量写在playbook中,我们也可以将变量放在一个单独的YAML文件中,通过vars_files语句来导入。vars_files变量只能作用于play全局,不能在某个task中单独被引用。vars_files参数可以使用系统绝对路径或playbook文件的相对路径。
- hosts: node1 vars_files: ./vars-files.yaml tasks: - debug: msg: "My age is {{ age }}"
2) roles中的变量
default变量:default变量位于roles/defaults/main.yml文件中,该变量作用于role里的所有play,通常作为模版或模块里的默认参数。default变量与 ansible filter变量 {{ some_variable | default("some_value") }} 具有同样的作用,在所有ansible变量中优先级最低。
dependencies变量:dependencies变量位于roles/meta/main.yaml文件中,该变量与 role 语句同级缩进,作用于本身的 role 和 dependencies role。如:
role_A 和 role_B定义了相同的task,debug出「age」变量:
role_A/meta/main.yaml定义role_A依赖role_B,并指定「age」变量等于26:
写playbook,引用role_A:
执行结果:
输出结果显示,dependencise变量「age」在role_A和role_B均生效。
3) vars变量
vars变量位于roles/vars/main.yml,该变量作用于role里的所有模块。通常将除了默认变量的其他的变量放在这个文件内。
4) register变量
register方法能够将一个task的执行结果注册为一个变量。书写格式要与模块名称对齐,该变量作用于整个play。
7.5.3 作用于task的变量
1)playbook中的变量
with modules:我们可以为某个模块定义变量,该变量作用于这个task。
示例:为 debug模块定义了 name 和 age 变量并在 msg 参数后使用了这两个变量:
with import*/include*:在使用import_playbook、import_tasks、include_tasks、import_role、include_role时可以在import*/include*的同级位置指定变量,该变量作用于导入的所有play。
例如:playbook导入role_A,并定义变量 age , 这样 role_A 内的 play 就可以使用 age 变量了:
其他import*/include*的语句使用方法类似,只要记住缩进与import*/include*语句保持一致即可。
with roles:在playbook中使用roles语句来导入role时也可以定义变量,该变量作用于role包含的所有play。
例如:playbook使用roles语句导入role_A,并定义变量 age:
2)roles中的变量
指的是在tasks/main.yaml或handlers/main.yaml内书写task时指定的变量,该变量作用于某个task,这个变量类型与with modules类似。
7.5.4 作用于host的变量
1)系统变量Facts
facts变量:ansible中有个特殊的变量,这些变量不是开发者定义的,而是ansible根据目的主机环境信息自动收集的,称之为fact变量。
facts缓存:在执行playbook时,我们发现在「Gathering Facts」步骤时总会卡住一会,如果定义的play多了,会非常耗时。其实这步就是ansible在收集目的主机的facts信息。
如果我们定义的playbook中并没有使用到fact变量,那么我们可以选择将其关闭,只需添加「gather_facts: false」即可。
假设本地redis服务正常运行,我们只需更改ansible配置文件即可达到缓存fact的目的。
redis缓存:
[defaults] gathering = smart fact_caching = redis fact_caching_timeout = 86400
json文件缓存:
[defaults] gathering = smart fact_caching = jsonfile fact_caching_connection = /path/to/cachedir fact_caching_timeout = 86400
2)inventory中的变量
主机变量:是指作用在某一台主机上的变量。位置可以与主机定义写在一起也可以写在inventory/host_vars/a_host_name.yaml文件里。通常前者使用使用INI格式,后者使用YAML格式。
这里要注意一下YAML的语法,在 ":" 后面要留有一个空格。如果组变量和主机变量都对同一个主机定义了相同的变量,那么ansible最终会采用主机变量而放弃组变量。主机变量示例:INI格式:
转换为YAML格式:
组变量:和主机变量类似,组变量作用于主机组,即多个主机。位置可以与主机组定义写在一起也可以写在inventory/group_vars/a_group_name.yaml文件里。通常前者使用使用INI格式,后者使用YAML格式。
7.6变量的调用顺序
下面是ansible的调用变量的顺序,越靠后变量优先级越高。
- 命令行参数(非-e指定的参数,eg: "-u user -b yes")
- roles defaults目录下的变量
- 组变量:inventory 文件
- 组变量:inventory/group_vars/all
- 组变量:playbook/group_vars/all
- 组变量:inventory/group_vars/*
- 组变量:playbook/group_vars/*
- 主机变量:inventory 文件
- 主机变量:inventory/group_vars/*
- 主机变量:playbook/group_vars/*
- facts变量
- play变量:vars定义的
- play变量:vars_prompt定义的
- play变量:vars_files导入的
- roles vars目录下的变量
- block中task定义的变量
- playbook中task定义的变量
- include_vars导入的变量
- set_facts/register注册的变量
- 使用roles/include_role/import_role语句时定义的变量
- 使用include语句(ansible旧版本)时定义的变量
- 命令行-e参数指定的额外变量(优先级最高)
7.7变量的使用
7.7.1 模块使用变量
一个变量被定义后,在它的作用域内的play可以直接调用,例如:
我们定义了整个play作用域的变量「name」和「age」,那么在之后的两个debug模块内可以直接调用。如:
输出结果展示:
7.7.2 模版使用变量
变量被频繁使用的还有模板,位于templates/目录或者roles/templates/目录下,该模版使用python的Jinja2模版语法。
模版多被用于生成服务的配置文件,所以会调用很多的变量。