Bootstrap

ansible-playbook的变量定义(静态/动态扩展)

一. 简述

   在ansible 中,变量的定义和使用是 Playbook 的核心功能之一,它们使得 Playbook 更加灵活、可重用且易于维护。Ansible 支持多种方式来定义变量,包括但不限于直接在 Playbook 中定义、通过外部文件导入、从命令行传递等。

二. 变量使用方式(静态定义)

1. ansible(inventory)内置变量:

hostvars:检索主机信息(类似于setup模块,数据较多) 
inventory_hostname: 主机名
groups:  所有主机组及主机
group_names: 当前主机所属组
inventory_hostname_short: 主机名(域名时适合[如:BJCER11-18.opi.com会取BJCER11-18])
inventory_dir:主机配置文件路径
inventory_file:文件名
play_hosts:当前play范围中可用的一组主机名
role_path:当前role的目录名,只有在role中才能使用该变量
ansible_check_mode:判断检测结果是否true,需要跟--check一起使用
 
自定义(具体见之前inventory文档): 
[test]
BJCER11-18.opi.com key=tests

参考:http://docs.ansible.com/ansible/playbooks_variables.html

例如配置如下:

- hosts: test
  tasks:
      - name: copy nginx.conf
        debug: msg="hostname:{{ inventory_hostname }} groups:{{ groups }} group_names:{{ group_names }} hostneme_short:{{ inventory_hostna
me_short }} dir:{{ inventory_dir }} file:{{ inventory_dir }} play_hosts:{{ play_hosts }} check:{{ ansible_check_mode }} key:{{ key }}"

执行结果:

# ansible-playbook aaa.yaml --check
*********************************************************
ok: [BJCER11-18.opi.com] => {
    "msg": "hostname:BJCER11-18.opi.com groups:{'ungrouped': [], u'test': [u'BJCER11-18.opi.com'], 'all': [u'BJCER11-18.opi.com', u'10.5.11.11'], u'test2': [u'10.5.11.11']} group_names:[u'test'] hostneme_short:BJCER11-18 dir:/etc/ansible file:/etc/ansible play_hosts:[u'BJCER11-18.opi.com'] check:True key:tests"
}
PLAY RECAP *********************************************************************
BJCER11-18.opi.com         : ok=2    changed=0    unreachable=0    failed=0   

2. 

通过变量文件定义变量:

    ansible默认目录是/etc/ansible/ 可以通过在此目录下创建hosts_vars和group_vars目录针对主机和主机组定义变量,例如:

hosts设置如下:
# cat hosts 
[test]
BJCER11-18.opi.com

主机变量如下:
# cat host_vars/BJCER11-18.opi.com   #文件名必须匹配hosts中的主机名
---
keys: 10.5.11.18


主机组变量如下:
# cat group_vars/test #文件名必须匹配hosts中相应的分组名
---
key: nginx


playbook文件如下:
- hosts: test    
  tasks:
      - name: copy nginx.conf
        debug: msg="key={{ key }} keys:{{ keys }}"

执行结果:

TASK [copy nginx.conf] *********************************************************
ok: [BJCER11-18.opi.com] => {
    "msg": "key=nginx keys:10.5.11.18"
}
3.  通过命令行参数传入变量:
# ansible-playbook bbb.yaml -e "key=bbbbbbb keys=aaaaa"  #优先级比文件配置的高

同时命令行参数也支持文件(支持json和yaml格式)传入方式,yaml格式上面已说过,这里贴下json的:

# cat var.json 
{"key":"ccccc","keys":"ddddd"}

#执行
# ansible-playbook bbb.yaml -e "@/tmp/var.json"

4. playbook内部定义变量:

 playbook内部变量通过vars指令,如下:

---
- hosts: test
  vars:
      port: 8080
  tasks:
      - name: copy nginx.conf
        debug: msg="port:{{ port }}

也可以通过vars_files调用文件变量:

---
- hosts: test
  vars_files:
      - /tmp/var.json

5. task之间(register)传递变量:

     playbook配置中可以将一个task的结果赋值给变量, 然后下一个task调用(适用于task结果判断场景),具体通过register指令实现:

---
- hosts: test

  tasks:
      - name: req value
        shell: hostname      #执行shell命令hostname
        register: hostinfo   #结果赋值给hostinfo

      - name: copy nginx.conf
        debug: msg="value:{{ hostinfo }}"

hostinfo是一个dict数据,如只想取需要的数据,可指定相关的key(如debug: msg="value:{{ hostinfo['stdout'] }}"【同理:list的话可使用hostinfo[0]】)。

6. 通过交互(vars_prompt)方式传递变量:

  通过人机交互方式,传递变量,执行相关任务:

---
- hosts: test
  vars_prompt:           #声明prompt
      - name: "a"        #定义变量key
        prompt: "please input a value"   #前端提示
        private: no                      #是否显示输入的变量值
      - name: "b"
        prompt: "please input b value"
        default: 'sss'                   #默认值
        private: yes
  tasks:
      - name: req value
        debug: msg="a value:{{ a }}"
      - name: copy nginx.conf
        debug: msg="b value:{{ b }}"


同理:变量可同时在j2文件中引用。

7. 使用facts获取数据/变量:

     除以上之外,playbook还可以通过facts访问远程系统获取相应的参数(其实就是ansible -m setup的结果),比如取其中ansible_default_ipv4中的address信息:

---
- hosts: test
  tasks:
      - name: req value
        debug: msg="{{ ansible_default_ipv4['address'] }}" 



注:(setup的信息可通过inventory的hostvars变量获取)
也可关闭facts功能:
---
- hosts: test
  gather_facts:no

三: 动态数据/变量(lookups扩展插件)获取:

  上面所说的变量基本是定义的静态变量,同时ansible也支持(通过lookups插件)从外部获取数据。lookups主要有以下方式:

1.  lookups file:

    类似通过python的open函数,读取文件内数据,返回给变量:

# cat aaaa 
test
test2
# vim ccc.yaml 
---
- hosts: test
  vars:
      aaa: "{{ lookup('file', '/tmp/aaaa') }}"     #获取aaaa内容
  tasks:
      - name: req value
        debug: msg="{{ aaa.split('\n')[0] }}"      #获取aaa内容以‘\n’分割的第一个字符串
 
#执行结果为test

2. lookups password:

    password会对传入的内容进行加密处理:

.........
  vars:
      aaa:"{{ lookup('password','test'}}"

3. lookups pipe:

    pipe实现的原理比较简单,就是在控制机器上调用subprocessPopen命令,然后将结果赋值给变量

  vars:
      aaa: "{{ lookup('pipe','uptime') }}"

还有一些其他的扩展,感兴趣的可以自行尝试:

1)   lookups csv:  读取csv文件
2)   lookups ini : 读取ini文件
3).   lookups credstash:  密钥管理(2.0版本后) 
4).  lookups DNS:  dns解析 (1.9版本后)
5).  lookups redis_kv: 从redis get数据
6) .  lookups template: 类似file,不过读取前,需要进行渲染

有其他需求, 可自行开发相关插件!

----------------------------------------------------------------------------------------------

深耕运维行业多年,擅长linux、容器云原生、运维自动化等方面。
承接各类运维环境部署、方案设计/实施、服务代运维工作,欢迎沟通交流 !
    
​​​​​

 

;