死磕ansible系列--一文搞懂 ansible 变量配置
如何自定义变量
1 | - hosts: webservers |
可以在temple 文件中使用 {{ }}
来使用变量
1 | My amp goes to {{ max_amp_value }} |
也可以在写playbook的时候使用变量
1 | template: src=foo.cfg.j2 dest={{ remote_install_path }}/foo.cfg |
这里有个小技巧,使用变量时,要用双引号引用。
错误写法
1 | - hosts: app_servers |
正确写法
1 | - hosts: app_servers |
facts: 系统的信息
从远程节点搜集到的系统信息称为facts。facts包括远程主机的IP地址,和操作系统类型,磁盘相关信息等等。
执行下边的命令来查看都有哪些信息:
1 | - debug: var=ansible_facts |
1 | ansible test -m setup |
返回内容类似下边这样:
1 | ansible linux-node2 -m setup |head |
可以在temple模板中使用上边返回的值:
1 | {{ ansible_devices.sda.model }} |
要获取系统的主机名:
1 | {{ ansible_hostname }} |
facts会经常在条件语句及模板中使用。如,根据不同的linux发行版,执行不同的包管理程序。
关闭facts
如果你确信不需要主机的任何facts信息,而且对远程节点主机都了解的很清楚,那么可以将其关闭。远程操作节点较多的时候,关闭facts会提升ansible的性能。
只需要在play中设置如下:
1 | - hosts: whatever |
本地facts(facts.d)
如果远程节点系统上存在etc/ansible/facts.d目录,这个目录下的以.fact为后缀的文件,里面的内容可以是JSON格式,或者ini格式书写;或者是一个可以返回json格式数据的可执行文件,都可以用来提供本地facts信息。
在远程节点创建一个/etc/ansible/facts.d/preferences.fact
的文件,内容如下:
1 | mkdir -p /etc/ansible/facts.d |
在控制节点获取自定义的信息:
1 | ansible linux-node2 -m setup -a "filter=ansible_local" |
可以在playbooks或者模板中这样使用获取到的信息:
1 | {{ ansible_local.preferences.general.name }} |
linux-node2 服务器配置
1 | mkdir /etc/ansible/facts.d -p |
结果展示
1 | ansible -i inventory/ linux-node2 -m setup -a "filter=ansible_local" |
缓存 facts数据
编辑 ansible.cfg 添加如下内容,让数据缓存到redis中。
1 | [defaults] |
需要安装相关的依赖程序
1 | yum install redis |
使用facter扩展facts信息
使用过Puppet的读者都熟悉facter是Puppet里面一个负责收集主机静态信息的组件,Ansible的facts功能也一样。Ansible的facts组件也会判断被控制机器上是否安装有facter和ruby-json包,如果存在的话,Ansible的facts也会采集facter信息。我们来查看以下机器信息:
1 | ansible linux-node2 -m shell -a 'rpm -qa ruby-json facter' |
当然,如果直接运行setup模块也会采集facter信息
所有facter信息在ansible_facts下以facter_开头,这些信息的引用方式跟Ansible自带facts组件收集的信息引用方式一致。
使用ohai扩展facts信息
ohai是Chef配置管理工具中检测节点属性的工具,Ansible的facts也支持ohai信息的采集。当然需要被管机器上安装ohai包。下面介绍ohai相关信息的采集:
1 | ansible linux-node2 -m shell -a 'gem list|grep ohai' |
如果主机上没有安装ohai包,可以使用gem方式进行安装。如果存在ohai包,可以直接运行ohai模块查看ohai属性:
1 | ansible linux-node2 -m ohai |
如果直接运行setup模块,也会采集ohai信息
Registered 获取执行命令的输出
register方式用于在task之间传递变量。
在刚开始使用 ansible-playbook 做应用程序部署的时候,因为在部署的过程中有使用到 command 或 shell 模块执行一些自定义的脚本,而且这些脚本都会有输出,用来表示是否执行正常或失败。如果像之前自己写脚本做应用程序部署的,这很好实现。但现在是用 Ansible 做,那么要怎么样做可以获取到 ansible playbook 中 command 模块的输出呢? Ansible 也提供的解决办法,这时我们就可以通过使用 register 关键字来实现,register 关键字可以存储指定命令的输出结果到一个自定义的变量中,我们通过访问这个自定义变量就可以获取到命令的输出结果。Register 的使用很方便,只需要在 task 声明 register 关键字,并自定义一个变量名就可以。如下:
1 | - hosts: web_servers |
register 中存放的的数据其实是ansible stdout返回的json数据,拿到json数椐后就可以做相关使用和处理了。可以使用-v 查看上一个task的stdout 数据。
1 | - name: echo date |
这里第 1 个 task 是执行了一个 date 命令,register 关键字将 date 命令的输出存储到 date_output 变量名。第 2 个 task 对输出进行分析,并使用 when 对关键字对分析后的进行判断,如果匹配,则执行这个 task,不匹配就不执行。这里要重点说下的,因为 register 获取到的输出内容都是字符串,而 ansible 又是 python 写的,你可以使用 python 字符串的方法对其做处理,比如本文中使用的 split,还可以使用 find 方法。个人觉得,真是非常灵活方便。
注册变量
1 | register: xxx |
- xxx.stdout.find(sdf)
- xxx.stdout_lines
使用debug模块查看register中的数据
1 |
|
内置变量
ansible 默认内置了一下变量,可以直接使用。hostvars, groups, group_names, and inventory_hostname
hostvars
hostvars 是用来调用指定主机变量,需要传入主机信息,返回结果也是一个 JSON 字符串,同样,也可以直接引用 JSON 字符串内的指定信息。如果主机执行获取了 facts 数据,则hosts中将会包含 facts 中的数据。
1 | - name: Get the masters IP |
hostvars 例子
1 | { |
groups
groups 变量是一个全局变量,引用了inventory文件里所有的主机以及主机组信息 它返回的是一个json字符串。
1 | { |
playbook中通过或是的方式来引用
1 | - name: Create a user for all app servers |
1 | {% for host in groups['app_servers'] %} |
1 | etcd_initial_cluster: |- |
group_names
group_names引用当前主机所在的group的名称
1 | {% if 'webserver' in group_names %} |
1 | - name: For secure machines |
- inventory_hostname 变量保存了在设备配置清单中服务器的主机名
- inventory_hostname_short 变量跟inventory_hostname一样,只是去掉域名,比如inventory_hostname 是host.example 那么inventory_hostname_short就是host
- inventory_dir 是设备清单文件的路径
- inventory_file 是设备清单文件的文件名
通过 vars_files 指定变量文件
1 |
|
/vars/external_vars.yml
文件内容
1 |
|
使用 –extra-vars (or -e ) 命令行传入 变量
1 | ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo" |
1 | ansible-playbook release.yml --extra-vars "@some_file.json" |
1 | ansible-playbook release.yml --extra-vars '{"version":"1.23.45","other_variable":"foo"}' |
变量读取的优先级
读取顺序倒叙实现,最后一行是优先级最高的
。
- command line values (eg “-u user”)
- role defaults [1]
- inventory file or script group vars [2]
- inventory group_vars/all [3]
- playbook group_vars/all [3]
- inventory group_vars/* [3]
- playbook group_vars/* [3]
- inventory file or script host vars [2]
- inventory host_vars/* [3]
- playbook host_vars/* [3]
- host facts / cached set_facts [4]
- play vars
- play vars_prompt
- play vars_files
- role vars (defined in role/vars/main.yml)
- block vars (only for tasks in block)
- task vars (only for the task)
- include_vars
- set_facts / registered vars
- role (and include_role) params
- include params
- extra vars (always win precedence)
定义一个roles 来测试执行顺序 vim roles/test/main.yaml
1 | - debug: |
playbook 中定义 vars vim playbooks/role.yaml
1 | - hosts: "{{ target }}" |
执行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD
1 | TASK [test : debug] ************************************************************************************************************************************************************************************************** |
第二步 在roles/vars中定义变量
1 | vim test/vars/main.yaml |
执行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD
1 | TASK [test : debug] ************************************************************************************************************************************************************************************************** |
第三步 在roles文件中定义 vim roles/test/main.yaml
1 | - debug: |
执行roles ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD
1 | TASK [test : debug] ************************************************************************************************************************************************************************************************** |
第四步 命令行中使用 -e 传入变量
1 | ansible-playbook -i inventory/ -e target=localhost -e role=test playbooks/role.yaml -t test_vars -CD -e "test_vars=cmdline" |
1 | TASK [test : debug] ************************************************************************************************************************************************************************************************** |