RHCE8.0讲义:管理变量

来自CloudWiki
跳转至: 导航搜索

ANSIBLE变量简介

Ansible支持利用变量来存储值,并在Ansible项目的所有文件中重复使用这些值。这可以简化项目 的创建和维护,并减少错误的数量。

通过变量,您可以轻松地在Ansible项目中管理给定环境的动态值。例如,变量可能包含下面这些 值:

  • 要创建的用户
  • 要安装的软件包
  • 要重新启动的服务
  • 要删除的文件
  • 要从互联网检索的存档

命名变量

变量的名称必须以字母幵头,并且只能含有字母、数字和下划线。

下表说明了无效和有效变量名称之间的差别。

无效和有效的Ansible变量名称的示例

无效的变量名称	有效的变量名称
web server	web_server
remote.file	remote_file
1st file	file_l
filel
remoteserver$l	remote_server_l 或remote_serverl

定义变量

可在Ansible项目中的多个位置定义变量。不过,这可简化为三个基本的范围级别:

  • 全局范围:从命令行或Ansible配置设置的变量
  • Play范围:在play和相关结构中设置的变量
  • 主机范围:由清单、事实收集或注册的任务,在主机组和个别主机上设置的变量

如果在多个级别上定义了相同名称的变量,则釆用优先级别最高的变量。

  • 窄范围优先于更广泛的范 围
  • 由清单定义的变量将被playbook定义的变量覆盖
  • playbook定义的变量将被命令行中定义的变量覆盖。

Ansible文档中详细探讨了变量优先级,本节末尾的“参考”部分中提供了其链接。

PLAYBOOK中的变量

变量在Ansible Playbook中发挥着重要作用'因为它们可以简化playbook中变量数据的管理。

在Playbook中定义变量

编写playbook时,您可以定义自己的变量,然后在任务中调用这些值。例如,名为web_package 的变量可以使用值httpd来定义。然后,任务可以使用yum模块调用该变量来安装httpd软件包。

Playbook变量可以通过多种方式定义。一种常见方式是将变量放在playbook幵头的vars块中:

- hosts: all
  vars:
    user: joe
    home: /home/joe

也可以在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用 vars_files指令,后面跟丄相对于playbook位置的外部变量文件名称列表:

- hosts: all
  vars_files:
     - vars/users.yml

而后,可以使用YAML格式在这一/这些文件中定义playbook变量:

user: joe
home: /home/joe

在Playbook中使用变量

声明了变量后,管理员可以在任务中使用这些变量。若要引用变量,可将变量名称放在双花括号 ({{}})内。在任务执行时,Ansible会将变量替换为其值。

---
- name: Install and start Apache HTTPD
  hosts: slave
  vars:
    user: joe
  tasks:
    # This line will read: Creates the user joe
    - name: Creates the user {{ user }}
      user:
        # This line will create the user named Joe
        name:"{{ user }}"

重要: 当变量用作开始一个值的第一元素时,必须使用引号。这可以防止Ansible将变量引 用视为YMAL字典的开头。如果缺少引号,将显示下列消息:

yum:
name: {{ service })
      △ 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中定义的变量的优先级比这 两者更高。

若要定义主机变量和组变量,一种方法是直接在清单文件中定义。这是较旧的做法,不建议采用, 但您仍可能会遇到。

  • 定义 demo. example. com 的 ansible_user 主机变量:
[servers]
demo.example.com ansible_user=joe
  • 定义servers主机组的user组变量。
[servers]
demol.example.com
demo2.example.com
[servers:vars]
user=joe
  • 定义servers组的user组变量,该组由两个主机组组成,每个主机组有两个服务器。
[serversl]
demol.example.com
demo2.example.com
[servers2]
demo3.example.com
demo4.example.com
[servers:children] 
serversl
servers2
[servers:vars] user=joe

此做法存在的一些缺点,它使得清单文件更难以处理,在同一文件中混合提供了主机和变量信息, 而且采用的也是过时的语法。

使用目录填充主机和组变量

定义主机和主机组的变量的首选做法是在与清单文件或目录相同的工作目录中,创建group_vars 和host_vars两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。

重要:建议的做法是使用host_vars和group_vars目录定义清单变量,而不直接在清 单文件中定义它们。

为了定义用于servers组的组变量,需要创建名为group_vars/servers的YAML文件,然后 该文件的内容将使用与playbook相同的语法将变量设置为值:

user: joe

类似地,为了定义用于特定主机的主机变量,需要在host_vars目录中创建名称与主机匹配的文 件来存放主机变量。

下面的示例更加详细地说明了这一做法。例如在一个场景中,需要管理两个数据中心,并在~/ proj ect/inventory清单文件中定义数据中心主机:

[admin@station project]$ cat ~/project/inventory

[datacenterl]
demol.example.com
demo2.example.com
[datacenter2]
demo3.example.com
demo4.example.com
[datacenters:children]
datacenterl
datacenter2
  • 如果需要为两个数据中心的所有服务器定义一个通用值,可以为datacenters主机组设置一个 组变量:

[admin@station project]$ cat */project/group_vars/datacenters

package: httpd
  • 如果要为每个数据中心定义不同的值,可以为每个数据中心主机组设置组变量:

[admin@station project]$ cat -/project/group_vars/datacenterl

package: httpd

[admin@station project]$ cat ~/project/group_vars/datacenter2

package: apache
  • 如果要为每一数据中心的各个主机定义不同的值,则在单独的主机变量文件中定义变量:

cat ~/proj ect/host_vars/demol.example.com

cat ~/proj ect/host_vars/demo2.example.com

cat ~/proj ect/host_vars/demo3.example.com

示例项目project的目录结构如果包含上面的所有示例文件,将如下所示:

project
I—— ansible.cfg
I——group_vars
I——datacenters
I——datacentersl
1——datacenters2
I——host_vars
I—— demol.example.com
I—— demo2.example.com
I— demo3.example.com
1—— demo4.example.com
I——inventory
1—— playbook.yml

从命令行覆盖变量

清单变量可被playbook中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible 或ansible-playbook命令来覆盖。在命令行上设置的变量称为额外变量。

当您需要覆盖一次性运行的playbook的变量的已定义值时,额外变量非常有用。例如:

[user@demo ~]$ ansible-playbook main.yml -e "package=apache"

使用数组作为变量

除了将与同一元素相关的配置数据(软件包列表、服务列表和用户列表等)分配到多个变量外,管 理员也可以使用数组。这种做法的一个好处在于,数组是可以浏览的。

例如,假设下列代码片段:

userl_first_name: Bob 
userl_last_name: Jones 
userl_home_dir: /users/bjones 
user2_first_name: Anne 
user2_last_name: Cook 
user2_home_dir: /users/acook

这可以改写成名为users的数组:

users:
  bjones: 
    first_name: Bob 
    last_name: Jones 
    home_dir: /users/bjones 
  acook:
    first_name: Anne 
    last_name: Cook 
    home_dir: /users/acook

然后,您可以使用以下变量来访问用户数据:

#Returns 'Bob'
users.bjones.first_name
#Returns 1/users/acook1 
users.acook.home_dir

由于变量被定义为Python字典,因此可以使用替代语法。

#Returns 'Bob1
users['bjones']['first_name']
#Returns '/users/acook'
users['acook1]['home_dir']

重要: 如果键名称与Python方法或属性的名称(如discard, copy和add等)相同,点 表示法可能会造成问题。使用方括号表示法有助于避免冲突和错误。

两种语法都有效,但为了方便故障排除,红帽建议在任何给定Ansible项目的所有文 件中一致地采用一种语法。

使用已注册变量捕获命令输出

管理员可以使用register语句捕获命令输出。输出保存在一个临时变量中,稍后在playbook中 可用于调试用途或者达成其他目的,例如基于命令输出的特定配置。

以下playbook演示了如何为调试用途捕获命令输出:

- name: Installs a package and prints the result hosts: all
  tasks:
    - name: Install the package
      yum:
        name: httpd
        state: installed
      register: install_result
    - debug: var=install_result


运行该playbook时,debug模块用于将install_result注册变量的值转储到终端。

[user@demo ~]$ ansible-playbook playbook.yml
PLAY [Installs a package and prints the result] *
TASK [setup] ************************************************* ok: [demo.example.com]
TASK [Install the package] ************************************************ ok: [demo.example.com]
TAsk [debug] *******************
ok: [demo.example.com] => {
"install_result": {
"changed": false,
,'msg":
"rcH: 0,
"results":[
"httpd-2.4.6-40.el7.x86_64 providing httpd is already installed"
]
}
PLAY RECAP ********
demo.example.com : ok=3 changed=0 unreachable=0 failed=0

参考文献

清单 — Ansible 文档

https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html

变量 — Ansible 文档

https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html

变量优先级:我该将变量放到何处?

https://docs.ansible.com/ansible/latest/user_guide/ playbooks_variables.html#variable-precedence-where-should-i-put-a-variable

YAML 语法 — Ansible 文档

https://docs.ansible.com/ansible/latest/reference_appendicAs/YAMLSyntax.html