Ansible变量与机密管理总结
一、Ansible变量基础
1. 变量定义规则
- 组成字符:仅允许字母、数字、下划线(
_
) - 命名开头:必须以字母开头,不能以数字或下划线开头
- 关键字限制:不可使用Ansible内置关键字(如
tasks
、hosts
等)作为变量名
2. 变量优先级(从高到低)
优先级 | 变量范围 | 说明 |
---|---|---|
1 | Global(全局) | 命令行传递变量(-e 参数)、Ansible配置文件(ansible.cfg )中定义的变量 |
2 | Play(剧本) | Playbook中通过vars 、vars_files 定义的变量 |
3 | Host(主机) | Inventory清单、主机事实变量(Facts)、register 注册的变量、host_vars /group_vars 目录定义的变量 |
注:若变量重复定义,优先级高的变量会覆盖优先级低的变量。
二、变量分类与详细用法
1. 事实变量(Facts)
定义
由Ansible自动收集的受控主机信息(如系统版本、IP地址、硬件配置等),无需手动定义,可直接调用。
查看方式
通过setup
模块收集指定主机的所有事实变量,输出到文件查看:
ansible node1 -m setup > node1_facts.txt
常用事实变量及作用
变量名 | 作用 | 示例用法 |
---|---|---|
ansible_default_ipv4.address |
获取受控主机默认IPv4地址 | msg: "主机IP: {{ ansible_default_ipv4.address }}" |
ansible_<网卡名>.ipv4.address |
获取指定网卡的IPv4地址(如ansible_ens160.ipv4.address ) |
msg: "ens160网卡IP: {{ ansible_ens160.ipv4.address }}" |
ansible_fqdn |
获取受控主机完全合格域名(FQDN) | msg: "FQDN: {{ ansible_fqdn }}" |
ansible_hostname |
获取受控主机短主机名 | msg: "主机名: {{ ansible_hostname }}" |
ansible_memtotal_mb |
获取受控主机总内存大小(单位:MB) | msg: "总内存: {{ ansible_memtotal_mb }}MB" |
ansible_bios_version |
获取受控主机BIOS版本 | msg: "BIOS版本: {{ ansible_bios_version }}" |
ansible_devices.<硬盘名>.size |
获取指定硬盘大小(如ansible_devices.vda.size ) |
msg: "vda硬盘大小: {{ ansible_devices.vda.size }}" |
ansible_lvm.vgs |
获取受控主机LVM卷组信息 | msg: "LVM卷组: {{ ansible_lvm.vgs }}" |
2. 内置变量(Built-in Variables)
定义
Ansible自带的通用变量,用于获取清单、主机组等基础信息,无需手动定义。
常用内置变量及作用
变量名 | 作用 | 示例用法 |
---|---|---|
groups.all |
列出Inventory中所有主机 | msg: "所有主机: {{ groups.all }}" (输出如[node1, node2] ) |
group_names |
列出当前主机所属的所有主机组 | msg: "所属组: {{ group_names }}" (输出如[net] ) |
inventory_hostname |
获取当前主机在Inventory中的名称 | msg: "清单主机名: {{ inventory_hostname }}" (输出如node1 ) |
play_hosts |
列出当前Play中所有目标主机 | msg: "Play目标主机: {{ play_hosts }}" (输出如[node1, node2] ) |
inventory_dir |
获取Inventory清单文件所在目录路径 | msg: "清单目录: {{ inventory_dir }}" (输出如/etc/ansible ) |
ansible_version |
获取Ansible版本信息(含主版本、次版本等) | msg: "Ansible版本: {{ ansible_version.full }}" (输出如2.9.18 ) |
3. 自定义变量(手动定义)
(1)vars
直接定义(Play内临时变量)
- 作用:在Playbook的
vars
段中直接定义变量,仅在当前Play内生效。 - 用法示例:
---
- name: 测试vars定义变量
hosts: node1
vars:
aa: 11 # 普通变量
bb: 22 # 普通变量
cc: # 字典类型变量
a1: c31
a2: c32
tasks:
- name: 输出普通变量aa
debug:
msg: "{{ aa }}" # 输出11
- name: 输出字典变量cc的a1值
debug:
msg: "{{ cc.a1 }}" # 输出c31
(2)vars_files
引用变量文件(外部变量文件)
- 作用:将变量存储在外部YAML文件中,通过
vars_files
引用,便于批量管理变量。 - 用法示例:
- 创建外部变量文件
/etc/ansible/var.yml
:
aa: 11 bb: 22 cc: a1: c31 a2: c32
- 在Playbook中引用:
--- - name: 测试vars_files引用变量 hosts: node1 vars_files: /etc/ansible/var.yml # 引用外部变量文件 tasks: - name: 输出变量aa debug: msg: "{{ aa }}" # 输出11
- 创建外部变量文件
(3)register
注册变量(任务结果变量)
- 作用:将某个任务的执行结果(如命令输出、返回码)注册为变量,供后续任务调用。
- 用法示例:
---
- name: 测试register注册变量
hosts: node1
tasks:
- name: 执行shell命令(查看/tmp/zz文件)
shell: "cat /tmp/ycy"
register: ycy # 将命令结果注册为变量ycy
- name: tast
debug:
msg: "{{ ycy }}" ##输出结果如下
- name:
debug:
var: ycy ##输出ycy的值
- name: 输出变量ycy的返回码(rc=0表示执行成功)
debug:
msg: "{{ ycy.rc }}" # 输出0
- name: 输出命令的标准输出
debug:
msg: "{{ ycy.stdout }}" # 输出/tmp/ycy文件内容
常用结果字段:
zz.rc
:任务返回码(0=成功,非0=失败)zz.stdout
:任务标准输出zz.stderr
:任务错误输出zz.changed
:是否修改了主机状态(true
/false
)[student@master ansible]$ ansible-playbook test3.yml ok: [node1] => { "msg": { "changed": true, "cmd": "cat /tmp/ycy", "delta": "0:00:00.003165", "end": "2025-09-02 01:52:54.778478", "failed": false, "msg": "", "rc": 0, "start": "2025-09-02 01:52:54.775313", "stderr": "", "stderr_lines": [], "stdout": "add", "stdout_lines": [ "add" ] } } TASK [debug] ***************************************************************************************************** ok: [node1] => { "ycy": { "changed": true, "cmd": "cat /tmp/ycy", "delta": "0:00:00.003165", "end": "2025-09-02 01:52:54.778478", "failed": false, "msg": "", "rc": 0, "start": "2025-09-02 01:52:54.775313", "stderr": "", "stderr_lines": [], "stdout": "add", "stdout_lines": [ "add" ] } } TASK [debug] ***************************************************************************************************** ok: [node1] => { "msg": "0" } TASK [debug] ***************************************************************************************************** ok: [node1] => { "msg": "add" } node1 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(4)set_fact
定义变量(动态变量)
- 作用:类似Shell的变量赋值,可将现有变量值或字符串赋值给新变量,支持动态计算。
- 用法示例:
---
- name: 测试set_fact定义变量
hosts: node1
tasks:
- name: 将事实变量赋值给新变量
set_fact:
host_ip: "{{ ansible_default_ipv4.address }}" # 新变量host_ip=默认IP
- name: 输出新变量
debug:
msg: "主机IP: {{ host_ip }}" # 输出默认IP
(5)命令行传递变量(-e
参数)
- 作用:通过
ansible-playbook
命令行临时传递变量,优先级最高,适合临时修改变量值。 - 用法示例:
- 创建Playbook
d.yml
:
--- - name: 测试命令行传递变量 hosts: node1 tasks: - name: 输出命令行变量name1 debug: msg: "name1: {{ name1 }}" - name: 输出命令行变量name2 debug: msg: "name2: {{ name2 }}"
- 命令行传递变量并执行:
ansible-playbook d.yml -e 'name1=tom name2=marry'
- 输出结果:
姓名1: tom
、姓名2: marry
- 创建Playbook
(6)Inventory清单变量
- 作用:在Inventory清单文件中为单个主机或主机组定义变量,仅对目标主机/组生效。
① 清单内直接定义
- 示例(
/etc/ansible/hosts
):
# 单个主机变量(直接跟在主机后)
node1 vars1=hello vars2=hi
# 主机组变量(通过[组名:vars]段定义)
[net]
node1
node2
[net:vars]
vars1=hello # 所有net组主机的变量vars1=hello
vars2=hi # 所有net组主机的变量vars2=hi
- Playbook引用示例:
---
- name: 测试清单变量
hosts: node1
tasks:
- name: 输出清单变量vars1
debug:
msg: "vars1: {{ vars1 }}" # 输出hello
② host_vars
/group_vars
目录定义
作用:通过专用目录存储变量文件,结构更清晰,支持YAML格式。
目录规则:
host_vars
:存储单个主机的变量,文件名为主机名(如node1
或node1.yml
)group_vars
:存储主机组的变量,文件名为组名(如net
或net.yml
)
优先级:同目录下,无后缀文件名(如
node1
)优先级高于YAML后缀文件(如node1.yml
)。示例:
- 创建
host_vars
目录及变量文件:
mkdir /etc/ansible/host_vars vim /etc/ansible/host_vars/node1 # 无后缀文件 vim /etc/ansible/host_vars/node1.yml ##优先级低于node1 当两个文件同时存在相同的变量,会优先执行node1的变量值。
- 写入变量(YAML格式):
vars1: groupvars1 vars2: groupvars2
- Playbook引用:
--- - name: 测试host_vars变量 hosts: node1 tasks: - name: 输出vars1 debug: msg: "{{ vars1 }}" # 输出groupvars1
- 创建
(7)with_items
迭代变量(多值变量)
- 作用:为变量赋予多个值,通过循环执行任务,适合批量操作(如批量输出、批量创建文件)。
- 用法示例:
---
- name: 测试with_items迭代变量
hosts: node1
tasks:
- name: 循环执行shell命令(输出多个值)
shell: "echo {{ item }}"
with_items: # 变量item依次取haha、heihei、hehe
- haha
- heihei
- hehe
register: hi_var # 注册循环结果到hi_var
- name: 输出第一个值的结果
debug:
var: hi_var.results[0].stdout # 输出haha
- name: 输出第二个值的结果
debug:
var: hi_var.results[1].stdout # 输出heihei
关键字段:
hi_var.results
为列表,存储每次循环的结果,通过索引([0]
/[1]
)访问单个结果。[student@master ansible]$ ansible-playbook ycy7.yml ok: [node1] TASK [test shell cmd] ******************************************************************************************** changed: [node1] => (item=ycy) changed: [node1] => (item=namcy) changed: [node1] => (item=gd) TASK [print test1] *********************************************************************************************** ok: [node1] => { "msg": "luoqi_var.results[0].sudout" } TASK [print test2] *********************************************************************************************** ok: [node1] => { "msg": "luoqi_var.results[1].sudout" } node1 : ok=4 changed=1
三、Ansible机密管理(Ansible Vault)
1. 作用
加密存储敏感数据(如密码、API密钥、用户密码等),避免敏感信息以明文形式存储在Playbook或变量文件中,降低安全风险。
2. 核心命令(ansible-vault
)
命令 | 作用 | 示例 |
---|---|---|
ansible-vault create <file> |
创建新的加密文件(默认用vi编辑) | ansible-vault create secret.yml (需输入密码) |
ansible-vault view <file> |
查看加密文件内容(需输入密码) | ansible-vault view secret.yml |
ansible-vault edit <file> |
编辑加密文件(需输入密码,编辑后自动重新加密) | ansible-vault edit secret.yml |
ansible-vault encrypt <file> |
加密已存在的明文文件 | ansible-vault encrypt plain.yml (需输入密码) |
ansible-vault decrypt <file> |
永久解密加密文件(解密后为明文) | ansible-vault decrypt secret.yml (需输入密码) |
ansible-vault decrypt <file> --output <newfile> |
解密文件并保存为新文件(原文件仍加密) | ansible-vault decrypt secret.yml --output plain.yml |
ansible-vault rekey <file> |
修改加密文件的密码 | ansible-vault rekey secret.yml (需输入旧密码和新密码) |
3. 执行加密Playbook的方法
加密后的Playbook无法直接执行,需通过以下方式提供解密密码:
(1)交互式输入密码(--ask-vault-pass
)
ansible-playbook --ask-vault-pass secret.yml
# 执行时会提示输入Vault密码,输入正确后执行
(2)密码文件传递(--vault-id <密码文件>
)
- 创建密码文件(如
secret.txt
),写入Vault密码(仅一行):
echo "redhat" > secret.txt
chmod 600 secret.txt # 限制文件权限,避免他人访问
- 通过密码文件执行加密Playbook:
ansible-playbook --vault-id secret.txt secret.yml
(3)临时交互密码(--vault-id @prompt
)
ansible-playbook --vault-id @prompt secret.yml
# 效果同--ask-vault-pass,提示输入密码
以下是Ansible变量执行方法的总结,涵盖不同类型变量的定义、调用及执行流程:
一、变量执行核心流程
- 定义变量:通过不同方式声明变量(内置/自定义/事实变量等)
- 调用变量:在Playbook中使用
{{ 变量名 }}
语法引用 - 执行验证:通过
ansible-playbook
运行并查看变量生效结果
二、各类变量的执行方法
1. 事实变量(Facts)
执行特点:自动收集,无需手动定义,直接调用
执行步骤:
- 无需额外配置,Playbook默认自动收集(可通过
gather_facts: no
关闭) - 在任务中直接使用
{{ 事实变量名 }}
调用 - 执行Playbook验证结果
- 无需额外配置,Playbook默认自动收集(可通过
示例执行:
# playbook.yml - hosts: node1 tasks: - name: 显示主机IP debug: msg: "IP地址: {{ ansible_default_ipv4.address }}"
运行命令:
ansible-playbook playbook.yml
2. 内置变量
执行特点:Ansible自带,无需定义,直接在任意Playbook中调用
执行步骤:
- 直接在任务中使用
{{ 内置变量名 }}
- 执行Playbook查看结果
- 直接在任务中使用
示例执行:
# playbook.yml - hosts: all tasks: - name: 显示当前主机名 debug: msg: "当前主机: {{ inventory_hostname }}"
运行命令:
ansible-playbook playbook.yml
3. 自定义变量(核心执行方法)
定义方式 | 执行步骤 | 示例命令 |
---|---|---|
vars直接定义 | 1. 在Playbook的vars 段声明变量2. 任务中用 {{ 变量名 }} 调用3. 直接执行Playbook |
ansible-playbook playbook.yml |
vars_files引用文件 | 1. 创建外部变量文件(如vars.yml )2. Playbook中通过 vars_files 引用3. 执行Playbook |
ansible-playbook playbook.yml |
register注册变量 | 1. 在任务中用register: 变量名 捕获结果2. 后续任务中调用 {{ 变量名.字段 }} 3. 执行Playbook查看输出 |
ansible-playbook playbook.yml |
set_fact动态定义 | 1. 用set_fact: 新变量={{ 源变量 }} 定义2. 任务中调用新变量 3. 执行Playbook |
ansible-playbook playbook.yml |
命令行传递(-e) | 1. Playbook中预留变量名 2. 执行时通过 -e "变量=值" 传递3. 动态生效 |
ansible-playbook playbook.yml -e "user=admin port=8080" |
Inventory清单变量 | 1. 在清单文件或host_vars /group_vars 中定义2. Playbook中直接调用 3. 执行Playbook |
ansible-playbook -i inventory.yml playbook.yml |
with_items迭代变量 | 1. 用with_items: [值1, 值2] 定义列表2. 任务中用 {{ item }} 循环调用3. 执行Playbook查看循环结果 |
ansible-playbook playbook.yml |
4. 加密变量(Ansible Vault)
- 执行特点:需解密后执行,保护敏感变量
- 执行步骤:
- 创建加密变量文件:
ansible-vault create secret.yml
- 在Playbook中引用加密文件:
vars_files: secret.yml
- 执行时提供解密密码:
- 交互式:
ansible-playbook --ask-vault-pass playbook.yml
- 密码文件:
ansible-playbook --vault-id pass.txt playbook.yml
- 交互式:
- 创建加密变量文件:
三、变量执行优先级验证方法
- 创建测试Playbook:
# priority_test.yml - hosts: node1 vars: test_var: "Play级变量" tasks: - name: 输出变量值 debug: var: test_var
- 通过不同方式定义同名变量:
- 清单文件定义:
node1 test_var="清单变量"
- 命令行传递:
-e "test_var=命令行变量"
- 清单文件定义:
- 依次执行验证覆盖关系:
ansible-playbook priority_test.yml # 输出Play级变量 ansible-playbook -i inventory.yml priority_test.yml # 输出清单变量 ansible-playbook priority_test.yml -e "test_var=命令行变量" # 输出命令行变量
四、常见执行问题及解决
变量未定义错误:
- 检查变量名拼写(区分大小写)
- 确认变量定义位置是否在当前作用域内
事实变量无法获取:
- 检查是否禁用了facts收集(
gather_facts: no
) - 确保受控主机网络通畅,Ansible可正常连接
- 检查是否禁用了facts收集(
加密变量解密失败:
- 确认密码正确
- 检查加密文件是否损坏(可尝试重新加密)
通过以上方法,可清晰掌握Ansible各类变量的执行逻辑,确保变量在自动化任务中正确生效。