06_Ansible: Variable、合法的变量名、在Inventory中定义变量、关于Jinja2、Facts、访问复杂变量数据、魔法变量、命令行中传递变量、变量的优先级

9.Variable
9.1.合法的变量名
9.2.在Inventory中定义变量
9.3.在playbook中定义变量
9.4.在文件和role中定义变量
9.5.使用变量:关于Jinja2
9.6.Jinja2过滤器
9.7.YAML陷阱
9.8.使用Facts获取的信息
9.9.关闭Facts
9.10.本地Facts(Facts.d)
9.11.Fact缓存
9.12.注册变量
9.13.访问复杂变量数据
9.14.魔法变量, 以及如何访问其它主机的信息
9.15.变量文件分割
9.16.命令行中传递变量
9.17.变量的优先级:我该在什么地方放置变量?

9.Variable

转自:https://ansible-tran.readthedocs.io/en/latest/docs/playbooks_variables.html

已经存在的自动化技术使得重复做事变得更加容易,但你的所有系统有时则不会这样. 在有些系统中你想设置一些行为或者配置,这与其它系统稍有不同.

并且,远程系统的可视行为或状态会影响我们配置这些系统.(比如你需要得到一个系统的IP地址,甚至用该值来配置另一个系统).

你可能有一些非常相似的模板或配置文件,而有些变量则稍微不同. Ansible中的变量用来处理系统间的不同.

为了理解变量,你也需要深入阅读 条件选择 和 循环.有用的模块(比如”group_by”模块和”when”条件)也可以结合变量使用,用于管理系统间的不同之处.

强烈建议你学习 ansible-examples github代码库,里面有大量使用变量的例子.

9.1.合法的变量名

在使用变量之前最好先知道什么是合法的变量名. 变量名可以为字母,数字以及下划线.变量始终应该以字母开头. “foo_port”是个合法的变量名.”foo5”也是. “foo-port”, “foo port”, “foo.port” 和 “12”则不是合法的变量名.

9.2.在Inventory中定义变量

我们已经在其它文档中覆盖了大量关于使用变量的场景,所以这里没多少新的知识点,权当加深记忆.

通常你想基于一个机器位于哪个群组而设置变量.比如,位于波士顿的很多机器会使用 ‘boston.ntp.example.com’ 作为NTP服务器.

请看 Inventory(https://ansible-tran.readthedocs.io/en/latest/docs/intro_inventory.html)文件 文档来学习在inventory中使用多种方式来定义变量.

9.3.在playbook中定义变量

在playbook中,可以直接定义变量,如下所示:

- hosts: webservers
  vars:
    http_port: 80

这种所见即所得的方式非常好。

9.4.在文件和role中定义变量

事实上在其它地方我们也讲过这点了. 正如在 Playbook 角色(Roles) 和 Include 语句 描述的一样,变量也可以通过文件包含在playbook中,该变量可以作为或者不作为“Ansible Role”的一部分.使用role是首选,因为它提供了一个很好的组织体系.

9.5.使用变量:关于Jinja2

我们已经知道很多关于定义变量的知识,那么你知道如何使用它们吗?

Ansible允许你使用Jinja2模板系统在playbook中引用变量.借助Jinja你能做很多复杂的操作,首先你要学习基本使用. 例如,在简单的模板中你可以这样做:

My amp goes to {
    
    {
    
     max_amp_value }}

这就是变量替换最基本的形式. 你也可以在playbook中直接这样用,你偶尔想这样做:

template: src=foo.cfg.j2 dest={
    
    {
    
     remote_install_path }}/foo.cfg

In the above example, we used a variable to help decide where to place a file. 在上述的例子中,我们使用变量来决定文件放置在哪里. 在模板中你自动会获取在主机范围之内的所有变量的访问权.事实上更多,你可以读取其它主机的变量.我们将演示如何做.

在模板中Jinja2可以用循环和条件语句,而在playbook中则不行.Ansible playbook是纯粹的机器解析的YAML.这是一个非常重要的功能,这意味着根据文件可以生成代码,或者其它系统工具能够读取Ansible文件.虽然并不是所有人都需要这个功能,但我们不能封锁可能性.

9.6.Jinja2过滤器

Jinja2中的过滤器可以把一个模板表达式转换为另一个.Jinja2附带了很多这样的功能.请参见Jinja2官方模板文档中的 builtin filters.

另外,Ansible还支持其它特性.请看 playbooks_filters 文档中关于一系列可用的过滤器及示例.

注意:
这并不是常用的特性.只在合适的时候使用它们,这是一个附加知识点.

9.7.YAML陷阱

YAML语法要求如果值以{ { foo }}开头的话我们需要将整行用双引号包起来.这是为了确认你不是想声明一个YAML字典.该知识点在 YAML 语法(https://ansible-tran.readthedocs.io/en/latest/docs/YAMLSyntax.html) 页面有所讲述.

这样是不行的:

- hosts: app_servers
 vars:
    app_path: {
    
    {
    
     base_path }} / 22 

你应该这么做:

- hosts: app_servers
  vars:
       app_path: "{
    
    { base_path }}/22"

9.8.使用Facts获取的信息

还有其它地方可以获取变量,这些变量是自动发现的,而不是用户自己设置的。

Facts通过访问远程系统获取相应的信息. 一个例子就是远程主机的IP地址或者操作系统是什么. 使用以下命令可以查看哪些信息是可用的:

ansible hostname -m setup

这会返回巨量的变量数据,比如对于Ubutu 12.04系统,Ansible 1.4获取的信息显示如下:

"ansible_all_ipv4_addresses": [
    "REDACTED IP ADDRESS"
],
"ansible_all_ipv6_addresses": [
    "REDACTED IPV6 ADDRESS"
],
"ansible_architecture": "x86_64",
"ansible_bios_date": "09/20/2012",
"ansible_bios_version": "6.00",
"ansible_cmdline": {
    
    
    "BOOT_IMAGE": "/boot/vmlinuz-3.5.0-23-generic",
    "quiet": true,
    "ro": true,
    "root": "UUID=4195bff4-e157-4e41-8701-e93f0aec9e22",
    "splash": true
},
"ansible_date_time": {
    
    
    "date": "2013-10-02",
    "day": "02",
    "epoch": "1380756810",
    "hour": "19",
    "iso8601": "2013-10-02T23:33:30Z",
    "iso8601_micro": "2013-10-02T23:33:30.036070Z",
    "minute": "33",
    "month": "10",
    "second": "30",
    "time": "19:33:30",
    "tz": "EDT",
    "year": "2013"
},
"ansible_default_ipv4": {
    
    
    "address": "REDACTED",
    "alias": "eth0",
    "gateway": "REDACTED",
    "interface": "eth0",
    "macaddress": "REDACTED",
    "mtu": 1500,
    "netmask": "255.255.255.0",
    "network": "REDACTED",
    "type": "ether"
},
"ansible_default_ipv6": {
    
    },
"ansible_devices": {
    
    
    "fd0": {
    
    
        "holders": [],
        "host": "",
        "model": null,
        "partitions": {
    
    },
        "removable": "1",
        "rotational": "1",
        "scheduler_mode": "deadline",
        "sectors": "0",
        "sectorsize": "512",
        "size": "0.00 Bytes",
        "support_discard": "0",
        "vendor": null
    },
    "sda": {
    
    
        "holders": [],
        "host": "SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01)",
        "model": "VMware Virtual S",
        "partitions": {
    
    
            "sda1": {
    
    
                "sectors": "39843840",
                "sectorsize": 512,
                "size": "19.00 GB",
                "start": "2048"
            },
            "sda2": {
    
    
                "sectors": "2",
                "sectorsize": 512,
                "size": "1.00 KB",
                "start": "39847934"
            },
            "sda5": {
    
    
                "sectors": "2093056",
                "sectorsize": 512,
                "size": "1022.00 MB",
                "start": "39847936"
            }
        },
        "removable": "0",
        "rotational": "1",
        "scheduler_mode": "deadline",
        "sectors": "41943040",
        "sectorsize": "512",
        "size": "20.00 GB",
        "support_discard": "0",
        "vendor": "VMware,"
    },
    "sr0": {
    
    
        "holders": [],
        "host": "IDE interface: Intel Corporation 82371AB/EB/MB PIIX4 IDE (rev 01)",
        "model": "VMware IDE CDR10",
        "partitions": {
    
    },
        "removable": "1",
        "rotational": "1",
        "scheduler_mode": "deadline",
        "sectors": "2097151",
        "sectorsize": "512",
        "size": "1024.00 MB",
        "support_discard": "0",
        "vendor": "NECVMWar"
    }
},
"ansible_distribution": "Ubuntu",
"ansible_distribution_release": "precise",
"ansible_distribution_version": "12.04",
"ansible_domain": "",
"ansible_env": {
    
    
    "COLORTERM": "gnome-terminal",
    "DISPLAY": ":0",
    "HOME": "/home/mdehaan",
    "LANG": "C",
    "LESSCLOSE": "/usr/bin/lesspipe %s %s",
    "LESSOPEN": "| /usr/bin/lesspipe %s",
    "LOGNAME": "root",
    "LS_COLORS": "rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:",
    "MAIL": "/var/mail/root",
    "OLDPWD": "/root/ansible/docsite",
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "PWD": "/root/ansible",
    "SHELL": "/bin/bash",
    "SHLVL": "1",
    "SUDO_COMMAND": "/bin/bash",
    "SUDO_GID": "1000",
    "SUDO_UID": "1000",
    "SUDO_USER": "mdehaan",
    "TERM": "xterm",
    "USER": "root",
    "USERNAME": "root",
    "XAUTHORITY": "/home/mdehaan/.Xauthority",
    "_": "/usr/local/bin/ansible"
},
"ansible_eth0": {
    
    
    "active": true,
    "device": "eth0",
    "ipv4": {
    
    
        "address": "REDACTED",
        "netmask": "255.255.255.0",
        "network": "REDACTED"
    },
    "ipv6": [
        {
    
    
            "address": "REDACTED",
            "prefix": "64",
            "scope": "link"
        }
    ],
    "macaddress": "REDACTED",
    "module": "e1000",
    "mtu": 1500,
    "type": "ether"
},
"ansible_form_factor": "Other",
"ansible_fqdn": "ubuntu2.example.com",
"ansible_hostname": "ubuntu2",
"ansible_interfaces": [
    "lo",
    "eth0"
],
"ansible_kernel": "3.5.0-23-generic",
"ansible_lo": {
    
    
    "active": true,
    "device": "lo",
    "ipv4": {
    
    
        "address": "127.0.0.1",
        "netmask": "255.0.0.0",
        "network": "127.0.0.0"
    },
    "ipv6": [
        {
    
    
            "address": "::1",
            "prefix": "128",
            "scope": "host"
        }
    ],
    "mtu": 16436,
    "type": "loopback"
},
"ansible_lsb": {
    
    
    "codename": "precise",
    "description": "Ubuntu 12.04.2 LTS",
    "id": "Ubuntu",
    "major_release": "12",
    "release": "12.04"
},
"ansible_machine": "x86_64",
"ansible_memfree_mb": 74,
"ansible_memtotal_mb": 991,
"ansible_mounts": [
    {
    
    
        "device": "/dev/sda1",
        "fstype": "ext4",
        "mount": "/",
        "options": "rw,errors=remount-ro",
        "size_available": 15032406016,
        "size_total": 20079898624
    }
],
"ansible_nodename": "ubuntu2.example.com",
"ansible_os_family": "Debian",
"ansible_pkg_mgr": "apt",
"ansible_processor": [
    "Intel(R) Core(TM) i7 CPU         860  @ 2.80GHz"
],
"ansible_processor_cores": 1,
"ansible_processor_count": 1,
"ansible_processor_threads_per_core": 1,
"ansible_processor_vcpus": 1,
"ansible_product_name": "VMware Virtual Platform",
"ansible_product_serial": "REDACTED",
"ansible_product_uuid": "REDACTED",
"ansible_product_version": "None",
"ansible_python_version": "2.7.3",
"ansible_selinux": false,
"ansible_ssh_host_key_dsa_public": "REDACTED KEY VALUE"
"ansible_ssh_host_key_ecdsa_public": "REDACTED KEY VALUE"
"ansible_ssh_host_key_rsa_public": "REDACTED KEY VALUE"
"ansible_swapfree_mb": 665,
"ansible_swaptotal_mb": 1021,
"ansible_system": "Linux",
"ansible_system_vendor": "VMware, Inc.",
"ansible_user_id": "root",
"ansible_userspace_architecture": "x86_64",
"ansible_userspace_bits": "64",
"ansible_virtualization_role": "guest",
"ansible_virtualization_type": "VMware"

可以在playbook中这样引用以上例子中第一个硬盘的模型:

{
    
    {
    
     ansible_devices.sda.model }}

同样,作为系统报告的主机名如以下所示:

{
    
    {
    
     ansible_nodename }}

不合格的主机名显示了句号(.)之前的字符串:

{
    
    {
    
     ansible_hostname }}

在模板和条件判断(请看 playbook_conditionals )中会经常使用Facts.

还可以使用Facts根据特定的条件动态创建主机群组,请查看 模块相关 文档中的 ‘group_by’ 小节获取详细内容.以及参见 条件选择 章节讨论的广义条件语句部分.

9.9.关闭Facts

如果你不需要使用你主机的任何fact数据,你已经知道了你系统的一切,那么你可以关闭fact数据的获取.这有利于增强Ansilbe面对大量系统的push模块,或者你在实验性平台中使用Ansible.在任何playbook中可以这样做:

- hosts: whatever
  gather_facts: no

9.10.本地Facts(Facts.d)

New in version 1.3

正如在playbook章节讨论的一样,Ansible facts主要用于获取远程系统的数据,从而可以在playbook中作为变量使用.

通常facts中的数据是由Ansible中的 ‘setup’模块自动发现的.用户也可以自定义facts模块,在API文档中有说明.然而,如果不借助于fact模块,而是通过一个简单的方式为Ansible变量提供系统或用户数据?

比如,你想用户能够控制受他们管理的系统的一些切面,那么应该怎么做? “Facts.d”是这样的一种机制.

Note
可能“局部facts”有点用词不当,它与 “中心供应的用户值”相对应,为”局部供应的用户值”,或者facts是 “局部动态测定的值”.

如果远程受管理的机器有一个 “/etc/ansible/facts.d” 目录,那么在该目录中任何以 ”.fact”结尾的文件都可以在Ansible中提供局部facts.这些文件可以是JSON,INI或者任何可以返回JSON的可执行文件.

例如建设有一个 /etc/ansible/facts.d/perferences.fact文件:

[general]
asdf=1
bar=2

这将产生一个名为 “general” 的哈希表fact,里面成员有 ‘asdf’ 和 ‘bar’. 可以这样验证:

ansible <hostname> -m setup -a "filter=ansible_local"

然后你会看到有以下fact被添加:

"ansible_local": {
    
    
        "preferences": {
    
    
            "general": {
    
    
                "asdf" : "1",
                "bar"  : "2"
            }
        }
 }

而且也可以再template或playbook中访问该数据:

- hosts: webservers
  tasks:
    - name: create directory for ansible custom facts
      file: state=directory recurse=yes path=/etc/ansible/facts.d
    - name: install custom impi fact
      copy: src=ipmi.fact dest=/etc/ansible/facts.d
    - name: re-read facts after adding custom fact
      setup: filter=ansible_local

然而在该模式中你也可以编写一个fact模块,这只不过是多了一个选项.

9.11.Fact缓存

New in version 1.8.

正如该文档中其它地方所示,从一个服务器引用另一个服务器的变量是可行的.比如:

{
    
    {
    
     hostvars[‘asdf.example.com’][‘ansible_os_family’] }}

如果禁用 “Fact Caching”,为了实现以上功能,Ansible在当前play之前已经与 ‘asdf.example.com’ 通讯过,或者在playbook有其它优先的play.这是ansible的默认配置.

为了避免这些,Ansible 1.8允许在playbook运行期间保存facts.但该功能需要手动开启.这有什么用处那?

想象一下,如果我们有一个非常大的基础设施,里面有数千个主机.Fact缓存可以配置在夜间运行,但小型服务器集群可以配置fact随时运行,或者在白天定期运行.即使开启了fact缓存,也不需要访问所有服务器来引用它们的变量和信息.

使用fact缓存可以跨群组访问变量,即使群组间在当前/user/bin/ansible-playbook执行中并没有通讯过.

为了启用fact缓存,在大多数plays中你可以修改 ‘gathering’ 设置为 ‘smart’ 或者 ‘explicit’,也可以设置 ‘gather_facts’ 为False.

当前,Ansible可以使用两种持久的缓存插件: redis和jsonfile.

可以在ansible.cfg中配置fact缓存使用redis:

[defaults]
gathering = smart
fact_caching = redis
fact_caching_timeout = 86400    # second

请执行适当的系统命令来启动和运行redis:

[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /path/to/cachedir
fact_caching_timeout = 86400  
# seconds

fact_caching_connection是一个放置在可读目录(如果目录不存在,ansible会试图创建它)中的本地文件路径。

9.12.注册变量

变量的另一个主要用途是在运行命令时,把命令结果存储到一个变量中.不同模块的执行结果是不同的.运行playbook时使用-v选项可以看到可能的结果值. 在ansible执行任务的结果值可以保存在变量中,以便稍后使用它.在 条件选择 章节有一些示例.

这里有一个语法示例,在上面文档中也有所提及:

- hosts: web_servers

  tasks:

     - shell: /usr/bin/foo
       register: foo_result
       ignore_errors: True

     - shell: /usr/bin/bar
       when: foo_result.rc == 5

在当前主机接下来playbook运行过程中注册的变量是有效地.这与Ansile中的 “facts” 生命周期一样. 实际上注册变量和facts很相似.

9.13.访问复杂变量数据

在该文档中我们已经讨论了一些与facts有关的高级特性.

有些提供的facts,比如网络信息等,是一个嵌套的数据结构.访问它们使用简单的 { { foo }} 语法并不够用,当仍然很容易.如下所示:

{
    
    {
    
     ansible_eth0["ipv4"]["address"] }}

或者这样写:

{
    
    {
    
     ansible_eth0.ipv4.address }}

相似的,以下代码展示了我们如何访问数组的第一个元素:

{
    
    {
    
     foo[0] }}

9.14.魔法变量, 以及如何访问其它主机的信息

Ansible会自动提供给你一些变量,即使你并没有定义过它们.这些变量中重要的有 ‘hostvars’,’group_names’,和 ‘groups’.由于这些变量名是预留的,所以用户不应当覆盖它们. ‘environmen’ 也是预留的. hostvars可以让你访问其它主机的变量,包括哪些主机中获取到的facts.如果你还没有在当前playbook或者一组playbook的任何play中访问那个主机,那么你可以获取变量,但无法看到facts值. 如果数据库服务器想使用另一个节点的某个 ‘fact’ 值,或者赋值给该节点的一个inventory变量.可以在一个模板中甚至命令行中轻松实现:

{
    
    {
    
     hostvars['test.example.com']['ansible_distribution'] }}

另外, group_names 是当前主机所在所有群组的列表(数组).所以可以使用Jinja2语法在模板中根据该主机所在群组关系(或角色)来产生变化:

{
    
    % if 'webserver' in group_names %}
   # some part of a configuration file that only applies to webservers
{
    
    % endif %}

groups 是inventory中所有群组(主机)的列表.可用于枚举群组中的所有主机.例如:

{
    
    % for host in groups['app_servers'] %}
   # something that applies to all app servers.
{
    
    % endfor %}

一个经常使用的范式是找出该群组中的所有IP地址:

{
    
    {
    
     hostvars['test.example.com']['ansible_distribution'] }}

另外, group_names 是当前主机所在所有群组的列表(数组).所以可以使用Jinja2语法在模板中根据该主机所在群组关系(或角色)来产生变化:

{
    
    % if 'webserver' in group_names %}
   # some part of a configuration file that only applies to webservers
{
    
    % endif %}

groups 是inventory中所有群组(主机)的列表.可用于枚举群组中的所有主机.例如:

{
    
    % for host in groups['app_servers'] %}
   # something that applies to all app servers.
{
    
    % endfor %}

一个经常使用的范式是找出该群组中的所有IP地址:

{
    
    % for host in groups['app_servers'] %}
   {
    
    {
    
     hostvars[host]['ansible_eth0']['ipv4']['address'] }}
{
    
    % endfor %}

比如,一个前端代理服务器需要指向所有的应用服务器,在服务器间设置正确的防火墙规则等.你需要确保所有主机的facts在使用前都已被获取到,例如运行一个play来检查这些facts是否已经被缓存起来(fact缓存是Ansible 1.8中的新特性).

另外, inventory_hostname 是Ansible inventory主机文件中配置的主机名称.由于其它一些神秘原因你不想使用自发现的主机名 ansible_hostname 时,你可以使用 inventory_hostname .如果主机的FQDN很长,那么inventory_hostname_short则会只包含域名第一个分号之前的部分,而舍弃其它部分.

play_hosts 是在当前play范围中可用的一组主机名.比如可以为多个主机填写模板,以便将这些主机注入负载均衡器规则.

delegate_to is the inventory hostname of the host that the current task has been delegated to using ‘delegate_to’.

delegate_to 是使用 ‘delegate_to’ 代理的任务中主机的inventory主机名.

不要担心以上东西,除非你需要使用它们.你会知道什么时候用它们.

inventory_dir 是保存Ansible inventory主机文件的目录路径, inventory_file 是指向Ansible inventory主机文件的路径和文件名.

最后, role_path 会返回当前role的目录名(1.8及以后).只有在role中才能使用该变量。

9.15.变量文件分割

把playbook置于源代码管理之下是个很好的注意,当你可能会想把playbook源码公开之余还想保持某些重要的变量私有.有时你也想把某些信息放置在不同的文件中,远离主playbook文件.

你可以使用外部的变量文件来实现:

---

- hosts: all
  remote_user: root
  vars:
    favcolor: blue
  vars_files:
    - /vars/external_vars.yml

  tasks:

  - name: this is just a placeholder
    command: /bin/echo foo

这可以保证你共享playbook源码时隔离敏感数据的风险.

每个变量文件的内容是一个简单的YAML文件,如下所示:

---
# in the above example, this would be vars/external_vars.yml
somevar: somevalue
password: magic
# 注意
保持每个主机和群组的变量在非常小的文件中是可能。

9.16.命令行中传递变量

除了vars_promptvars_files也可以通过Ansible命令行发送变量.如果你想编写一个通用的发布playbook时则特别有用,你可以传递应用的版本以便部署:

ansible-playbook release.yml --extra-vars "version=1.23.45 other_variable=foo"

其它场景中也很有用,比如为playbook设置主机群组或用户.

Example:
---

- hosts: '{
    
    { hosts }}'
  remote_user: '{
    
    { user }}'

  tasks:
     - ...

ansible-playbook release.yml --extra-vars "hosts=vipers user=starbuck"

Ansible 1.2中你可以给extra-vars传递JSON,比如:

--extra-vars '{"pacman":"mrs","ghosts":["inky","pinky","clyde","sue"]}'

key=value形式非常简单,但很实用!

Ansible 1.3中,实用”@”语法可以为extra-vars传递JSON文件:

-- extra-vars “@some_file.json”

同样在Ansible 1.3中,我们可以为extra-vars传递YAML格式,无论直接通过命令行还是放置在文件中.

9.17.变量的优先级:我该在什么地方放置变量?

很多人都在问变量重载的规则是怎么样的.最终Ansible的哲学是你最好知道哪里放置变量,然后会简化变量覆盖的复杂度.

避免在47个地方定义 “x” 变量然后询问 “那个x会被使用”. 为什么那? 因为这不是Ansible做事的哲学.

世界上只有一个帝国大厦.也只有一个蒙娜丽莎.请弄明白在那里定义变量,而不要把事情搞复杂.

然而,我们还是来讨论一下优先权的问题.它存在.你有可能会用到它.

如果同样名称的变量在多个地方都有定义,那么采纳是有个确定的顺序,如下:

* extra vars (-e in the command line) always win
* then comes connection variables defined in inventory (ansible_ssh_user, etc)
* then comes "most everything else" (command line switches, vars in play, included vars, role vars, etc)
* then comes the rest of the variables defined in inventory
* then comes facts discovered about a system
* then "role defaults", which are the most "defaulty" and lose in priority to everything.

* extra vars (在命令行中使用 -e)优先级最高
* 然后是在inventory中定义的连接变量(比如ansible_ssh_user)
* 接着是大多数的其它变量(命令行转换,play中的变量,included的变量,role中的变量等)
* 然后是在inventory定义的其它变量
* 然后是由系统发现的facts
* 然后是"role默认变量", 这个是最默认的值,很容易丧失优先权

猜你喜欢

转载自blog.csdn.net/toto1297488504/article/details/132228657