Ansible 变量

Ansible-变量

一、Ansible变量介绍

我们在PlayBook一节中,将PlayBook类比成了Linux中的shell。那么它作为一门Ansible特殊的语言,肯定要涉及到变量定义、控制结构的使用等特性。在这一节中主要讨论变量的定义和使用

二、变量命名规则

  • 变量的名字由字母、下划线和数字组成,必须以字母开头
# 如下变量命名为正确
good_a
ok_b

# 如下变量命名为错误:
_aaa
2_bb
  • 保留关键字不能作为变量名称
add, append, as_integer_ratio, bit_length, capitalize, center, 
clear, conjugate, copy, count, decode, denominator, difference, 
difference_update, discard, encode, endswith, expandtabs, extend, 
find, format, fromhex, fromkeys, get,has_key, hex, imag, index, 
insert, isalnum, intersection, intersection_update, isalpha, 
isdecimal, isdigit,isdisjoint, is_integer, islower,isnumeric, 
isspace, issubset, issuperset, istitle,isupper, items, iteritems, 
iterkeys, itervalues, join, keys,ljust, lower, lstrip, numerator, 
partition, pop, popitem, real,remove, replace, reverse, rfind, 
rindex, rjust, rpartition,rsplit, rstrip, setdefault, sort, split, 
splitlines, startswith,strip, swapcase, symmetric_difference, 
symmetric_difference_update,title, translate, union, update, upper, 
values, viewitems,viewkeys,viewvalues, zfill

三、变量类型

根据变量的作用范围大体的将变量分为

  • 全局变量
  • 剧本变量
  • 资产变量

但只是一个比较粗糙的划分,不能囊括 Ansible 中的所有变量。下面将分别从这三种变量入手,去介绍变量的使用。

1、全局变量

全局变量,是我们使用ansible 或使用ansible-playbook 时,手动通过 -e 参数传递给Ansible 的变量。

通过ansible 或 ansible-playbook 的 help 帮助, 可以获取具体格式使用方式

# ansible -h |grep var 
-e EXTRA_VARS, --extra-vars=EXTRA_VARS 
				set additional variables as key=value or YAML/JSON
# ansible-playbook -h |grep var 
-e EXTRA_VARS, --extra-vars=EXTRA_VARS 
				set additional variables as key=value or YAML/JSON

Example

1.1 传递普通的key=value 的形式
# ansible all -i localhost, -m debug -a "msg='my key is {{ key }}'" -e "key=value"
1.2 传递一个YAML/JSON 的形式(注意不管是YAML还是JSON,它们的 最终格式一定要是一个字典)
  • json必须双引号
  • playbook中的变量用双引号
# cat a.json
{"name":"qfedu","type":"school"}

# ansible all -i localhost, -m debug -a "msg='name is {{ name }}, type is {{ type }}'" -e @a.json
# cat a.yml
---
name: qfedu
type: school
...

# ansible all -i localhost, -m debug -a "msg='name is {{ name }}, type is {{ type }}'" -e @a.yml
2、剧本变量

此种变量和PlayBook 有关,定义在PlayBook中的。它的定义方式有多种,我们这里介绍两种最常见的定义方式。

2.1 通过 playbook 属性 vars 定义
---
- name: test play vars
  hosts: all
  vars:
    user: lilei
    home: /home/lilei
2.2 通过 playbook 属性 vars_files 定义
# 当通过vars属性定义的变量很多时,这个 Play 就会感觉特别臃肿。
# 此时我们可以将变量单独从 Play 中抽离出来,形成单独的YAML 文件。
---
- name: test play vars
  hosts: all
  vars_files:
  - vars/users.yml
# cat vars/users.yml
---
user: lilei
home: /home/lilei
2.3 如何在PlayBook中使用这些变量
  • 在PlayBook中使应变量时,使用 {{ 变量名 }} 来使用变量
---
- name: test play vars
  hosts: all
  vars:
    user: lilei
    home: /home/lilei
  tasks:
  - name: create the user {{ user }}
    user:
      name: "{{ user }}"
      home: "{{ home }}"
...
---
- name: test play vars
  hosts: all
  vars_files:
  - vars/users.yml
  tasks:
  - name: create the user {{ user }}
    user:
      name: "{{ user }}"
      home: "{{ home }}"
...
  • 在PlayBook中使用变量的注意点

PlayBook 是YAML 的文件格式, 当Ansible 分析YAML 文件时,变量如果不加上引号,有可能会误解为name: {{ user }} 是一个字典的开始。因此加针对变量的使用,加上了双引号,避免Ansible错误解析。

3、资产变量

资产共分为静态资产和动态资产。这一节中学习的资产变量,就是和资产紧密相关的一种变量。资产变量分为主机变量、组变量、父变量,分别针对资产中的单个主机和组

3.1 主机变量

以下资产中,定义了一个主机变量 lilei ,此变量只针对 172.18.0.3 这台服务器有效

# cat hostsandhostvars
[webservers]
172.18.0.3 user=lilei port=3309
172.18.0.4

验证

// 获取定义的变量值
# ansible 172.18.0.3 -i hostsandhostvars -m debug -a "msg='{{user}} {{port}}'"
172.18.0.3 | SUCCESS => {
 "user": "lilei"
}
// 未获取到定义的变量值,因为 user 这个变量针对 172.18.0.4主机无效。
# ansible 172.18.0.4 -i hostsandhostvars -m debug -a "var=user"
172.18.0.4 | SUCCESS => {
 "user": "VARIABLE IS NOT DEFINED!"
}
3.2 主机组变量

以下资产中,定义了一个组变量home ,此变量将针对webservers 这个主机组中的所有服务器有效

# cat hostsandgroupvars
[webservers]
172.18.0.3 user=lilei
172.18.0.4
[webservers:vars]
home="/home/lilei"

验证

// home 是 webservers 的组变量,会针对这个组内的所有服务器生效。
# ansible webservers -i hostsandgroupvars -m debug -a "var=home"
172.18.0.3 | SUCCESS => {
 "home": "/home/lilei"
}
172.18.0.4 | SUCCESS => {
 "home": "/home/lilei"
}
3.3 主机变量 VS 组变量

当主机变量和组变量在同一个资产中发生重名的情况,会有什么效果呢?

  • 主机变量 > 组变量 > 父组变量
# cat hosts_v2
[webservers]
172.18.0.3 user=lilei
172.18.0.4

[webservers:vars]
user=tom

验证

// 在资产中定义了主机变量和组变量 user, 此时发现 172.18.0.3 这台机器的主机变量 user 的优先级更高。
# ansible webservers -i hosts_v2 -m debug -a "var=user"
172.18.0.3 | SUCCESS => {
 "user": "lilei"
}
172.18.0.4 | SUCCESS => {
 "user": "tom"
}
3.4 变量的继承

在介绍资产时说过资产的继承,那么变量是否也存在继承关系呢?

# cat hosts_v3
[webservers]
172.18.0.3
[dbservers]
172.18.0.4
[allservers]
[allservers:children]
dbservers
webservers
[allservers:vars]
user=lilei

验证

// 在资产继承的同时,对应的变量也发生了继承
# ansible allservers -i hosts_v3 -m debug -a "var=user"
172.18.0.4 | SUCCESS => {
 "user": "lilei"
}
172.18.0.3 | SUCCESS => {
 "user": "lilei"
}
# ansible dbservers -i hosts_v3 -m debug -a "var=user"
172.18.0.4 | SUCCESS => {
 "user": "lilei"
}
# ansible webservers -i hosts_v3 -m debug -a "var=user"
172.18.0.3 | SUCCESS => {
 "user": "lilei"
}
3.5 Inventory 内置变量的说明

在/etc/ansible/hosts里面定义内置变量
内置变量几乎都是以 ansible_ 为前缀

ansible_ssh_host:
	将要连接的远程主机名.与你想要设定的主机的别名不同的话,可通过此变量设置
ansible_ssh_port:
	ssh端口号.如果不是默认的端口号,通过此变量设置
ansible_ssh_user:
	默认的 ssh 用户名,远程被管理资源的用户
ansible_ssh_pass:
	ssh 密码(这种方式并不安全,官方强烈建议使用 --ask-pass 或 SSH 密钥)
ansible_sudo_pass:
	sudo 密码(这种方式并不安全,官方强烈建议使用 --ask-sudo-pass)
ansible_sudo_exe (new in version 1.8)sudo 命令路径(适用于1.8及以上版本)
ansible_ssh_private_key_file:
	ssh 使用的私钥文件.适用于有多个密钥,而你不想使用 SSH 代理的情况.
ansible_python_interpreter:
	目标主机的 python 路径.适用于的情况(系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 /usr/local/bin/python3)
4、Facts变量

Facts变量不包含在前文中介绍的全局变量、剧本变量及资产变量之内。
Facts变量不需要我们人为去声明变量名及赋值,它的声明和赋值完全由Ansible 中的Facts模块帮我们完成。
类似于资产变量中的主机变量,它收集了有关被管理服务器的操作系统的版本、服务器的IP地址、主机名,磁盘的使用情况、CPU个数、内存大小等等有关被管理服务器的私有信息。
在每次PlayBook运行的时候都会发现在PlayBook执行前都会有一个Gathering
Facts的过程这个过程就是收集被管理服务器的Facts信息过程。

4.1 手动收集Facts变量(-c指定连接类型)
# ansible all -i localhost, -c local -m setup
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_all_ipv4_addresses": [
            "192.168.122.130"
        ], 
        "ansible_all_ipv6_addresses": [
            "fe80::f816:3eff:feb2:a261"
        ], 
        "ansible_apparmor": {
            "status": "disabled"
        }, 
        "ansible_architecture": "x86_64", 
        "ansible_bios_date": "04/01/2014", 
        "ansible_bios_version": "1.9.1-5.el7_3.1", 
        "ansible_cmdline": {
            "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-693.el7.x86_64", 
            "console": "ttyS0,115200n8", 
            "crashkernel": "auto", 
            "ro": true, 
            "root": "UUID=f70301df-8075-4f0b-823d-598a2ca015e3"
        }, 

 ...
 ...
4.2 过滤Facts变量

通过刚刚的手动收集Facts,我们发现facts 信息量很大。
能不能有针对性的显示我们想要的信息呢?   可以通过使用Facts
模块中的filter参数去过滤我们想要的信息

仅获取服务器的内存情况信息(memory)

# ansible all -i localhost, -m setup -a "filter=*memory*" -c local
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_memory_mb": {
            "nocache": {
                "free": 3504, 
                "used": 286
            }, 
            "real": {
                "free": 2950, 
                "total": 3790, 
                "used": 840
            }, 
            "swap": {
                "cached": 0, 
                "free": 0, 
                "total": 0, 
                "used": 0
            }
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

仅获取服务器的磁盘挂载情况

# ansible all -i localhost, -m setup -a "filter=*mount*" -c local
localhost | SUCCESS => {
    "ansible_facts": {
        "ansible_mounts": [
            {
                "block_available": 15318354, 
                "block_size": 4096, 
                "block_total": 15725819, 
                "block_used": 407465, 
                "device": "/dev/vda1", 
                "fstype": "xfs", 
                "inode_available": 31400058, 
                "inode_total": 31456752, 
                "inode_used": 56694, 
                "mount": "/", 
                "options": "rw,relatime,attr2,inode64,noquota", 
                "size_available": 62743977984, 
                "size_total": 64412954624, 
                "uuid": "f70301df-8075-4f0b-823d-598a2ca015e3"
            }
        ], 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}
4.3 Playbook中使用Facts变量

默认情况下,在执行PlayBook的时候,它会去自动的获取每台被管理服务器的facts信息,可以像使用其他变量一样,去使用facts 变量。

# cat 4.yaml
---
- name: a play example
  hosts: all
  remote_user: root
  tasks:
  - name: install nginx package
    yum:
      name: nginx
      state: present
  - name: copy nginx.conf to remote server
    copy: 
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
  - name: start nginx server
    service:
      name: nginx
      enabled: true
      state: started

执行

# ansible-playbook -i hosts 4.yaml
PLAY [a play example]****************************************************
# 执行 PLAYBOOK 时,自动收集 facts 信息
TASK [Gathering Facts]****************************************************
ok: [172.18.0.4]
ok: [172.18.0.3]
TASK [install nginx package]****************************************************
ok: [172.18.0.3]
ok: [172.18.0.4]
...
...

可以像使用其他变量一样,去使用 facts 变量

# cat 5.yaml
---
- name: print facts variable
  hosts: all
  tasks:
  - name: print facts variable
    debug:
      msg: "The default IPV4 address is {{ ansible_default_ipv4.address }}"

执行

# ansible-playbook -i hosts 5.yaml 
PLAY [print facts variable]*******************************************************

TASK [Gathering Facts]************************************************************
ok: [172.18.0.4]
ok: [172.18.0.3]

TASK [print facts variable]******************************************************
ok: [172.18.0.3] => {
    "msg": "The default IPV4 address is 172.18.0.3"
}
ok: [172.18.0.4] => {
    "msg": "The default IPV4 address is 172.18.0.4"
}
...
...
4.4 在PlayBook中去关闭Facts 变量的获取

若在整个PlayBook 的执行过程中,完全未使用过Facts 变量,此时我们可以将其关闭,以加快PlayBook的执行速度

# cat 6.yaml
---
- name: a play example
  hosts: all
  gather_facts: no	# 关闭 facts 变量收集功能
  remote_user: root
  tasks:
  - name: install nginx package
    yum:
      name: nginx
      state: present
  - name: copy nginx.conf to remote server
    copy: 
      src: nginx.conf
      dest: /etc/nginx/nginx.conf
  - name: start nginx server
    service:
      name: nginx
      enabled: true
      state: started

执行

# ansible-playbook -i hosts 6.yaml
PLAY [a play example]****************************************************

TASK [install nginx package]****************************************************
ok: [172.18.0.3]
ok: [172.18.0.4]
...
...
5、注册变量

注册变量往往用于保存一个 task 任务的执行结果, 以便于 debug 时使用。或者将此次 task 任务的结果作为条件,去判断是否去执行其他 task 任务。

注册变量在PlayBook中通过register关键字去实现。

cat 7.yaml
---
- name: install a package and print the result
  hosts: webservers
  remote_user: root
  tasks:
  - name: install nginx package
    yum: 
      name: nginx
      state: present
    register: install_result
  - name: print result
    debug: 
      var: install_result

执行

# ansible-playbook -i hosts 7.yaml 

PLAY [install a package and print the result] ***********************************************************************

TASK [Gathering Facts] ***********************************************************************
ok: [172.18.0.3]

TASK [install nginx package] ***********************************************************************
ok: [172.18.0.3]

TASK [print result] ***********************************************************************
ok: [172.18.0.3] => {
    "install_result": {
        "changed": false, 
        "failed": false, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "1:nginx-1.20.1-9.el7.x86_64 providing nginx is already installed"
        ]
    }
}

PLAY RECAP **********************************************************************
172.18.0.3               : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
6、变量优先级

目前介绍了全局变量、剧本变量、资产变量、Facts变量及注册变量。其中Facts变量不需要人为去声明、赋值;注册变量只需通过关键 字register去声明,而不需要赋值。而全局变量、剧本变量及资产变量则完全需要人为的去声明、赋值。变量的优先权讨论,也将着重从这三类变量去分析。

假如在使用过程中,我们同时在全局变量、剧本变量及资产变量声明了同一个变量名,那么哪一个优先级最高呢? 下面我们将以实验的形式去验证变量的优先级

环境准备

定义一份资产、且定义了资产变量user

[dbservers]
172.18.0.3
[webservers]
172.18.0.4 ansible_ssh_port=2222
[allservers:children]
dbservers
webservers
[allservers:vars]
user=tomcat

编写一份PlayBook、同样定义剧本变量user

---
- name: test variable priority
  hosts: all
  remote_user: root
  vars:
    user: mysql
  tasks:
  - name: print the user value
    debug:
      msg: 'the user value is {{ user }}'

验证测试

同时使用全局变量、剧本变量、资产变量

当变量user同时定义在全局变量、剧本变量及资产变量中时,全局变量的优先级最高。

# ansible-playbook -i hosts priority.yml -e "user=www"
PLAY [a play example] ****************************************************

TASK [Gathering Facts] ****************************************************

ok: [172.18.0.4]
ok: [172.18.0.3]
// 打印的 user 值 为www , 全局变量生效
TASK [print the user value] ****************************************************
ok: [172.18.0.3] => {
 "msg": "the user value is www"
}
ok: [172.18.0.4] => {
 "msg": "the user value is www"
}
PLAY RECAP ****************************************************

172.18.0.3 : ok=2 changed=0 unreachable=0 failed=0
172.18.0.4 : ok=2 changed=0 unreachable=0 failed=0

同时使用剧本变量和资产变量
取消全局变量,发现剧本变量的优先级要高于资产变量的优先级。

# ansible-playbook -i hosts priority.yml
PLAY [a play example] ****************************************************

TASK [Gathering Facts] ****************************************************

ok: [172.18.0.3]
ok: [172.18.0.4]
// 打印的 user 值 为mysql , 剧本变量生效
TASK [print the user value] ****************************************************
ok: [172.18.0.3] => {
 "msg": "the user value is mysql"
}
ok: [172.18.0.4] => {
 "msg": "the user value is mysql"
}
PLAY RECAP ****************************************************
172.18.0.3 : ok=2 changed=0 unreachable=0 failed=0
172.18.0.4 : ok=2 changed=0 unreachable=0 failed=0

只使用资产变量的情况

不使用全局变量、且注释掉剧本变量后,资产变量才最终生效。
---
- name: test variable priority
  hosts: all
  remote_user: root
#  vars:
#  user: mysql
  tasks:
  - name: print the user value
    debug:
      msg: 'the user value is {{ user }}'
      
# ansible-playbook -i hosts priority.yml
PLAY [a play example] ****************************************************

TASK [Gathering Facts] ****************************************************
ok: [172.18.0.3]
ok: [172.18.0.4]
// 打印的 user 值 为tomcat , 资产变量生效。
TASK [print the user value] ****************************************************
ok: [172.18.0.3] => {
 "msg": "the user value is tomcat"
}
ok: [172.18.0.4] => {
 "msg": "the user value is tomcat"
}
PLAY RECAP ****************************************************
172.18.0.3 : ok=2 changed=0 unreachable=0 failed=0
172.18.0.4 : ok=2 changed=0 unreachable=0 failed=0

变量优先级结论:

  • 当一个变量同时在全局变量、剧本变量和资产变量中定义时,优先级最高的是全局变量;其次是剧本变量;最后才是资产变量。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值