ansible执行playbook时能自动解密vault加密变量,前提是必须显式提供正确密码:可用--ask-vault-pass交互输入、--vault-password-file指定权限为600的密码文件,或通过ansible_vault_password_file环境变量传入;vars_files加载加密yaml后,其中变量(如db_password)可直接引用,无需额外处理。

Ansible 执行 Playbook 时能自动解密 Vault 加密的变量,前提是提供正确的 Vault 密码 —— 不是“能不能解”,而是“密码怎么给、给对没、给得稳不稳”。
执行时必须显式提供 Vault 密码
Ansible 不会默认读取任何密码源。即使 secrets.yml 已用 ansible-vault create 加密,运行 ansible-playbook deploy.yml 时若不带解密参数,会直接报错:
$ ansible-playbook deploy.yml ERROR! Attempting to decrypt but no vault secrets found
必须用以下任一方式明确传入密码:
-
--ask-vault-pass:交互式输入(适合本地调试) -
--vault-password-file /path/to/pass.txt:从文件读取(单行纯文本,权限应为600) -
ANSIBLE_VAULT_PASSWORD_FILE=/path/to/pass.txt ansible-playbook ...:通过环境变量指定(CI/CD 中更可控)
vars_files 加载加密文件后,变量可直接引用
只要解密成功,vars_files 引入的加密 YAML 文件里定义的变量(如 db_password)和普通变量完全等效,无需额外解包或转换:
- name: Deploy app
hosts: webservers
vars_files:
- secrets.yml # ← 此文件内容是 AES256 加密的
tasks:
- name: Use decrypted password
ansible.builtin.debug:
msg: "Connecting with {{ db_password }}"
注意:secrets.yml 必须是完整 YAML 格式(不能是裸字符串),且其中不能包含未被 Vault 加密的敏感值混用。
常见失败原因:Vault ID 不匹配或密码文件权限错误
如果用了 --vault-id dev@dev-pass.txt,但 dev-pass.txt 里写的不是对应 Vault ID 的密码,或者该文件被其他用户可读(如权限是 644),Ansible 会静默拒绝读取并报错:
ERROR! Error while reading /tmp/dev-pass.txt: Permission denied
关键检查点:
- 密码文件是否仅当前用户可读写(
chmod 600 /path/to/pass.txt) - 若用
--vault-id label@file,确认label和加密时用的标签一致(ansible-vault encrypt --vault-id dev secrets.yml→ 解密也得用--vault-id dev@...) - CI/CD 中避免把密码明文 echo 进文件;优先用 Secret 注入后
printf "%s" "$SECRET" > /tmp/vault-pass,再立即chmod 600
加密字符串嵌入 Playbook 时需注意格式
用 ansible-vault encrypt_string 'mypass' --name 'api_token' 生成的 !vault | 块,必须原样粘贴进 YAML 文件,且所在层级要合法:
api_token: !vault |
$ANSIBLE_VAULT;1.1;AES256
64396437306633393735313832303232306165656463363639376165626236346465666136366162
...
常见误操作:
- 手动删掉缩进或换行,导致解析失败
- 把
!vault |块放在 list item 内部(YAML 不支持) - 在
vars:下直接写!vault |而没给变量名(必须有 key,如api_token:)
最稳妥的做法仍是把所有敏感值集中到独立加密文件,而不是散落在多个 Playbook 里 —— 后续轮换密码、审计权限、CI/CD 配置都更清晰。Vault 不难用,难的是让密码流经每个环节时都不落地、不越权、不混淆。











