Ansible Vault #

什么是 Ansible Vault? #

Ansible Vault 是 Ansible 内置的加密工具,用于加密敏感数据,如密码、密钥、证书等,确保机密信息不会以明文形式存储。

text
┌─────────────────────────────────────────────────────────────┐
│                    Vault 工作流程                            │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  明文文件               加密                 解密            │
│  ──────────            ──────────           ──────────      │
│  password: secret      $ANSIBLE_VAULT       password: secret │
│  api_key: key123       1.1...               api_key: key123  │
│                        AES256...                             │
│                                                              │
│                        加密密码保护                           │
│                                                              │
└─────────────────────────────────────────────────────────────┘

创建加密文件 #

创建新的加密文件 #

bash
# 创建加密的 YAML 文件
ansible-vault create secrets.yml

# 会提示输入密码,然后打开编辑器
# 输入内容后保存退出,文件自动加密

加密现有文件 #

bash
# 加密现有文件
ansible-vault encrypt secrets.yml

# 加密多个文件
ansible-vault encrypt file1.yml file2.yml file3.yml

使用密码文件 #

bash
# 使用密码文件创建
ansible-vault create --vault-password-file ~/.vault_pass secrets.yml

# 使用密码文件加密
ansible-vault encrypt --vault-password-file ~/.vault_pass secrets.yml

编辑加密文件 #

编辑加密文件 #

bash
# 编辑加密文件
ansible-vault edit secrets.yml

# 使用密码文件
ansible-vault edit --vault-password-file ~/.vault_pass secrets.yml

查看加密文件 #

bash
# 查看加密文件内容
ansible-vault view secrets.yml

# 使用密码文件
ansible-vault view --vault-password-file ~/.vault_pass secrets.yml

解密文件 #

解密文件 #

bash
# 解密文件(永久解密)
ansible-vault decrypt secrets.yml

# 解密到标准输出
ansible-vault decrypt --output=- secrets.yml

# 解密到新文件
ansible-vault decrypt secrets.yml --output=secrets_decrypted.yml

临时解密使用 #

bash
# 执行 Playbook 时提供密码
ansible-playbook site.yml --ask-vault-pass

# 使用密码文件
ansible-playbook site.yml --vault-password-file ~/.vault_pass

# 使用多个密码文件
ansible-playbook site.yml --vault-password-file pass1.txt --vault-password-file pass2.txt

修改密码 #

修改加密密码 #

bash
# 修改密码
ansible-vault rekey secrets.yml

# 使用密码文件修改
ansible-vault rekey --vault-password-file ~/.vault_pass secrets.yml

# 使用新密码文件
ansible-vault rekey --new-vault-password-file ~/.new_vault_pass secrets.yml

加密字符串 #

加密单个字符串 #

bash
# 加密字符串
ansible-vault encrypt_string 'my_secret_password' --name 'db_password'

# 输出
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          663864396539666364663166363964...

加密并保存到文件 #

bash
# 加密字符串并保存
ansible-vault encrypt_string 'my_secret_password' --name 'db_password' >> vars.yml

# 从 stdin 读取
echo 'my_secret_password' | ansible-vault encrypt_string --stdin-name 'db_password'

在 Playbook 中使用加密字符串 #

yaml
---
- name: Use encrypted string
  hosts: databases
  vars:
    db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          663864396539666364663166363964...
  
  tasks:
    - name: Configure database
      mysql_user:
        name: appuser
        password: "{{ db_password }}"

使用加密文件 #

加密变量文件 #

yaml
# secrets.yml (加密文件)
---
db_root_password: SuperSecretPassword123!
db_app_password: AppPassword456!
api_key: sk-1234567890abcdef
ssl_certificate: |
  -----BEGIN CERTIFICATE-----
  MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA0G...
  -----END CERTIFICATE-----
yaml
# site.yml
---
- name: Deploy application
  hosts: app_servers
  vars_files:
    - secrets.yml
  
  tasks:
    - name: Configure database
      mysql_user:
        name: appuser
        password: "{{ db_app_password }}"

加密 Inventory 变量 #

yaml
# inventory/group_vars/databases.yml (加密文件)
---
mysql_root_password: "{{ vault_mysql_root_password }}"
mysql_replication_password: "{{ vault_mysql_replication_password }}"

密码管理 #

密码文件 #

bash
# 创建密码文件
echo "my_vault_password" > ~/.vault_pass

# 设置权限
chmod 600 ~/.vault_pass

配置文件指定密码文件 #

ini
# ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass

使用脚本获取密码 #

bash
#!/bin/bash
# ~/.vault_pass.sh

# 从环境变量获取
echo $VAULT_PASSWORD

# 或从密钥管理服务获取
# aws ssm get-parameter --name "/ansible/vault_password" --with-decryption --query "Parameter.Value" --output text
ini
# ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass.sh

多密码管理 #

使用 Vault ID #

bash
# 使用 Vault ID 创建文件
ansible-vault create --vault-id prod@~/.vault_prod secrets_prod.yml
ansible-vault create --vault-id dev@~/.vault_dev secrets_dev.yml

# 使用 Vault ID 加密
ansible-vault encrypt --vault-id prod@~/.vault_prod secrets_prod.yml

# 执行时指定 Vault ID
ansible-playbook site.yml --vault-id prod@~/.vault_prod --vault-id dev@~/.vault_dev

多密码文件结构 #

text
project/
├── .vault/
│   ├── prod_pass    # 生产环境密码
│   ├── staging_pass # 预发环境密码
│   └── dev_pass     # 开发环境密码
├── inventory/
│   ├── production/
│   │   └── group_vars/
│   │       └── secrets.yml    # 使用 prod_pass 加密
│   ├── staging/
│   │   └── group_vars/
│   │       └── secrets.yml    # 使用 staging_pass 加密
│   └── development/
│       └── group_vars/
│           └── secrets.yml    # 使用 dev_pass 加密
└── ansible.cfg
ini
# ansible.cfg
[defaults]
vault_identity_list = prod@.vault/prod_pass, staging@.vault/staging_pass, dev@.vault/dev_pass

最佳实践 #

1. 分离敏感数据 #

text
inventory/
├── group_vars/
│   ├── all.yml           # 非敏感变量
│   ├── webservers.yml    # 非敏感变量
│   └── vault/
│       └── all.yml       # 加密的敏感变量

2. 使用变量引用 #

yaml
# inventory/group_vars/all.yml (明文)
---
db_host: localhost
db_port: 3306
db_user: appuser
db_password: "{{ vault_db_password }}"

# inventory/group_vars/vault/all.yml (加密)
---
vault_db_password: SuperSecretPassword123!

3. 版本控制 #

gitignore
# .gitignore
.vault_pass
.vault/
*.pass

# 加密文件应该提交到版本控制
# !secrets.yml

4. 密码管理策略 #

bash
# 开发环境:使用密码文件
echo "dev_password" > .vault_dev_pass

# 生产环境:使用密钥管理服务
# AWS Secrets Manager
aws secretsmanager get-secret-value --secret-id ansible/vault_password --query SecretString --output text > .vault_prod_pass

# HashiCorp Vault
vault kv get -field=password secret/ansible/vault > .vault_prod_pass

5. CI/CD 集成 #

yaml
# .gitlab-ci.yml
deploy:
  stage: deploy
  script:
    - echo "$VAULT_PASSWORD" > .vault_pass
    - ansible-playbook -i inventory/production site.yml --vault-password-file .vault_pass
    - rm .vault_pass
  only:
    - main
yaml
# GitHub Actions
- name: Deploy with Ansible
  env:
    VAULT_PASSWORD: ${{ secrets.VAULT_PASSWORD }}
  run: |
    echo "$VAULT_PASSWORD" > .vault_pass
    ansible-playbook -i inventory/production site.yml --vault-password-file .vault_pass
    rm .vault_pass

完整示例 #

项目结构 #

text
project/
├── ansible.cfg
├── .vault_pass
├── inventory/
│   ├── production/
│   │   ├── hosts
│   │   └── group_vars/
│   │       ├── all.yml
│   │       └── vault/
│   │           └── all.yml
│   └── staging/
│       ├── hosts
│       └── group_vars/
│           ├── all.yml
│           └── vault/
│               └── all.yml
├── playbooks/
│   └── site.yml
└── roles/
    └── app/

配置文件 #

ini
# ansible.cfg
[defaults]
inventory = inventory/production
vault_password_file = .vault_pass
host_key_checking = False
retry_files_enabled = False

变量文件 #

yaml
# inventory/production/group_vars/all.yml
---
app_name: myapp
app_port: 8080
db_host: db.production.example.com
db_port: 3306
db_name: "{{ app_name }}_production"
db_user: "{{ app_name }}"
db_password: "{{ vault_db_password }}"
api_key: "{{ vault_api_key }}"
yaml
# inventory/production/group_vars/vault/all.yml (加密)
---
vault_db_password: SuperSecretProductionPassword!
vault_api_key: prod_api_key_1234567890abcdef
vault_ssl_cert: |
  -----BEGIN CERTIFICATE-----
  MIIDXTCCAkWgAwIBAgIJAJC1HiIAZAiUMA0G...
  -----END CERTIFICATE-----

Playbook #

yaml
# playbooks/site.yml
---
- name: Deploy application
  hosts: app_servers
  become: yes
  vars_files:
    - inventory/production/group_vars/vault/all.yml
  
  tasks:
    - name: Configure database connection
      template:
        src: templates/db_config.yml.j2
        dest: /etc/app/db_config.yml
        owner: appuser
        group: appuser
        mode: '0600'
    
    - name: Deploy SSL certificate
      copy:
        content: "{{ vault_ssl_cert }}"
        dest: /etc/app/ssl/cert.pem
        owner: root
        group: root
        mode: '0644'

常见问题 #

忘记密码 #

bash
# 如果忘记密码,无法恢复加密文件
# 建议备份密码文件或使用密钥管理服务

批量加密 #

bash
# 批量加密文件
for file in inventory/*/group_vars/vault/*.yml; do
  ansible-vault encrypt "$file"
done

检查文件是否加密 #

bash
# 检查文件头
head -1 secrets.yml
# 加密文件以 $ANSIBLE_VAULT 开头

下一步 #

现在你已经掌握了 Ansible Vault,接下来学习 最佳实践 了解如何编写高质量的 Ansible 代码!

最后更新:2026-03-29