美文网首页ansible
Ansible-5 ansible变量

Ansible-5 ansible变量

作者: Habit_1027 | 来源:发表于2020-01-15 18:52 被阅读0次
    我们在PlayBook一节中,将PlayBook类比成了Linux中的shell。那么它作为一门Ansible特殊的语言,肯定要涉及到变量定义、控制结构的使用等特性。在这一节中主要讨论变量的定义和使用。
    
    
    变量命名规则

    变量的名字由字母、下划线和数字组成,以字母开头。

    如下变量命名为正确:
    good_a  OK
    ok_b    OK
    如下变量命名为错误:
    _aaa    FAIL
    2_bb    FAIL
    

    保留关键字不能作为变量名称

    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 中的所有变量。下面将分别从这三种变量入手,去介绍变量的使用
    
    
    全局变量
    全局变量,是我们使用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":"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
    
    剧本变量
    此种变量和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: all
      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 }}"
    

    在PlayBook中使用变量的注意点

    ---
    # 这里我们将上面的Playbook中引用变量的部分进行修改,去掉了双引号。
    - name: test play vars 
      hosts: all
      vars:
        user: lilei
        home: /home/lilei
      tasks:
        - name: create the user {{ user }}
          user:
            # 注意这里将 "{{ user }}" 改成了 {{ user }}
            name: {{ user }}
            home: "{{ home }}”
    

    执行以上的PlayBook 时,会出现以下错误

    The offending line appears to be:
    
          user:
            name: {{ user }}
                   ^ here
    We could be wrong, but this one looks like it might be an issue with
    missing quotes.  Always quote template expression brackets when they
    start a value. For instance:
    
        with_items:
          - {{ foo }}
    
    Should be written as:
    
        with_items:
          - "{{ foo }}"
    
    
    这样错误的主要原因是PlayBook 是YAML 的文件格式, 当Ansible 分析YAML 文件时,有可能会误认为类似
    name: {{ user }} 是一个字典的开始。因此加针对变量的使用,加上了双引号,避免Ansible错误解析。
    
    
    资产变量
    在第二章中我们学习了资产。资产共分为静态资产和动态资产。这一节中学习的资产变量,就是和资产紧密相关的一种变量。资产变量分为主机变量和组变量,分别针对资产中的单个主机和组。
    
    

    主机变量

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

    # cat inventoryandhostvars
    [web-servers]
    192.168.122.129 user=lilei
    192.168.122.131
    

    验证

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

    组变量

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

    # cat inventoryandgroupvars
    [web-servers]
    192.168.122.129 user=lilei
    192.168.122.131
    
    [web-servers:vars]
    home="/home/lilei"
    

    验证

    // user 在资产中定义的是主机变量, 所有在主机 192.168.122.131 中未获取到变量user 值
    # ansible web-servers  -i inventoryandgroupvars  -m debug -a "var=user"
    192.168.122.129 | SUCCESS => {
        "user": "lilei"
    }
    192.168.122.131 | SUCCESS => {
        "user": "VARIABLE IS NOT DEFINED!"
    }
    // home 是 web-servers 的组变量,会针对这个组内的所有服务器生效。
    # ansible web-servers  -i inventoryandgroupvars  -m debug -a "var=home"
    192.168.122.129 | SUCCESS => {
        "home": "/home/lilei"
    }
    192.168.122.131 | SUCCESS => {
        "home": "/home/lilei"
    }
    

    主机变量 VS 组变量

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

    # cat inventory_v2
    [web-servers]
    192.168.122.129 user=lilei
    192.168.122.131
    
    [web-servers:vars]
    user=cat
    

    验证

    // 在资产中定义了主机变量和组变量 user, 此时发现 192.168.122.129 这台机器的主机变量 user 的优先级
    // 优先于 组变量user 使用。
    # ansible web-servers  -i inventory_v2  -m debug -a "var=user"
    192.168.122.129 | SUCCESS => {
        "user": "lilei"
    }
    192.168.122.131 | SUCCESS => {
        "user": "cat"
    }
    

    变量继承

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

    # cat inventory_v3
    [web-servers]
    192.168.122.129
    
    [db-servers]
    192.168.122.131
    
    [all-servers]
    [all-servers:children]
    db-servers
    web-servers
    
    [all-servers:vars]
    user=lilei
    

    验证

    // 在资产继承的同时,对应的变量也发生了继承
    # ansible all-servers  -i inventory_v3  -m debug -a "var=user"
    192.168.122.131 | SUCCESS => {
        "user": "lilei"
    }
    192.168.122.129 | SUCCESS => {
        "user": "lilei"
    }
    # ansible db-servers  -i inventory_v3  -m debug -a "var=user"
    192.168.122.131 | SUCCESS => {
        "user": "lilei"
    }
    # ansible web-servers  -i inventory_v3  -m debug -a "var=user"
    192.168.122.129 | SUCCESS => {
        "user": "lilei"
    }
    
    Facts变量
    Facts变量不包含在前文中介绍的全局变量、剧本变量及资产变量之内。Facts变量不需要我们人为去声明变量名及赋值。它的声明和赋值完全有Ansible 中的Facts模块帮我们完成。类似于资产变量中的主机变量,它收集了有关被管理服务器的操作系统的版本、服务器的IP地址、主机名,磁盘的使用情况、CPU个数、内存大小等等有关被管理服务器的私有信息。假如我们足够细心的话,在每次PlayBook运行的时候都会发现在PlayBook执行前都会有一个Gathering Facts的过程。这个过程就是收集被管理服务器的Facts信息过程。
    
    

    手动收集Facts 变量

    # 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::20c:29ff:fede:b5b"
            ],
            "ansible_apparmor": {
                "status": "disabled"
            },
            "ansible_architecture": "x86_64",
            "ansible_bios_date": "07/02/2015",
            "ansible_bios_version": "6.00",
            "ansible_cmdline": {
                "KEYBOARDTYPE": "pc",
                "KEYTABLE": "us",
                "LANG": "en_US.UTF-8",
                "SYSFONT": "latarcyrheb-sun16",
                "nomodeset": true,
                "quiet": true,
                "rd_LVM_LV": "vg_mouse00/lv_root",
                "rd_NO_DM": true,
                "rd_NO_LUKS": true,
                "rd_NO_MD": true,
                "rhgb": true,
                "ro": true,
                "root": "/dev/mapper/vg_mouse00-lv_root"
            },
        ...
        ...
        ...
    

    过滤Facts

    通过刚刚的手动收集Facts,我们发现facts 信息量很大。 能不能有针对性的显示我们想要的信息呢?
    可以通过使用Facts 模块中的filter参数去过滤我们想要的信息。
    
    
    // 比如我想要服务器的内存情况信息
    # ansible all -i localhost, -m setup -a "filter=*memory*" -c local
    localhost | SUCCESS => {
        "ansible_facts": {
            "ansible_memory_mb": {
                "nocache": {
                    "free": 508,
                    "used": 473
                },
                "real": {
                    "free": 59,
                    "total": 981,
                    "used": 922
                },
                "swap": {
                    "cached": 0,
                    "free": 1981,
                    "total": 1983,
                    "used": 2
                }
            }
        },
        "changed": false
    }
    // 比如想要服务器的磁盘挂载情况
    # ansible all -i localhost, -m setup -a "filter=*mount*" -c local
    localhost | SUCCESS => {
        "ansible_facts": {
            "ansible_mounts": [
                {
                    "device": "/dev/mapper/vg_mouse00-lv_root",
                    "fstype": "ext4",
                    "mount": "/",
                    "options": "rw",
                    "size_available": 5795786752,
                    "size_total": 18435350528,
                    "uuid": "N/A"
                },
                {
                    "device": "/dev/sda1",
                    "fstype": "ext4",
                    "mount": "/boot",
                    "options": "rw",
                    "size_available": 442216448,
                    "size_total": 499355648,
                    "uuid": "N/A"
                }
            ]
        },
        "changed": false
    }
    

    如何在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
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    # 执行PLAYBOOK时,自动收集facts 信息
    TASK [Gathering Facts] **************************************************************************************************************************************************************
    ok: [192.168.122.131]
    ok: [192.168.122.129]
    
    TASK [install nginx package] ********************************************************************************************************************************************************
    ok: [192.168.122.129]
    ok: [192.168.122.131]
    ......
    ......
    

    可以像使用其他变量一样,去使用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
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    
    TASK [install nginx package] ********************************************************************************************************************************************************
    ok: [192.168.122.129]
    ok: [192.168.122.131]
    
    TASK [copy nginx.conf to remote server] *********************************************************************************************************************************************
    ok: [192.168.122.131]
    ok: [192.168.122.129]
    
    TASK [start nginx server] ***********************************************************************************************************************************************************
    ok: [192.168.122.131]
    
    注册变量
    往往用于保存一个task任务的执行结果, 以便于debug时使用。或者将此次task任务的结果作为条件,去判断是否去执行其他task任务。注册变量在PlayBook中通过register关键字去实现。
    
    
    ---
    - 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  myplaybook3.yml
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************************
    ok: [192.168.122.131]
    ok: [192.168.122.129]
    
    TASK [install nginx package] ********************************************************************************************************************************************************
    ok: [192.168.122.129]
    ok: [192.168.122.131]
    // 打印软件包安装结果
    TASK [print result] *****************************************************************************************************************************************************************
    ok: [192.168.122.129] => {
        "install_result": {
            "changed": false,
            "msg": "",
            "rc": 0,
            "results": [
                "nginx-1.12.1-1.el6.ngx.x86_64 providing nginx is already installed"
            ]
        }
    }
    ok: [192.168.122.131] => {
        "install_result": {
            "changed": false,
            "msg": "",
            "rc": 0,
            "results": [
                "nginx-1.12.2-1.el6.ngx.x86_64 providing nginx is already installed"
            ]
        }
    }
    
    PLAY RECAP **************************************************************************************************************************************************************************
    192.168.122.129            : ok=3    changed=0    unreachable=0    failed=0
    192.168.122.131            : ok=3    changed=0    unreachable=0    failed=0
    
    变量优先级
    目前介绍了全局变量、剧本变量、资产变量、Facts变量及注册变量。其中Facts变量不需要人为去声明、赋值;注册变量只需通过关键字register去声明,而不需要赋值。而全局变量、剧本变量及资产变量则完全需要人为的去声明、赋值。变量的优先权讨论,也将着重从这三类变量去分析。
    
    
    假如在使用过程中,我们同时在全局变量、剧本变量及资产变量声明了同一个变量名,那么哪一个优先级最高呢?
    下面我们将以实验的形式去验证变量的优先级
    
    

    环境准备

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

    [web-servers]
    192.168.122.129
    192.168.122.131
    
    [web-servers:vars]
    user=tomcat
    

    2、编写一份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 priority.yml -e "user=www"
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************************
    ok: [192.168.122.131]
    ok: [192.168.122.129]
    
    // 打印的 user 值 为www , 全局变量生效
    TASK [print the user value] *********************************************************************************************************************************************************
    ok: [192.168.122.129] => {
        "msg": "the user value is www"
    }
    ok: [192.168.122.131] => {
        "msg": "the user value is www"
    }
    
    PLAY RECAP **************************************************************************************************************************************************************************
    192.168.122.129            : ok=2    changed=0    unreachable=0    failed=0
    192.168.122.131            : ok=2    changed=0    unreachable=0    failed=0
    

    同时使用剧本变量和资产变量

    取消全局变量,发现剧本变量的优先级要高于资产变量的优先级。
    
    
    # ansible-playbook priority.yml
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************************
    ok: [192.168.122.129]
    ok: [192.168.122.131]
    // 打印的 user 值 为mysql , 剧本变量生效
    TASK [print the user value] *********************************************************************************************************************************************************
    ok: [192.168.122.129] => {
        "msg": "the user value is mysql"
    }
    ok: [192.168.122.131] => {
        "msg": "the user value is mysql"
    }
    
    PLAY RECAP **************************************************************************************************************************************************************************
    192.168.122.129            : ok=2    changed=0    unreachable=0    failed=0
    192.168.122.131            : 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 priority.yml
    
    PLAY [a play example] ***************************************************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************************************************************
    ok: [192.168.122.129]
    ok: [192.168.122.131]
    
    // 打印的 user 值 为tomcat , 资产变量生效。
    TASK [print the user value] *********************************************************************************************************************************************************
    ok: [192.168.122.129] => {
        "msg": "the user value is tomcat"
    }
    ok: [192.168.122.131] => {
        "msg": "the user value is tomcat"
    }
    
    PLAY RECAP **************************************************************************************************************************************************************************
    192.168.122.129            : ok=2    changed=0    unreachable=0    failed=0
    192.168.122.131            : ok=2    changed=0    unreachable=0    failed=0
    

    变量优先级结论

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

    相关文章

      网友评论

        本文标题:Ansible-5 ansible变量

        本文链接:https://www.haomeiwen.com/subject/zotxzctx.html