6.管理变量和事实
实验环境
bash
[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
参数输出变量值:
bash
[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
模块安装该软件包:
bash
[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
下以变量名: 值
的形式定义:
yaml
---
- name: 测试play中的vars声明 # play名称
hosts: node1 # 目标主机
vars: # 定义变量
user: joe # 变量user的值为joe
home: /home/joe # 变量home的值为/home/joe
tasks: # 任务列表
- name: 创建用户{{ user }} # 任务名称,引用user变量
user: # user模块用于管理用户
name: "{{ user }}" # 用户名,引用user变量
home: "{{ home }}" # 家目录,引用home变量
state: present # 确保用户存在
- name: 输出用户信息 # 第二个任务,调试变量
debug: # debug模块用于输出信息
msg: | # 多行消息
用户名是 {{ user }}
家目录是 {{ home }}
...
格式 2:列表格式(注意:Ansible 2.18 版本已移除)
早期版本支持以列表形式定义,每个变量作为列表元素:
yaml
---
- name: 测试play中的vars声明(列表格式)
hosts: node1
vars: # 列表格式,每个变量是一个键值对
- 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
引用该文件
步骤详解:
-
创建变量文件目录及文件:
bash[bq@controller web]$ mkdir vars # 创建存放变量文件的目录 [bq@controller web]$ vim vars/user1.yaml # 创建变量文件
变量文件内容(YAML 格式):
yaml# vars/user1.yaml user: user1 # 定义变量user的值为user1 home: /home/user1 # 定义变量home的值为/home/user1
-
编写引用变量文件的 playbook:
yaml--- - name: 测试vars_files引用外部变量 hosts: node1 vars_files: # 引用外部变量文件 - vars/user1.yaml # 变量文件路径 tasks: - name: 创建用户{{ user }} user: name: "{{ user }}" home: "{{ home }}" state: present - name: 输出用户信息 debug: msg: > # 单行消息(换行被忽略) 用户名是 {{ user }} 家目录是 {{ home }}
变量引用注意事项
变量通过{``{ 变量名 }}
引用,但有一个重要规则:当变量作为值的第一个元素时,必须用引号包裹,否则会报错。
错误示例(变量作为值的第一个元素且未加引号):
yaml
---
- name: 测试变量引用错误案例
hosts: node1
vars:
user: joe
tasks:
- name: 创建用户
user:
name: {{ user }} # 错误:变量作为第一个元素,未加引号
state: present
错误原因 :YAML 语法会将{``{ user }}
识别为特殊结构,而非字符串,导致解析失败。
正确示例(加引号包裹):
yaml
name: "{{ user }}" # 正确:用双引号包裹
# 或
name: '{{ user }}' # 正确:用单引号包裹
Host scope(主机变量)
主机变量针对具体主机或主机组生效,优先级低于全局和剧本变量。推荐通过目录结构管理(而非直接写在清单中)。
不推荐:直接在清单文件中定义(旧做法)
在清单文件中同时定义主机和变量,会导致清单文件混乱,仅作了解:
示例清单文件:
ini
[servers] # 主机组servers
node1 user=bq # 给node1定义变量user=bq
node2 # 未单独定义,将使用组变量
[servers:vars] # 给servers组定义变量
user=laowang # 组内所有主机默认使用user=laowang(node1因单独定义而覆盖)
验证变量值:
bash
[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
(单主机变量)目录管理,结构清晰,是官方推荐的做法。
目录结构:
plaintext
工作目录/
├── inventory # 主机清单
├── group_vars/ # 存放主机组变量(文件名=组名)
│ └── servers.yaml # servers组的变量
└── host_vars/ # 存放单主机变量(文件名=主机名)
└── node1.yaml # node1的变量
示例 1:基础用法
-
准备清单文件:
bash[bq@controller web]$ cat inventory [servers] # 定义主机组servers node1 node2
-
创建组变量文件:
bash[bq@controller web]$ mkdir group_vars # 创建组变量目录 [bq@controller web]$ vim group_vars/servers.yaml # 定义servers组的变量 user: laowang # 组内所有主机默认user=laowang
-
创建主机变量文件:
bash[bq@controller web]$ mkdir host_vars # 创建主机变量目录 [bq@controller web]$ vim host_vars/node1.yaml # 定义node1的变量 user: bq # node1的user=bq(覆盖组变量)
-
验证变量值:
bash[bq@controller web]$ ansible servers -m debug -a 'var=user' node1 | SUCCESS => { "user": "bq" # node1使用主机变量 } node2 | SUCCESS => { "user": "laowang" # node2使用组变量 }
示例 2:嵌套组变量
当主机属于多个嵌套组(如dc1
和dc2
属于dc
组),变量优先级为:主机变量 > 直接所属组变量 > 父组变量。
-
清单文件(含嵌套组):
bash[bq@controller web]$ cat inventory [dc1] # 子组dc1 node1 node2 [dc2] # 子组dc2 node3 node4 [dc:children] # 父组dc,包含dc1和dc2 dc1 dc2
-
定义各级变量:
bash# 父组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
-
验证变量值:
bash[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
指定连接用户:
yaml
# host_vars/node1.yaml
ansible_user: devops # 连接node1时使用devops用户
ansible_become: True # 自动提权
数组变量(复杂结构变量)
当需要存储一组相关数据(如多个用户的信息),可使用数组变量(类似字典或列表),避免定义大量零散变量。
数组变量的定义
零散变量定义(不推荐):
yaml
# 每个用户的信息分散成多个变量,难以管理
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
数组变量定义(推荐):
yaml
# 用字典结构整合相关变量,键为用户名,值为该用户的详细信息
users:
bjones: # 第一个用户
first_name: Bob
last_name: Jones
home_dir: /users/bjones
acook: # 第二个用户
first_name: Anne
last_name: Cook
home_dir: /users/acook
数组变量的引用
有两种引用方式,推荐根据场景选择:
引用方式 | 语法示例 | 适用场景 |
---|---|---|
. 分隔符 |
users.bjones.first_name |
键名不含特殊字符,且不与 Python 关键字冲突时 |
[''] 包裹 |
users['acook']['home_dir'] |
键名含特殊字符,或与 Python 关键字(如copy )冲突时 |
示例 1:引用字典类型数组
yaml
---
- name: 测试字典类型数组变量
hosts: node1
vars:
users: # 定义字典类型数组
bq:
user_name: bq
home_path: /home/bq
laowang:
user_name: laowang
home_path: /home/laowang
tasks:
- 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 开始):
yaml
---
- name: 测试列表类型数组变量
hosts: node1
vars:
users: # 列表类型数组(每个元素是一个字典)
- user_name: bq1 # 第一个元素(索引0)
home_path: /home/bq1
- user_name: bq2 # 第二个元素(索引1)
home_path: /home/bq2
tasks:
- 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
并捕获安装结果
yaml
---
- name: 安装软件并捕获结果
hosts: node1
tasks:
- name: 安装httpd
yum:
name: httpd
state: 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 变量):
ini
controller # 单独主机
[webs] # 网站服务器组
node1
node2
[dbs] # 数据库服务器组
node3
node4
验证 Magic 变量:
-
inventory_hostname
(当前主机名):bash[bq@controller web]$ ansible node1 -m debug -a 'var=inventory_hostname' node1 | SUCCESS => { "inventory_hostname": "node1" # 清单中定义的主机名 }
-
group_names
(所属组):bash[bq@controller web]$ ansible node1 -m debug -a 'var=group_names' node1 | SUCCESS => { "group_names": ["webs"] # node1属于webs组 }
-
groups
(所有组信息):bash[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
(跨主机变量):bash# 查看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
):bash[bq@controller web]$ export EDITOR=vim # 临时设置为vim [bq@controller web]$ echo 'export EDITOR=vim' >> ~/.bashrc # 永久生效(需重新加载) [bq@controller web]$ source ~/.bashrc # 重新加载配置
-
创建加密文件 (如
secret.yaml
,存储密码):bash[bq@controller web]$ ansible-vault create secret.yaml New Vault password: 123 # 输入密码(示例用123,实际需复杂密码) Confirm New Vault password: 123 # 确认密码
输入内容(YAML 格式):
yamlpassword: redhat # 敏感信息:密码为redhat
-
查看加密文件:
bash[bq@controller web]$ ansible-vault view secret.yaml Vault password: 123 # 输入创建时的密码 password: redhat # 解密后内容
-
从密码文件读取密码(避免每次输入):
bash[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 # 无需手动输入密码
-
在配置文件中指定密码文件(更便捷):
bash[bq@controller web]$ vim ansible.cfg # 编辑Ansible配置 [defaults] vault_password_file = ./pass # 指定密码文件路径
之后操作加密文件无需指定
--vault-password-file
:bash[bq@controller web]$ ansible-vault view secret.yaml # 直接查看 password: redhat
-
编辑加密文件:
bash[bq@controller web]$ ansible-vault edit secret.yaml # 自动解密并编辑 # 编辑后内容:password: redhat123(保存后自动重新加密)
-
解密文件(谨慎使用,会明文存储):
bash[bq@controller web]$ ansible-vault decrypt secret.yaml Decryption successful # 解密成功,原文件变为明文 [bq@controller web]$ cat secret.yaml password: redhat123 # 明文显示
-
重新加密文件:
bash[bq@controller web]$ ansible-vault encrypt secret.yaml Encryption successful # 重新加密
-
更改密码:
bash[bq@controller web]$ ansible-vault rekey secret.yaml # 交互式更改 New Vault password: 456 # 新密码 Confirm New Vault password: 456 Rekey successful
综合案例:用加密变量配置数据库
目标:通过加密的变量文件配置 MySQL 用户,避免密码明文暴露。
步骤流程:
- 创建加密的变量文件(存储数据库用户信息)
- 编写 playbook,引用加密变量文件
- 执行 playbook,使用加密密码配置数据库
步骤详解:
-
创建加密变量文件:
bash[bq@controller web]$ mkdir vault # 创建存放加密文件的目录 [bq@controller web]$ ansible-vault create vault/mysql.yml # 创建加密文件
输入变量内容(数据库用户信息):
yamluser: bq # 数据库用户名 password: redhat # 数据库密码(加密存储) host: '%' # 允许所有主机连接 priv: '*.*:ALL' # 权限:所有库表的所有权限
-
编写 playbook (
playbook.yaml
):yaml--- - name: 配置MariaDB服务器 hosts: node1 vars_files: - vault/mysql.yml # 引用加密的变量文件 tasks: - name: 安装MariaDB及依赖 yum: name: - mariadb-server # 数据库服务 - python3-PyMySQL # Python连接MySQL的库 state: present - name: 启动并启用MariaDB service: name: mariadb enabled: yes # 开机自启 state: started # 启动服务 - name: 创建数据库用户{{ user }} mysql_user: # 管理MySQL用户的模块 name: "{{ user }}" # 引用加密变量中的用户名 password: "{{ password }}" # 引用加密变量中的密码 host: "{{ host }}" # 允许连接的主机 priv: "{{ priv }}" # 权限设置 state: present # 确保用户存在
-
执行 playbook:
bash# 若ansible.cfg未配置vault_password_file,需用--ask-vault-pass交互输入密码 [bq@controller web]$ ansible-playbook playbook.yaml --ask-vault-pass Vault password: 123 # 输入加密文件的密码
-
验证结果(在 node1 上):
bash[root@node1 ~]# mysql -u bq -predhat # 使用加密变量中的用户名和密码登录 Welcome to the MariaDB monitor. # 登录成功,说明配置生效
变量管理推荐做法
- 敏感变量单独加密:将敏感信息(密码、密钥)放在独立文件中,用 Vault 加密;普通变量明文存储。
- 目录结构分类 :通过
group_vars
、host_vars
按主机 / 组分类变量,每个主机 / 组可包含多个变量文件(如vars.yaml
存普通变量,vault.yaml
存加密变量)。
推荐目录结构示例:
plaintext
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):
yaml
---
- name: 打印所有FACTS信息
hosts: node1
tasks:
- name: 输出所有FACTS
debug:
var: ansible_facts # 所有FACTS都在ansible_facts变量中
查看单个 FACTS
直接引用具体的 FACTS 变量(如主机名、IP 地址):
yaml
---
- hosts: node1
tasks:
- name: 输出指定FACTS
debug:
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 信息:
bash[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:
bash[bq@controller web]$ ansible node1 -m setup -a 'gather_subset=network' # 只输出网络相关的FACTS(如接口、IP、MAC等)
关闭 FACTS 收集
默认情况下,play 会自动收集 FACTS,但以下场景可关闭:
- 不使用任何 FACTS,想加快 play 执行速度
- 受管主机无法运行
setup
模块(如缺少依赖) - 需先安装软件再收集 FACTS
关闭方式:
-
在 play 中设置:
yaml--- - name: 关闭自动FACTS收集 hosts: node1 gather_facts: no # 关闭自动收集
-
在 Ansible 配置文件中全局设置:
ini[defaults] gathering = explicit # 全局关闭自动收集,需手动调用setup模块
手动收集 :即使关闭自动收集,仍可通过setup
模块手动收集:
yaml
tasks:
- name: 手动收集FACTS
setup: # 显式调用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,观察变量值的变化,验证优先级
步骤详解
-
环境准备:
bash# 创建变量文件 [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
):yaml--- - name: 验证变量优先级 hosts: node1 gather_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 并观察结果:
bash# 带命令行变量执行(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)
以此类推,可逐步验证各位置变量的优先级。
- 第一个
如涉及版权问题请联系作者处理!!!