引言 (Introduction)
随着云计算和容器化技术的快速发展,企业在构建现代化应用时对安全性和合规性的要求日益提高。然而,在容器化环境中,敏感数据(如 API 密钥、数据库凭据、TLS 证书)的安全管理成为保障系统安全的关键挑战。
HashiCorp Vault 作为业界领先的开源秘密管理工具,提供了集中化、动态化和高安全性的解决方案,能够有效应对这些挑战。其通过动态秘密生成、细粒度访问控制和加密即服务等功能,为 TKE 环境中的外部密钥管理提供了灵活且强大的支持。
本文将结合 Vault 的核心架构与 TKE 的容器化特性,介绍具体的集成方法、配置步骤和最佳实践,旨在帮助企业构建安全、高效的云原生密钥管理体系,满足合规性要求并提升 DevOps 效率。
Vault 介绍
What is Vault ?
Vault 提供集中化的Secret管理、数据加密和访问控制,解决传统硬编码凭据或分散管理带来的安全风险。其主要功能包括:
● Secret管理:安全存储和管理敏感数据,如 API 密钥、数据库密码、证书等,支持动态生成和定期轮换。
● 数据加密:通过加密即服务(Encryption as a Service)保护数据,支持静态数据加密和传输中数据加密。
● 身份认证与访问控制:基于角色和策略的访问控制(RBAC),支持多种身份认证方式(如 LDAP、Kubernetes、JWT 等)。
● 动态Secret
● :为数据库、云服务等生成临时凭据,降低泄露风险。例如,Vault 可以为数据库生成短生命周期的用户名和密码。
● 证书管理:自动生成、轮换和管理 TLS 证书,支持与公共或私有 CA 集成。
● 加密密钥管理:管理加密密钥的生命周期,支持密钥轮换和版本控制。
Why Vault ?
Kubernetes 原生提供了 Secret 对象来管理敏感信息。然而,原生 Secret 存在一些局限性:
● 静态存储: Secret 通常以 Base64 编码存储在 etcd(K8s 的数据存储)中。虽然可以加密 etcd,但这仍然是集群管理员需要额外关注的一个静态存储点。
● 权限管理粒度:RBAC 控制对 Secret 的访问,但配置相对复杂,且 Secret 一旦被 Pod 挂载,其内容对整个 Pod 内的所有容器都是可见的。
● 缺乏与外部密钥管理系统的原生集成: 企业通常使用专门的密钥管理系统(如 HashiCorp Vault、AWS Secrets Manager、Azure Key Vault、Google Secret Manager)来集中、安全地管理密钥。原生 Secret 需要手动或通过外部工具同步这些密钥。
● 密钥轮换: 当外部密钥管理系统中的密钥更新后,需要手动更新 K8s Secret 并重启相关 Pod 才能生效。
Vault 架构

Vault 的架构由以下关键组件构成:
● 核心 (Core) :负责 Vault 的核心逻辑,包括请求路由、认证、授权、审计和密钥管理。请求处理:解析客户端请求,调用认证方法、秘密引擎和策略检查。
● 存储后端 (Storage Backend):Vault 不直接存储数据,而是依赖外部存储后端保存加密的秘密和元数据。数据以加密形式存储,Vault 使用 Master Key(主密钥)进行加密/解密。
● 秘密引擎 (Secrets Engines):模块化组件,负责生成、管理和提供特定类型的秘密。每个秘密引擎独立配置,可按需启用,支持动态秘密生成以降低泄露风险。
● 认证方法 (Auth Methods):用于验证客户端身份,生成访问 Vault 的令牌(Token)。认证后,Vault 分配令牌,关联特定策略以控制访问权限。
● 策略 (Policies):定义客户端的访问权限,使用 HCL(HashiCorp Configuration Language)编写。基于角色的访问控制(RBAC),支持细粒度权限管理。
Vault 后端存储
Overview
特性 | Raft | Consul | S3/GCS/Azure | PostgreSQL |
---|---|---|---|---|
存储类型 | 本地(BoltDB) | 分布式键值存储 | 云对象存储 | 关系型数据库 |
HA 支持 | 是(3-5 节点) | 是 | 是(云厂商托管) | 是(视数据库配置) |
运维复杂性 | 低(内置) | 高(需 Consul 集群) | 低(云厂商托管) | 高(需数据库集群) |
性能 | 高(本地存储) | 中(网络依赖) | 中(网络依赖) | 中(事务开销) |
跨集群适用性 | 高(只需网络访问 Vault) | 高(需网络访问 Consul) | 中(云厂商绑定) | 中(需数据库集群) |
成本 | 低(仅磁盘) | 中(Consul 集群资源) | 高(云厂商收费) | 中(数据库资源) |
Integrated Storage (Raft)
Integrated Storage (Raft) 是 Vault 的内置存储后端,官方推荐。基于 Raft 协议实现的一种分布式一致性存储后端,适合中小型生产环境。它通过 Raft 协议和 BoltDB 提供加密存储、高可用性和高性能,无需外部依赖,简化部署和运维。
Integrated Storage 的优势:
● 架构简单:无需外部存储服务,Vault 内置 Raft 逻辑,部署和维护简单。
● 高可用:支持多节点集群(建议 3-5 节点),自动故障转移,提供强一致性读写,适合生产环境。
● 加密存储:所有数据在写入 BoltDB 前加密,使用 Vault 的加密密钥。
● 快照与备份:支持定期快照和手动备份,方便数据迁移和灾难恢复。
● 性能优化:本地存储(BoltDB)减少网络延迟,适合高性能场景。
● 动态扩展:支持动态添加或移除节点,新节点自动同步数据,无需手动干预。
配置样例
ini
disable_mlock = true
ui = true
cluster_name = "vault-integrated-storage"
storage "raft" {
path = "/vault/data/"
}# 配置后端存储为raft
listener "tcp" {
address = "[::]:8200"
cluster_address = "[::]:8201"
tls_disable = "true"
}
Vault Secret Engine
Overview
Secret Engine | 功能描述 | 典型用途 |
---|---|---|
Key/Value (KV) | 存储静态键值对秘密(如配置、密码),支持版本控制、元数据。 | 配置文件、API密钥、数据库密码 |
AWS | 动态生成AWS IAM凭据、STS令牌 | AWS EC2, S3, Lambda 等 |
Azure | 动态生成Azure服务主体(Service Principal) | Azure VM, Key Vault, SQL DB |
Database | 统一接口:为多种数据库动态生成短期账号/密码 | MySQL, PostgreSQL, Oracle, MongoDB 等 |
PKI | 动态签发X.509证书(TLS/SSL) | 替代传统CA,支持自动轮换 |
SSH | 生成一次性SSH OTP或签署SSH公钥 | 安全SSH服务器/客户端访问 |
Consul | 动态生成Consul ACL令牌 | 安全访问Consul服务发现 |
LDAP | 绑定OpenLDAP或其他LDAP服务管理用户 | 企业目录服务集成 |
OIDC | 提供OpenID Connect身份提供商(IdP)功能 | 单点登录(SSO) |
key/value
Key/Value 秘密引擎是 Vault 最简单、最通用的秘密存储方式,用于存储和管理任意键值对数据。支持版本控制、软删除和数据轮换,适合需要历史记录和恢复的场景。
使用流程

使用样例
ini
# 启用KV v2引擎
vault secrets enable -path=secret kv-v2
# 写入秘密
vault kv put secret/db-config \
username="admin" \
password="s3cr3tP@ss"
# 读取最新版本
vault kv get secret/db-config
# 读取特定版本
vault kv get -version=1 secret/db-config
# 列出路径
vault kv list secret/
# 删除版本 (标记删除)
vault kv delete -versions=2 secret/db-config
# 彻底销毁版本
vault kv destroy -versions=2 secret/db-config
database
Database 秘密引擎为数据库(如 MySQL)提供动态凭据管理,Vault 自动生成和管理数据库用户凭据,具有短生命周期和自动轮换功能,增强安全性。
使用流程

使用样例
ini
# 启用数据库引擎
vault secrets enable database
# 配置MySQL连接
vault write database/config/mysql-prod \
plugin_name=mysql-database-plugin \
connection_url="{{username}}:{{password}}@tcp(10.0.0.5:3306)/" \
allowed_roles="app-role" \
username="vault-admin" \
password="vault-admin-password"
# 创建角色
vault write database/roles/app-role \
db_name=mysql-prod \
creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; \
GRANT SELECT ON app_db.* TO '{{name}}'@'%';" \
default_ttl="1h" \
max_ttl="24h"
# 获取动态凭据
vault read database/creds/app-role
# 验证连接
mysql -u v-token-app-role-xyz123 -p'8f4cda6c-12e3-45ef-9b7a' -h 10.0.0.5
# 配置静态根凭据轮换
vault write -force database/rotate-root/mysql-prod
# 查看租约信息
vault lease lookup database/creds/app-role/abcd1234
Kubernetes
Kubernetes Secret Engine 允许 Vault 动态生成 Kubernetes 服务账户(Service Account)的对应token,支持动态生成短生命周期的 Service Account Token(TTL 可配置),可以跨多个 Kubernetes 集群、云平台或其他系统统一管理 Service Account Token 的生成、分配和生命周期。
使用流程

使用样例
- 创建 Vault Server 使用的Service Account
yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: vault
namespace: vault
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: k8s-minimal-secrets-abilities
rules:
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get"]
- apiGroups: [""]
resources: ["serviceaccounts", "serviceaccounts/token"]
verbs: ["create", "update", "delete"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings", "clusterrolebindings"]
verbs: ["create", "update", "delete"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles", "clusterroles"]
verbs: ["bind", "escalate", "create", "update", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: vault-token-creator-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: k8s-minimal-secrets-abilities
subjects:
- kind: ServiceAccount
name: vault
namespace: vault
- 创建 测试 使用的Service Account
yaml
apiVersion: v1
kind: Namespace
metadata:
name: test
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-service-account-with-generated-token
namespace: test
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: test-role-list-pods
namespace: test
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-role-abilities
namespace: test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: test-role-list-pods
subjects:
- kind: ServiceAccount
name: test-service-account-with-generated-token
namespace: test
- 配置Vault
bash
# 启用Kubernetes引擎
vault secrets enable kubernetes
# 创建角色
vault write -f kubernetes/config
vault write kubernetes/roles/my-role allowed_kubernetes_namespaces="*" service_account_name="test-service-account-with-generated-token" token_default_ttl="10m"
# 生成ServiceAccount令牌
vault write kubernetes/creds/my-role kubernetes_namespace=test
# 使用令牌访问K8s API
curl -H "Authorization: Bearer $TOKEN" https://k8s-api:6443/api/v1/pods
Vault AuthN method
Overview
方法名称 | 认证方式描述 | 适用场景 |
---|---|---|
Userpass | 用户名+密码认证(用户信息存储在Vault内部) | 内部用户/开发人员访问 |
AppRole | 机器/服务通过角色ID(Role ID)和密钥ID(Secret ID)认证 | CI/CD流水线、自动化服务 |
GitHub | 使用GitHub个人访问令牌(PAT)验证用户/团队身份 | 开发团队协作场景 |
AWS | 通过AWS IAM角色/实例元数据/Lambda函数认证 | AWS EC2, Lambda, IAM用户 |
Azure | 使用Azure AD身份/托管身份(Managed Identity)/服务主体认证 | Azure VM, 应用服务, AAD |
OIDC | 与OpenID Connect提供商(如Okta, Auth0)集成 | 企业SSO(单点登录) |
JWT/OIDC | 直接提交JWT令牌认证(可对接外部OIDC提供商) | 微服务认证、自定义身份系统集成 |
approle
AppRole 是一种面向机器或应用程序的认证方法,适合自动化工作流。它通过 RoleID(类似用户名)和 SecretID(类似密码)进行认证。
auth 流程

使用样例
ini
# 1. 启用AppRole认证
vault auth enable approle
# 2. 创建角色并绑定策略
vault write auth/approle/role/ci-cd-role \
token_policies="prod-db-access" \
secret_id_ttl=10m \
token_num_uses=5
# 3. 获取Role ID (静态配置)
vault read auth/approle/role/ci-cd-role/role-id
# 4. 生成Secret ID (动态获取)
vault write -f auth/approle/role/ci-cd-role/secret-id
# 5. 使用凭证登录
vault write auth/approle/login \
role_id="db-access-role" \
secret_id="a1b2c3d4-5678"
Userpass
UserPass 是一种面向人类用户的认证方法,通过用户名和密码对进行认证。它适用于需要人工交互的场景,如管理员或开发人员通过 CLI 或 UI 访问 Vault。
auth 流程

使用样例
ini
# 1. 启用Userpass认证
vault auth enable userpass
# 2. 创建用户账户
vault write auth/userpass/users/alice \
password="s3cr3tP@ss!" \
policies="dev-readonly" \
ttl="8h"
# 3. 用户登录 (CLI)
vault login -method=userpass username=alice password=s3cr3tP@ss!
# 4. 用户登录 (API)
curl --request POST \
--data '{"password": "s3cr3tP@ss!"}' \
http://127.0.0.1:8200/v1/auth/userpass/login/alice
Use Vault On K8S
Vault agent Injector
GitHub - hashicorp/vault-k8s: First-class support for Vault and Kubernetes.
通过Mutating Webhook拦截Pod创建事件,注入Vault Agent Sidecar容器,Agent负责认证Vault、获取Secret并渲染到共享内存卷。
功能特性
● 支持所有Vault动态Secret(如数据库凭据、PKI证书),通过Vault Agent管理租约。
● 需为每个集群配置独立的Vault认证方法(如Kubernetes认证),多集群管理复杂。
● Secrets存储在共享内存卷(tmpfs)中,作为文件供Pod消费。
安全特性
● 使用Kubernetes Service Account认证
● Secrets存储在内存卷,降低持久化风险
● 支持所有Vault认证方法
● 提供Secret缓存和自动轮换
典型适用场景
● 需要高灵活性,支持多种Vault Secret引擎
● 应用不希望直接依赖Kubernetes Secret
● 需要Secret缓存或复杂模板化
部署架构

使用样例
yaml
# webapp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
annotations:
vault.hashicorp.com/agent-inject: "true" # 启用注入
vault.hashicorp.com/role: "db-app" # Vault 角色名
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/db-role" # Secret路径
spec:
template:
spec:
serviceAccountName: webapp-sa # 匹配Vault角色绑定的SA
containers:
- name: app
image: nginx:latest
volumeMounts:
- name: vault-secrets
mountPath: /vault/secrets
volumes:
- name: vault-secrets
emptyDir:
medium: Memory
Vault Secret operator
使用Kubernetes Operator模式,通过CRD(如VaultStaticSecret)同步Vault Secret到Kubernetes Secret,支持动态Secret和滚动重启。
功能特性
● 支持多集群,通过SecretStore或ClusterSecretStore配置Vault连接,简化多集群管理。
● 支持静态、动态和PKI秘密,自动处理租约续订和轮换,支持滚动重启以更新应用。
● Secrets同步到Kubernetes原生Secret对象,可作为环境变量或文件使用。
安全特性
● 使用Kubernetes Service Account认证
● Secrets存储在etcd,可能需额外加密
● 提供细粒度访问控制和审计
● 支持动态Secret轮换和滚动重启
典型适用场景
● 希望与Kubernetes原生Secret集成
● 需要动态Secret管理和自动轮换
● 适合只需要简单Secret同步的场景
部署架构

使用样例
yaml
# vault-connection.yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultConnection
metadata:
name: prod-vault
spec:
address: "https://vault.prod:8200" #vault server 地址
# vault-auth-role.yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultAuth
metadata:
name: kubernetes-auth
spec:
vaultConnectionRef: prod-vault
method: kubernetes
mount: kubernetes
kubernetes:
role: db-app
serviceAccount: webapp-sa
# database-secret.yaml
apiVersion: secrets.hashicorp.com/v1beta1
kind: VaultDynamicSecret
metadata:
name: db-credentials
spec:
vaultConnectionRef: prod-vault
vaultAuthRef: kubernetes-auth
path: database/creds/db-role
refreshAfter: "5m" # 每5分钟轮换凭证
destination:
create: true
name: db-secret # 生成的K8s Secret名称
# 应用中既可以使用env 挂到pod中:
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Vault secrets-store-csi-driver
GitHub - hashicorp/vault-csi-provider: HashiCorp Vault Provider for Secret Store CSI Driver
使用CSI标准,通过SecretProviderClass CRD配置Vault Secret路径,CSI驱动在Pod创建时挂载Secret到文件系统。
功能特性
● 支持多集群,需在每个集群安装CSI驱动和Vault Provider,配置相对简单。
● 支持所有Vault动态Secret,CSI驱动管理租约续订,但无内置滚动重启功能。
● Secrets作为CSI卷挂载到Pod的文件系统中,可选择同步到Kubernetes Secret。
● DaemonSet模式在集群的每个节点上运行,负责处理挂载请求、与 Provider 交互、管理临时卷。
安全特性
● 使用Kubernetes Service Account认证
● Secrets通过CSI卷挂载,降低泄露风险
● 支持TLS/mTLS通信
● 可选同步到Kubernetes Secret
典型适用场景
● 希望直接挂载Secret到Pod文件系统
● 需要支持多云或外部Secret管理器
● 适合高安全性需求,不希望Secret存储在etcd
部署架构

使用样例
需要提前安装secrets-store-csi-driver
yaml
# vault-spc.yaml 配置 SecretProviderClass
apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
name: vault-db-creds
spec:
provider: vault
parameters:
vaultAddress: "https://vault.example.com:8200"
roleName: "csi-role"
objects: |
- objectPath: "kv/data/app/database"
secretKey: "username"
path: "db_user"
- objectPath: "kv/data/app/database"
secretKey: "password"
path: "db_pass"
# 可选:同步到Kubernetes Secret
secretObjects:
- secretName: "db-secret" # 生成的Secret名称
type: Opaque
data:
- key: "username"
objectName: "db_user"
- key: "password"
objectName: "db_pass"
# app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
spec:
serviceAccountName: app-sa # 必须匹配Vault角色
containers:
- name: app
image: nginx:latest
volumeMounts:
- name: db-creds
mountPath: "/etc/secrets"
readOnly: true
volumes:
- name: db-creds
csi:
driver: secrets-store.csi.k8s.io
readOnly: true
volumeAttributes:
secretProviderClass: "vault-db-creds" # 引用SecretProviderClass
External-Secret
通过Operator模式,使用SecretStore和ExternalSecret CRD,从Vault获取Secret并同步到Kubernetes Secret。
功能特性
● 支持多集群,通过ClusterSecretStore CRD配置,适合多云或混合环境。
● 仅支持KV Secret引擎,不支持动态Secret(如数据库凭据或PKI)。
● Secrets同步到Kubernetes原生Secret对象,可作为环境变量或文件使用。
安全特性
● 使用外部Secret管理器的认证(如Vault的Kubernetes认证)
● Secrets存储在etcd,需加密保护
● 提供访问控制和审计,但较弱
典型适用场景
● 希望简单集成外部Secret管理器(如Vault、AWS Secrets Manager)
● 应用依赖Kubernetes Secret作为环境变量
● 适合多云或混合环境
部署架构

使用样例
需要提前安装 external-secrets
yaml
# vault-secretstore.yaml
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: vault-backend
spec:
provider:
vault:
server: "https://vault.example.com:8200"
path: "secret"
version: "v2" # KV引擎版本
auth:
# 使用Kubernetes认证/也可以使用approle认证。
kubernetes:
mountPath: "kubernetes"
role: "eso-role"
serviceAccountRef:
name: eso-auth-sa # 专用ServiceAccount
# database-externalsecret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: "5m" # 同步间隔
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: db-secret # 生成的K8s Secret名称
data:
- secretKey: username
remoteRef:
key: database/creds/db-role
property: username # 指定Secret字段
- secretKey: password
remoteRef:
key: database/creds/db-role
property: password
# 应用中使用env 挂到pod中:
env:
- name: DB_USER
valueFrom:
secretKeyRef:
name: db-secret # 匹配ExternalSecret生成的Secret
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: db-secret
key: password