6.Ansible自动化之-管理变量和事实
6.管理变量和事实
实验环境
[bq@controller ~]$ mkdir web && cd web[bq@controller web]$ cat > ansible.cfg <<'EOF'
[defaults]
remote_user = bq
inventory = ./inventory[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF[bq@controller web]$ cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF
管理 VARIABLES(变量)
变量简介
变量是 Ansible 中存储数据的 “容器”,可以在 playbook、命令中重复使用。比如我们可以用变量定义软件包名称(如package: httpd
),之后在安装、启动服务时直接引用这个变量,避免重复写相同的值,既方便维护又减少出错。
变量命名规则
- 只能包含字母、数字和下划线(比如
my_var1
是合法的,而my var
、my.var
、$myvar
都是非法的) - 必须以字母开头(不能以数字或下划线开头,如
1var
、_var
都是错误的)
变量范围和优先级
Ansible 的变量可以在不同位置定义,按生效范围分为 3 类,优先级从高到低如下:
范围 | 定义位置 | 说明 |
---|---|---|
Global(全局) | 命令行参数或 Ansible 配置文件 | 优先级最高,会覆盖其他范围的同名变量 |
Play(剧本) | playbook 的vars 、vars_files 等 | 仅在当前 play 中生效,优先级高于主机范围变量 |
Host(主机) | 清单、group_vars 、host_vars 等 | 针对具体主机或主机组生效,优先级最低,会被全局和剧本范围变量覆盖 |
简单说:如果在多个地方定义了同名变量,最终生效的是优先级高的那个。
Global scope(全局变量)
全局变量通过命令行的-e
选项传递,临时生效,适用于单次执行的特殊需求。
命令语法:
ansible [主机/组] -m [模块] -a "[模块参数]" -e "[变量=值]"
-m
:指定使用的模块(如debug
用于输出信息,yum
用于管理软件包)-a
:指定模块的具体参数-e
:定义临时变量(键值对格式)
示例 1:用debug
模块验证全局变量
通过-e
定义变量package=httpd
,并通过debug
模块的msg
参数输出变量值:
[bq@controller web]$ ansible node1 -m debug -a "msg={{ package }}" -e "package=httpd"
node1 | SUCCESS => {"msg": "httpd" # 输出变量package的值为httpd
}
示例 2:用yum
模块安装软件(引用全局变量)
通过-e
定义变量package=httpd
,并使用yum
模块安装该软件包:
[bq@controller web]$ ansible node1 -m yum -a "name={{ package }} state=present" -e "package=httpd"
node1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/libexec/platform-python"},"changed": false,"msg": "Nothing to do", # 若已安装则提示无需操作"rc": 0,"results": ["Installed: httpd" # 若未安装则提示安装成功]
}
Play scope(剧本变量)
剧本变量在 playbook 中定义,仅对当前 play 生效,适合在剧本内统一管理变量。
vars
声明(直接在 play 中定义变量)
格式 1:键值对格式(推荐)
直接在 play 的vars
下以变量名: 值
的形式定义:
---
- name: 测试play中的vars声明 # play名称hosts: node1 # 目标主机vars: # 定义变量user: joe # 变量user的值为joehome: /home/joe # 变量home的值为/home/joetasks: # 任务列表- name: 创建用户{{ user }} # 任务名称,引用user变量user: # user模块用于管理用户name: "{{ user }}" # 用户名,引用user变量home: "{{ home }}" # 家目录,引用home变量state: present # 确保用户存在- name: 输出用户信息 # 第二个任务,调试变量debug: # debug模块用于输出信息msg: | # 多行消息用户名是 {{ user }}家目录是 {{ home }}
...
格式 2:列表格式(注意:Ansible 2.18 版本已移除)
早期版本支持以列表形式定义,每个变量作为列表元素:
---
- name: 测试play中的vars声明(列表格式)hosts: node1vars: # 列表格式,每个变量是一个键值对- user: joe - home: /home/joe tasks:- name: 创建用户{{ user }}user:name: "{{ user }}"home: "{{ home }}"state: present- name: 输出用户信息debug:msg: |用户名是 {{ user }}家目录是 {{ home }}
vars_files
声明(引用外部变量文件)
当变量较多时,可将变量存到外部文件,再通过vars_files
引用,便于分类管理。
示例流程:
- 创建变量文件存放目录
vars
- 在
vars
目录下创建变量文件(如user1.yaml
) - 在 playbook 中通过
vars_files
引用该文件
步骤详解:
-
创建变量文件目录及文件:
[bq@controller web]$ mkdir vars # 创建存放变量文件的目录 [bq@controller web]$ vim vars/user1.yaml # 创建变量文件
变量文件内容(YAML 格式):
# vars/user1.yaml user: user1 # 定义变量user的值为user1 home: /home/user1 # 定义变量home的值为/home/user1
-
编写引用变量文件的 playbook:
--- - name: 测试vars_files引用外部变量hosts: node1vars_files: # 引用外部变量文件- vars/user1.yaml # 变量文件路径tasks:- name: 创建用户{{ user }}user:name: "{{ user }}"home: "{{ home }}"state: present- name: 输出用户信息debug:msg: > # 单行消息(换行被忽略)用户名是 {{ user }} 家目录是 {{ home }}
变量引用注意事项
变量通过{{ 变量名 }}
引用,但有一个重要规则:当变量作为值的第一个元素时,必须用引号包裹,否则会报错。
错误示例(变量作为值的第一个元素且未加引号):
---
- name: 测试变量引用错误案例hosts: node1vars:user: joetasks:- name: 创建用户user:name: {{ user }} # 错误:变量作为第一个元素,未加引号state: present
错误原因:YAML 语法会将{{ user }}
识别为特殊结构,而非字符串,导致解析失败。
正确示例(加引号包裹):
name: "{{ user }}" # 正确:用双引号包裹
# 或
name: '{{ user }}' # 正确:用单引号包裹
Host scope(主机变量)
主机变量针对具体主机或主机组生效,优先级低于全局和剧本变量。推荐通过目录结构管理(而非直接写在清单中)。
不推荐:直接在清单文件中定义(旧做法)
在清单文件中同时定义主机和变量,会导致清单文件混乱,仅作了解:
示例清单文件:
[servers] # 主机组servers
node1 user=bq # 给node1定义变量user=bq
node2 # 未单独定义,将使用组变量[servers:vars] # 给servers组定义变量
user=laowang # 组内所有主机默认使用user=laowang(node1因单独定义而覆盖)
验证变量值:
[bq@controller web]$ ansible servers -m debug -a 'var=user' # 查看servers组的user变量
node1 | SUCCESS => {"user": "bq" # node1使用自己的变量
}
node2 | SUCCESS => {"user": "laowang" # node2使用组变量
}
推荐:通过目录结构定义(group_vars
和host_vars
)
通过group_vars
(主机组变量)和host_vars
(单主机变量)目录管理,结构清晰,是官方推荐的做法。
目录结构:
工作目录/
├── inventory # 主机清单
├── group_vars/ # 存放主机组变量(文件名=组名)
│ └── servers.yaml # servers组的变量
└── host_vars/ # 存放单主机变量(文件名=主机名)└── node1.yaml # node1的变量
示例 1:基础用法
-
准备清单文件:
[bq@controller web]$ cat inventory [servers] # 定义主机组servers node1 node2
-
创建组变量文件:
[bq@controller web]$ mkdir group_vars # 创建组变量目录 [bq@controller web]$ vim group_vars/servers.yaml # 定义servers组的变量 user: laowang # 组内所有主机默认user=laowang
-
创建主机变量文件:
[bq@controller web]$ mkdir host_vars # 创建主机变量目录 [bq@controller web]$ vim host_vars/node1.yaml # 定义node1的变量 user: bq # node1的user=bq(覆盖组变量)
-
验证变量值:
[bq@controller web]$ ansible servers -m debug -a 'var=user' node1 | SUCCESS => {"user": "bq" # node1使用主机变量 } node2 | SUCCESS => {"user": "laowang" # node2使用组变量 }
示例 2:嵌套组变量
当主机属于多个嵌套组(如dc1
和dc2
属于dc
组),变量优先级为:主机变量 > 直接所属组变量 > 父组变量。
-
清单文件(含嵌套组):
[bq@controller web]$ cat inventory [dc1] # 子组dc1 node1 node2[dc2] # 子组dc2 node3 node4[dc:children] # 父组dc,包含dc1和dc2 dc1 dc2
-
定义各级变量:
# 父组dc的变量 [bq@controller web]$ echo "package: httpd" > group_vars/dc # 子组dc1的变量 [bq@controller web]$ echo "package: httpd" > group_vars/dc1 # 子组dc2的变量 [bq@controller web]$ echo "package: apache" > group_vars/dc2 # 主机node1的变量(覆盖所有组变量) [bq@controller web]$ echo "package: mariadb-server" > host_vars/node1.yaml
-
验证变量值:
[bq@controller web]$ ansible all -m debug -a 'var=package' node1 | SUCCESS => { "package": "mariadb-server" } # 主机变量优先级最高 node2 | SUCCESS => { "package": "httpd" } # 子组dc1变量 node3 | SUCCESS => { "package": "apache" } # 子组dc2变量 node4 | SUCCESS => { "package": "apache" } # 子组dc2变量
主机连接特殊变量
这些变量用于配置 Ansible 与受管主机的连接方式(如用户名、端口、提权等),常用变量如下:
变量名 | 功能说明 |
---|---|
ansible_host | 实际连接的主机地址(默认与清单中的主机名一致) |
ansible_port | SSH 端口(默认 22) |
ansible_user | SSH 连接用户名 |
ansible_ssh_pass | SSH 密码(禁止明文存储,需用 Vault 加密) |
ansible_become | 是否启用提权(如sudo ,默认false ) |
ansible_become_method | 提权方式(如sudo 、su ,默认sudo ) |
ansible_become_user | 提权后的目标用户(默认root ) |
ansible_become_pass | 提权密码(禁止明文存储,需用 Vault 加密) |
可在host_vars
或group_vars
中定义这些变量,例如为node1
指定连接用户:
# host_vars/node1.yaml
ansible_user: devops # 连接node1时使用devops用户
ansible_become: True # 自动提权
数组变量(复杂结构变量)
当需要存储一组相关数据(如多个用户的信息),可使用数组变量(类似字典或列表),避免定义大量零散变量。
数组变量的定义
零散变量定义(不推荐):
# 每个用户的信息分散成多个变量,难以管理
user1_first_name: Bob
user1_last_name: Jones
user1_home_dir: /users/bjones
user2_first_name: Anne
user2_last_name: Cook
user2_home_dir: /users/acook
数组变量定义(推荐):
# 用字典结构整合相关变量,键为用户名,值为该用户的详细信息
users:bjones: # 第一个用户first_name: Boblast_name: Joneshome_dir: /users/bjonesacook: # 第二个用户first_name: Annelast_name: Cookhome_dir: /users/acook
数组变量的引用
有两种引用方式,推荐根据场景选择:
引用方式 | 语法示例 | 适用场景 |
---|---|---|
. 分隔符 | users.bjones.first_name | 键名不含特殊字符,且不与 Python 关键字冲突时 |
[''] 包裹 | users['acook']['home_dir'] | 键名含特殊字符,或与 Python 关键字(如copy )冲突时 |
示例 1:引用字典类型数组
---
- name: 测试字典类型数组变量hosts: node1vars: users: # 定义字典类型数组bq:user_name: bqhome_path: /home/bqlaowang:user_name: laowanghome_path: /home/laowangtasks:- name: 创建用户{{ users.bq.user_name }} # 用.分隔符引用user:name: '{{ users.bq.user_name }}' # 变量作为第一个元素,加引号home: "{{ users.bq.home_path }}"- name: 输出laowang信息 # 用['']引用debug: msg: >用户名是 {{ users['laowang']['user_name'] }}家目录是 {{ users['laowang']['home_path'] }}
示例 2:引用列表类型数组
数组也可以是列表(按索引访问,索引从 0 开始):
---
- name: 测试列表类型数组变量hosts: node1vars: users: # 列表类型数组(每个元素是一个字典)- user_name: bq1 # 第一个元素(索引0)home_path: /home/bq1- user_name: bq2 # 第二个元素(索引1)home_path: /home/bq2tasks:- name: 创建用户{{ users.0.user_name }} # 用.加索引引用user:name: "{{ users.0.user_name }}"home: "{{ users.0.home_path }}"- name: 输出第二个用户 # 用[索引]引用debug: msg: "{{ users[1].user_name }}" # 索引1对应第二个元素
register
语句(捕获任务输出)
register
用于将任务的执行结果保存到变量中,方便后续任务使用(如判断任务是否成功、提取输出信息等)。
示例:安装httpd
并捕获安装结果
---
- name: 安装软件并捕获结果hosts: node1tasks:- name: 安装httpdyum:name: httpdstate: installed # 确保软件已安装register: install_result # 将结果保存到install_result变量- name: 输出安装结果debug: var: install_result # 打印变量内容(包含安装状态、变更信息等)
执行后可看到install_result
包含的信息:如是否有变更(changed: true
表示安装成功)、软件版本、执行日志等。
Magic 变量(Ansible 内置变量)
Magic 变量是 Ansible 自动生成的特殊变量,用于获取受管主机的清单信息,常用的有 4 个:
变量名 | 功能说明 |
---|---|
inventory_hostname | 清单中定义的当前主机名(可能与实际主机名不同) |
group_names | 当前主机所属的所有主机组列表 |
groups | 清单中所有主机组及组内主机的信息(字典格式) |
hostvars | 所有受管主机的变量信息(可用于跨主机引用变量,如hostvars['node1']['user'] ) |
示例清单(用于测试 Magic 变量):
controller # 单独主机[webs] # 网站服务器组
node1
node2[dbs] # 数据库服务器组
node3
node4
验证 Magic 变量:
-
inventory_hostname
(当前主机名):[bq@controller web]$ ansible node1 -m debug -a 'var=inventory_hostname' node1 | SUCCESS => {"inventory_hostname": "node1" # 清单中定义的主机名 }
-
group_names
(所属组):[bq@controller web]$ ansible node1 -m debug -a 'var=group_names' node1 | SUCCESS => {"group_names": ["webs"] # node1属于webs组 }
-
groups
(所有组信息):[bq@controller web]$ ansible node1 -m debug -a 'var=groups' node1 | SUCCESS => {"groups": {"all": ["controller", "node1", "node2", "node3", "node4"],"dbs": ["node3", "node4"],"webs": ["node1", "node2"],"ungrouped": ["controller"] # 未分组主机} }
-
hostvars
(跨主机变量):# 查看node3的所属组(需先收集过node3的变量) [bq@controller web]$ ansible node1 -m debug -a 'var=hostvars.node3.group_names' node1 | SUCCESS => {"hostvars.node3.group_names": ["dbs"] # node3属于dbs组 }
管理 SECRETS(敏感信息)
Ansible Vault 简介
Ansible 中可能需要使用密码、API 密钥等敏感信息,若明文存储会有安全风险。Ansible Vault 可加密这些敏感文件(如变量文件),只有知道密码的人才能解密使用。
ansible-vault
命令(加密 / 解密工具)
ansible-vault
用于管理加密文件,常用命令如下:
命令 | 功能说明 | 常用选项 |
---|---|---|
create | 创建新的加密文件 | --vault-password-file :从文件读取密码 |
view | 查看加密文件内容 | 同上 |
edit | 编辑加密文件 | 同上 |
encrypt | 加密已存在的明文文件 | 同上 |
decrypt | 解密加密文件(会覆盖原文件) | 同上 |
rekey | 更改加密文件的密码 | --new-vault-password-file :新密码文件 |
示例操作:
-
设置默认编辑器(可选,默认用
vi
):[bq@controller web]$ export EDITOR=vim # 临时设置为vim [bq@controller web]$ echo 'export EDITOR=vim' >> ~/.bashrc # 永久生效(需重新加载) [bq@controller web]$ source ~/.bashrc # 重新加载配置
-
创建加密文件(如
secret.yaml
,存储密码):[bq@controller web]$ ansible-vault create secret.yaml New Vault password: 123 # 输入密码(示例用123,实际需复杂密码) Confirm New Vault password: 123 # 确认密码
输入内容(YAML 格式):
password: redhat # 敏感信息:密码为redhat
-
查看加密文件:
[bq@controller web]$ ansible-vault view secret.yaml Vault password: 123 # 输入创建时的密码 password: redhat # 解密后内容
-
从密码文件读取密码(避免每次输入):
[bq@controller web]$ echo 123 > pass # 创建密码文件(权限需设为600) [bq@controller web]$ chmod 600 pass # 限制权限,仅所有者可读写 [bq@controller web]$ ansible-vault view secret.yaml --vault-password-file=pass password: redhat # 无需手动输入密码
-
在配置文件中指定密码文件(更便捷):
[bq@controller web]$ vim ansible.cfg # 编辑Ansible配置 [defaults] vault_password_file = ./pass # 指定密码文件路径
之后操作加密文件无需指定
--vault-password-file
:[bq@controller web]$ ansible-vault view secret.yaml # 直接查看 password: redhat
-
编辑加密文件:
[bq@controller web]$ ansible-vault edit secret.yaml # 自动解密并编辑 # 编辑后内容:password: redhat123(保存后自动重新加密)
-
解密文件(谨慎使用,会明文存储):
[bq@controller web]$ ansible-vault decrypt secret.yaml Decryption successful # 解密成功,原文件变为明文 [bq@controller web]$ cat secret.yaml password: redhat123 # 明文显示
-
重新加密文件:
[bq@controller web]$ ansible-vault encrypt secret.yaml Encryption successful # 重新加密
-
更改密码:
[bq@controller web]$ ansible-vault rekey secret.yaml # 交互式更改 New Vault password: 456 # 新密码 Confirm New Vault password: 456 Rekey successful
综合案例:用加密变量配置数据库
目标:通过加密的变量文件配置 MySQL 用户,避免密码明文暴露。
步骤流程:
- 创建加密的变量文件(存储数据库用户信息)
- 编写 playbook,引用加密变量文件
- 执行 playbook,使用加密密码配置数据库
步骤详解:
-
创建加密变量文件:
[bq@controller web]$ mkdir vault # 创建存放加密文件的目录 [bq@controller web]$ ansible-vault create vault/mysql.yml # 创建加密文件
输入变量内容(数据库用户信息):
user: bq # 数据库用户名 password: redhat # 数据库密码(加密存储) host: '%' # 允许所有主机连接 priv: '*.*:ALL' # 权限:所有库表的所有权限
-
编写 playbook(
playbook.yaml
):--- - name: 配置MariaDB服务器hosts: node1vars_files:- vault/mysql.yml # 引用加密的变量文件tasks:- name: 安装MariaDB及依赖yum:name: - mariadb-server # 数据库服务- python3-PyMySQL # Python连接MySQL的库state: present- name: 启动并启用MariaDBservice:name: mariadbenabled: yes # 开机自启state: started # 启动服务- name: 创建数据库用户{{ user }}mysql_user: # 管理MySQL用户的模块name: "{{ user }}" # 引用加密变量中的用户名password: "{{ password }}" # 引用加密变量中的密码host: "{{ host }}" # 允许连接的主机priv: "{{ priv }}" # 权限设置state: present # 确保用户存在
-
执行 playbook:
# 若ansible.cfg未配置vault_password_file,需用--ask-vault-pass交互输入密码 [bq@controller web]$ ansible-playbook playbook.yaml --ask-vault-pass Vault password: 123 # 输入加密文件的密码
-
验证结果(在 node1 上):
[root@node1 ~]# mysql -u bq -predhat # 使用加密变量中的用户名和密码登录 Welcome to the MariaDB monitor. # 登录成功,说明配置生效
变量管理推荐做法
- 敏感变量单独加密:将敏感信息(密码、密钥)放在独立文件中,用 Vault 加密;普通变量明文存储。
- 目录结构分类:通过
group_vars
、host_vars
按主机 / 组分类变量,每个主机 / 组可包含多个变量文件(如vars.yaml
存普通变量,vault.yaml
存加密变量)。
推荐目录结构示例:
web/
├── ansible.cfg # Ansible配置
├── inventory # 主机清单
├── playbook.yaml # 主剧本
├── group_vars/ # 组变量
│ ├── all.yaml # 所有主机通用变量(普通)
│ └── servers.yaml # servers组变量(普通)
├── host_vars/ # 主机变量
│ └── node1/
│ ├── vars.yaml # node1的普通变量
│ └── vaults.yaml # node1的敏感变量(加密)
└── vault/└── mysql.yml # 数据库相关敏感变量(加密)
管理 FACTS(主机信息)
FACTS 介绍
FACTS是 Ansible 自动从受管主机收集的信息,相当于主机的 “体检报告”,包括主机名、IP 地址、操作系统、内存、磁盘等。这些信息会被存为变量,可在 playbook 中直接引用。
用途:
- 根据内核版本决定是否重启主机
- 根据内存大小调整软件配置(如 MySQL 缓存)
- 用主机 IP 地址自动填充配置文件
查看 FACTS 内容
查看所有 FACTS
通过debug
模块打印ansible_facts
变量(包含所有 FACTS):
---
- name: 打印所有FACTS信息hosts: node1tasks:- name: 输出所有FACTSdebug:var: ansible_facts # 所有FACTS都在ansible_facts变量中
查看单个 FACTS
直接引用具体的 FACTS 变量(如主机名、IP 地址):
---
- hosts: node1tasks:- name: 输出指定FACTSdebug: msg: >主机{{ ansible_fqdn }}的默认IPv4地址是{{ ansible_default_ipv4.address }}# ansible_fqdn:完全限定域名;ansible_default_ipv4.address:默认IPv4地址
常用 FACTS 变量
FACTS 描述 | 变量(新格式,Ansible 2.5+) | 旧格式(兼容,不推荐) |
---|---|---|
短主机名 | ansible_facts['hostname'] | ansible_hostname |
完全限定域名(FQDN) | ansible_facts['fqdn'] | ansible_fqdn |
默认 IPv4 地址 | ansible_facts['default_ipv4']['address'] | ansible_default_ipv4['address'] |
所有网络接口 | ansible_facts['interfaces'] | ansible_interfaces |
内核版本 | ansible_facts['kernel'] | ansible_kernel |
DNS 服务器列表 | ansible_facts['dns']['nameservers'] | ansible_dns['nameservers'] |
/dev/vda1 分区大小 | ansible_facts['devices']['vda']['partitions']['vda1']['size'] | ansible_devices['vda']['partitions']['vda1']['size'] |
setup
模块(收集 FACTS)
setup
模块用于手动收集 FACTS,支持过滤和限制收集范围,比自动收集更灵活。
命令语法:
ansible [主机] -m setup -a "[选项]"
选项 | 功能说明 |
---|---|
filter=Pattern | 只收集匹配 Pattern 的 FACTS(支持通配符* ) |
gather_subset=Subset | 限制收集的 FACTS 类别(如!all 禁用所有,network 只收集网络信息) |
示例:
-
只收集默认 IPv4 信息:
[bq@controller web]$ ansible node1 -m setup -a 'filter=ansible_default_ipv4' node1 | SUCCESS => {"ansible_facts": {"ansible_default_ipv4": {"address": "172.25.250.10", # IPv4地址"gateway": "172.25.250.254", # 网关"netmask": "255.255.255.0" # 子网掩码}} }
-
只收集网络相关 FACTS:
[bq@controller web]$ ansible node1 -m setup -a 'gather_subset=network' # 只输出网络相关的FACTS(如接口、IP、MAC等)
关闭 FACTS 收集
默认情况下,play 会自动收集 FACTS,但以下场景可关闭:
- 不使用任何 FACTS,想加快 play 执行速度
- 受管主机无法运行
setup
模块(如缺少依赖) - 需先安装软件再收集 FACTS
关闭方式:
-
在 play 中设置:
--- - name: 关闭自动FACTS收集hosts: node1gather_facts: no # 关闭自动收集
-
在 Ansible 配置文件中全局设置:
[defaults] gathering = explicit # 全局关闭自动收集,需手动调用setup模块
手动收集:即使关闭自动收集,仍可通过setup
模块手动收集:
tasks:- name: 手动收集FACTSsetup: # 显式调用setup模块收集FACTS
扩展练习:变量优先级验证
实验目标:验证不同位置定义的变量的优先级(从高到低)。
变量定义位置及值:
定义位置 | 变量值 | 优先级(1 最高,10 最低) |
---|---|---|
命令行-e | user1 | 1 |
task 中include_vars 引用的文件 | user2 | 2 |
task 中vars 指令 | user3 | 3 |
play 中vars_files 引用的文件 | user4 | 4 |
play 中vars 指令 | user5 | 5 |
host_vars 目录中的主机文件 | user6 | 6 |
清单文件中主机单独定义 | user7 | 7 |
group_vars 目录中的组文件 | user8 | 8 |
group_vars/all 文件 | user9 | 9 |
清单文件中all:vars 定义 | user10 | 10 |
实验流程:
- 准备环境(创建变量文件、目录、清单)
- 编写 playbook,引用不同位置的变量
- 执行 playbook,观察变量值的变化,验证优先级
步骤详解
-
环境准备:
# 创建变量文件 [bq@controller web]$ echo "user: user2" > var2 # task中include_vars引用 [bq@controller web]$ echo "user: user4" > var4 # play中vars_files引用# 创建host_vars和group_vars目录 [bq@controller web]$ mkdir host_vars group_vars -p# 定义host_vars(主机变量) [bq@controller web]$ echo "user: user6" > host_vars/node1# 定义group_vars(组变量) [bq@controller web]$ echo "user: user8" > group_vars/servers # 组变量 [bq@controller web]$ echo "user: user9" > group_vars/all # 所有组通用变量# 创建清单文件(含组变量和主机变量) [bq@controller web]$ cat > inventory << eof [servers] node1 user=user7 # 清单中主机单独定义变量 [servers:vars] user=user10 # 清单中组变量 [all:vars] user=user11 # 清单中所有主机的变量 eof
-
编写 playbook(
playbook.yaml
):--- - name: 验证变量优先级hosts: node1gather_facts: no # 关闭FACTS收集,加快执行vars_files:- var4 # 引用var4文件(user=user4)vars: user: user5 # play中vars定义(user=user5)tasks:- name: 输出当前user值(play级变量)debug:msg: hello {{ user }} # 预期输出user5(当前最高优先级为play的vars)- name: 引用var2文件(user=user2)include_vars:file: var2 # 加载var2文件,变量变为user2- name: 输出当前user值(task的include_vars后)vars:user: user3 # task中vars定义(user=user3,优先级更高)debug:msg: hello {{ user }} # 预期输出user3
-
执行 playbook 并观察结果:
# 带命令行变量执行(user=user1,优先级最高) [bq@controller web]$ ansible-playbook playbook.yaml -e "user=user1"
预期输出:
- 第一个
debug
任务:hello user1
(命令行变量优先级最高) - 第二个
debug
任务:hello user1
(命令行变量覆盖 task 的 vars)
若去掉命令行变量执行,结果会依次变为:
- 第一个
debug
:hello user5
(play 的 vars) - 第二个
debug
:hello user3
(task 的 vars)
以此类推,可逐步验证各位置变量的优先级。
- 第一个
如涉及版权问题请联系作者处理!!!