Ansible 变量 day4

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, intersection, 
intersection_update, isalnum, 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
传递普通的key=value的形式

  # ansible all -i localhost, -m debug -a "msg='my key is {
    
    { key }}'" -e "key=value"

传递一个YAML/JSON 的形式(注意不管是YAML还是JSON,它们的最终格式一定要是一个字典)

# cat a.json
{
    
    "name":"csdn","type":"school"}

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

在这里插入图片描述

# cat a.yml
---
name: csdn
type: school
...
[root@server ~]# ansible all -i localhost, -m debug -a "msg='name is {
    
    { name }}, type is {
    
    { type }}'" -e @a.yml

name是和yaml的冲突了这里,改成name_a就行

在这里插入图片描述

2.剧本变量

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

①通过PLAY 属性 vars 定义

---
- name: test play vars 
  hosts: all
  vars:
    user: lilei
    home: /home/lilei

②通过PLAY属性vars_files定义

#当通过vars属性定义的变量很多时,这个play就会感觉特别臃肿。此时我们可以将变量单独从Play中抽离出来,
#形成单独的YAML文件。
---
- name:test play vars 
  hosts:al1
  vars files:
	- vars/users.yml
# cat vars/users.yml
---
user:lilei
home:/home/lilei

如何在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 }}"
...

YAML格式相当严谨, 当Ansible 分析YAML 文件时,有可能会误认为类似name: { { user }} 是一个字典的开始。因此加针对变量的使用,加上了双引号,避免Ansible错误解析。
在这里插入图片描述

3.资产变量

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

3.1 主机变量

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

# cat hostsandhostvars
[webservers]
192.168.1.133 user=lilei port=3309
192.168.1.134

验证

// 获取定义的变量值
# ansible 192.168.1.133  -i hostsandhostvars -m debug -a "msg='{
    
    {user}} {
    
    {port}}'"
192.168.1.133 | SUCCESS => {
    
    
    "msg": "lilei 3309"
}


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

在这里插入图片描述

3.2 主机组变量

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

# cat hostsandgroupvars
[webservers]
192.168.1.133 user=lilei
192.168.1.134

[webservers:vars]
home="/home/lilei"

验证

// home 是 web-servers 的组变量,会针对这个组内的所有服务器生效。
[root@server ~]# ansible webservers -i hostsandgroupvars -m debug -a "var=home"
192.168.1.133 | SUCCESS => {
    
    
    "home": "/home/lilei"
}
192.168.1.134 | SUCCESS => {
    
    
    "home": "/home/lilei"
}



// user 在资产中定义的是主机变量, 所以在主机 192.168.1.134 中未获取到变量user 值
[root@server ~]# ansible webservers -i hostsandgroupvars -m debug -a "var=user"
192.168.1.133 | SUCCESS => {
    
    
    "user": "lilei"
}
192.168.1.134 | SUCCESS => {
    
    
    "user": "VARIABLE IS NOT DEFINED!"
}

在这里插入图片描述

3.3 主机变量 VS 主机组变量

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

# cat hosts_v2
[webservers]
192.168.1.133 user=lilei
192.168.1.134

[webservers:vars]
user=tom

验证

// 在资产中定义了主机变量和组变量 user, 此时发现 192.168.1.133 这台机器的主机变量 user 的优先级 优于 组变量user 

[root@server ~]# ansible webservers -i hosts_v2 -m debug -a "var=user"
192.168.1.133 | SUCCESS => {
    
    
    "user": "lilei"
}
192.168.1.134 | SUCCESS => {
    
    
    "user": "tom"
}


在这里插入图片描述

3.4 变量的继承

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

# cat hosts_v3
[web-servers]
192.168.1.133

[db-servers]
192.168.1.134

[all-servers]
[all-servers:children]
db-servers
web-servers

[all-servers:vars]
user=lilei

验证

// 在资产继承的同时,对应的变量也发生了继承

[root@server ~]# ansible all-servers -i hosts_v3 -m debug -a "var=user"
[WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details
192.168.1.134 | SUCCESS => {
    
    
    "user": "lilei"
}
192.168.1.133 | SUCCESS => {
    
    
    "user": "lilei"
}

在这里插入图片描述

3.5 Inventory内置变量的说明

内置变量几乎都是以ansible_ 为前缀

[dbservers]
192.168.1.134 ansible_ssh_port=2222
ansible ssh host
	将要连接的远程主机名与你想要设定的主机的别名不同的话,可通过此变量设置.

ansible_ssh port 
	ssh端口号.如果不是默认的端口号,通过此变量设置.

ansible ssh user
	默认的ssh用户名   ,再次之前要ssh-copy-id [email protected] -p 2222

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/1oca1/bin/python3

4.Facts变量

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

4.1 手动收集Facts 变量

[root@server ~]# ansible all -i localhost, -c local -m setup
localhost | SUCCESS => {
    
    
    "ansible_facts": {
    
    
        "ansible_all_ipv4_addresses": [
            "192.168.1.133", 
            "192.168.122.1"
        ], 
        "ansible_all_ipv6_addresses": [
            "fe80::4614:18c8:50f3:43ad"
        ], 
        "ansible_apparmor": {
    
    
            "status": "disabled"
        }, 
        "ansible_architecture": "x86_64", 
        "ansible_bios_date": "07/02/2015", 
        "ansible_bios_version": "6.00", 
        "ansible_cmdline": {
    
    
            "BOOT_IMAGE": "/vmlinuz-3.10.0-957.el7.x86_64", 
            "LANG": "zh_CN.UTF-8", 
            "crashkernel": "auto", 
            "quiet": true, 
            "rd.lvm.lv": "centos/swap", 
            "rhgb": true, 
            "ro": true, 
            "root": "/dev/mapper/centos-root"
        }, 
        "ansible_date_time": {
    
    
            "date": "2020-07-11", 
            "day": "11", 
            "epoch": "1594477374", 
            "hour": "22", 
            "iso8601": "2020-07-11T14:22:54Z", 
            "iso8601_basic": "20200711T222254196782", 
            "iso8601_basic_short": "20200711T222254", 
            "iso8601_micro": "2020-07-11T14:22:54.196873Z", 
            "minute": "22", 
            "month": "07", 
            "second": "54", 
            "time": "22:22:54", 
            "tz": "CST", 
            "tz_offset": "+0800", 
            "weekday": "星期六", 
            "weekday_number": "6", 
            "weeknumber": "27", 
            "year": "2020"
        }, 
...
...
...

4.2 过滤Facts

通过刚刚的手动收集Facts,我们发现facts 信息量很大。 能不能有针对性的显示我们想要的信息呢?

可以通过使用Facts 模块中的filter参数去过滤我们想要的信息。

// 比如我想要服务器的内存情况信息
# ansible all -i localhost, -m setup -a "filter=*memory*" -c local
[root@server ~]# ansible all -i localhost, -m setup -a "filter=*memory*" -c local
localhost | SUCCESS => {
    
    
    "ansible_facts": {
    
    
        "ansible_memory_mb": {
    
    
            "nocache": {
    
    
                "free": 1142, 
                "used": 677
            }, 
            "real": {
    
    
                "free": 686, 
                "total": 1819, 
                "used": 1133
            }, 
            "swap": {
    
    
                "cached": 0, 
                "free": 2047, 
                "total": 2047, 
                "used": 0
            }
        }, 
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false
}

// 比如想要服务器的磁盘挂载情况
# ansible all -i localhost, -m setup -a "filter=*mount*" -c local

4.3 在PlayBook中去使用Facts 变量

默认情况下,在执行PlayBook的时候,它会去自动的获取每台被管理服务器的facts信息。

---
- 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   myplaybook.yml

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

---
- name: print facts variable
  hosts: all
  tasks:
   - name: print facts variable
     debug:
       msg: "The default IPV4 address is {
    
    { ansible_default_ipv4.address }}"    //字典取值

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

---
- name: a play example
  hosts: all
  # 关闭 facts 变量收集功能
  gather_facts: no
  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   myplaybook2.yml


5.注册变量

往往用于保存一个task任务的执行结果, 以便于debug时使用。或者将此次task任务的结果作为条件,去判断是否去执行其他task任务。注册变量在PlayBook中通过register关键字去实现。

myplaybook3.yml

---
- name: web
  hosts: web_server
  remote_user: root
  tasks:
    - name: install nginx
      yum: name=nginx state=present
      register: nginx      //定义变量名
    - name: print
      debug: var=nginx.changed    //变量是一个字典,读取对应值
...


---
- name: install a package and print the result
  hosts: all
  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 myplaybook3.yml

6.变量优先级

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

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

结论:全局变量 -e参数 >资产变量>playbook变量

环境准备
1、定义一份资产、且定义资产变量user

hosts

[dbservers]
192.168.1.133

[webservers]
192.168.1.134

[allservers:children]
dbservers
webservers

[allservers:vars]
user=tomcat

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

priority.yml

---
- 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"

在这里插入图片描述
在这里插入图片描述
变量优先级结论

  • 当一个变量同时在全局变量、剧本变量和资产变量中定义时,优先级最高的是全局变量;其次是剧本变量;最后才是资产变量。

猜你喜欢

转载自blog.csdn.net/qq_39578545/article/details/107256424