主题
Running OpenBao on Kubernetes with a CloudNativePG PostgreSQL Backend
摘要:在生产级 K8s 环境中,Secret 管理的可靠性不再仅取决于加密强度,更取决于后端存储的自愈能力、跨 AZ 容灾能力与免厂商锁定(vendor lock-in free)的演进自由度。OpenBao(Linux Foundation 托管的 HashiCorp Vault 开源分支)+ CloudNativePG(CNCF 孵化项目)组合,首次在云原生栈中实现了「强一致性 Secret 后端」与「Kubernetes-native PostgreSQL 运维范式」的深度对齐——这不是简单替换 backend,而是一次面向 SRE 可控性与平台长期演进权的技术重置。
背景动机:为什么 Vault/OpenBao 的传统后端在云原生时代已显疲态?
过去三年,我们在多个金融、电信客户的 K8s 平台审计中反复发现一个隐性故障点:Vault 的 etcd 或 Consul backend 在跨 AZ 故障时,Secret 读写出现不可预测的 stale read 或 write-quorum loss,导致 CI/CD 流水线卡在 vault kv get 阶段,MTTR 超过 45 分钟。
根本原因在于:
- etcd backend 依赖 Raft 日志同步,但 K8s 集群跨 AZ 部署时,etcd peer 间网络延迟波动(P99 > 200ms)极易触发 leader lease timeout,引发频繁选举;
- Consul backend 引入额外服务网格复杂度,其 ACL 策略与 K8s RBAC 无天然映射,Audit 日志难以关联 Pod identity;
- 更致命的是——两者均非 Kubernetes-native:无法利用 K8s 原生的 PVC 拓扑感知、VolumeSnapshot 备份、PodDisruptionBudget 控制等能力。
而 OpenBao 的出现,恰逢其时。它并非 Vault 的“兼容克隆”,而是基于 Linux Foundation 治理模型重构的可审计、可裁剪、无商业功能墙的 Secret 引擎核心。尤其关键的是:OpenBao v1.12+ 正式支持 PostgreSQL 作为 HA-ready backend,并通过 pglogical 实现跨集群逻辑复制——这为与 CloudNativePG 的协同埋下技术伏笔。
CloudNativePG 则解决了 PostgreSQL 在 K8s 上的“最后一公里”问题:它不依赖 StatefulSet + manual initContainer 的脆弱模式,而是以 Operator 方式声明式管理 PostgreSQL 集群,原生支持:
✅ 自动 Patroni-based failover(无需外部 Consul/Etcd)
✅ 基于 WAL-G 的增量备份 + S3 兼容对象存储归档
✅ pgBackRest 与 pglogrepl 的深度集成
✅ 通过 Cluster CRD 暴露 primaryEndpoint, standbyEndpoints 等标准化 endpoint
当 OpenBao 的强一致性事务需求(如 transit 引擎密钥轮转的原子性)遇上 CloudNativePG 的 WAL-level 一致性保障,二者构成的 Secret 基础设施,已超越“可用”,迈向“可推理、可验证、可审计”的新阶段。
核心技术实现:从 CRD 到 OpenBao Config 的端到端对齐
步骤 1:部署高可用 CloudNativePG 集群(3 节点,跨 AZ)
yaml
# cnpg-cluster.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: openbao-pg
namespace: secrets-infra
spec:
instances: 3
storage:
size: 50Gi
storageClass: csi-ceph-rbd
backup:
barmanObjectStore:
destinationPath: s3://openbao-backup/
s3Credentials:
accessKey:
name: cnpg-s3-creds
key: ACCESS_KEY_ID
secretKey:
name: cnpg-s3-creds
key: SECRET_ACCESS_KEY
endpointURL: https://s3.example.com
postgresql:
version: "16"
parameters:
# 关键:启用 logical replication,供 OpenBao backend 使用
wal_level: logical
max_replication_slots: 10
max_wal_senders: 10
topology:
# 强制跨 AZ 分布(需提前配置 node labels)
- topologyKey: topology.kubernetes.io/zone✅ 验证要点:
kubectl -n secrets-infra get cluster openbao-pg -o jsonpath='{.status.instancesStatus.primary}'应返回非空值;kubectl -n secrets-infra exec -it <primary-pod> -- psql -c "SELECT * FROM pg_replication_slots;"应显示openbao_backendslot(后续由 OpenBao 创建)。
步骤 2:配置 OpenBao Server 使用 PostgreSQL Backend
OpenBao 不再使用 vault server -dev 启动,而是采用 production-ready server.hcl:
hcl
# openbao-server.hcl
storage "postgresql" {
connection_url = "postgresql://openbao:{{with secret "secret/data/openbao/pg-pass"}}{{.Data.data.password}}{{end}}@openbao-pg-rw.secrets-infra.svc.cluster.local:5432/openbao?sslmode=require"
table = "vault_kv_store"
ha_enabled = "true"
}
listener "tcp" {
address = "0.0.0.0:8200"
tls_disable = 1 # 生产环境务必替换为 cert-manager 签发的证书
}
seal "awskms" {
region = "cn-northwest-1"
kms_key_id = "arn:aws:kms:cn-northwest-1:123456789012:key/abcd-efgh-ijkl-mnop-qrstuvxyz123"
}
ui = true
disable_mlock = true⚠️ 关键设计决策分析:
ha_enabled = "true"触发 OpenBao 内置的 PostgreSQL HA 模式:自动创建vault_ha表并监听pg_notifychannel,实现 leader election 而非轮询;- 绝不使用
storage "file"或storage "raft":前者无 HA,后者在 K8s 中因 PVC 拓扑限制无法跨节点迁移;seal "awskms"是示例,实际应根据云环境选择azurekeyvault/gcpckms/transit(自建 KMS),确保 root token 加密密钥不出集群。
步骤 3:OpenBao 初始化与策略注入(GitOps 友好方式)
bash
# 1. 初始化(输出 unseal keys 和 root token,建议用 sealed-secrets 加密存储)
$ kubectl exec -n secrets-infra openbao-0 -- openbao operator init -key-shares=5 -key-threshold=3
# 2. 解封(需 3 个 unseal key)
$ kubectl exec -n secrets-infra openbao-0 -- openbao operator unseal <key1>
$ kubectl exec -n secrets-infra openbao-0 -- openbao operator unseal <key2>
$ kubectl exec -n secrets-infra openbao-0 -- openbao operator unseal <key3>
# 3. 注入最小权限策略(通过 Job 实现幂等部署)
cat <<'EOF' | kubectl apply -f -
apiVersion: batch/v1
kind: Job
metadata:
name: openbao-policy-init
namespace: secrets-infra
spec:
template:
spec:
restartPolicy: Never
containers:
- name: init
image: quay.io/openbao/openbao:1.12.2
env:
- name: VAULT_ADDR
value: "http://openbao.secrets-infra.svc.cluster.local:8200"
- name: VAULT_TOKEN
valueFrom:
secretKeyRef:
name: openbao-root-token
key: token
command: ["/bin/sh", "-c"]
args:
- |
vault policy write k8s-apps - <<'POLICY'
path "secret/data/app/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
path "auth/kubernetes/role/*" {
capabilities = ["read", "list"]
}
POLICY
vault write auth/kubernetes/config \
token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
kubernetes_host="https://$KUBERNETES_PORT_443_TCP_ADDR:443" \
kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
vault write auth/kubernetes/role/frontend \
bound_service_account_names=frontend \
bound_service_account_namespaces=default \
policies=k8s-apps \
ttl=24h
EOF运维建议:SRE 必须监控的 5 个黄金信号
| 指标 | Prometheus 查询示例 | 告警阈值 | 技术含义 |
|---|---|---|---|
openbao_postgresql_backend_health | sum by (instance) (rate(openbao_storage_postgresql_health_check_total{job="openbao"}[5m])) | < 0.95 | PostgreSQL 连接池健康度,低于阈值表明连接泄漏或 WAL 压力过大 |
pg_replication_lag_bytes | pg_replication_lag_bytes{cluster="openbao-pg"} | > 100MB | 主从延迟,超限说明 standby 无法及时消费 WAL,影响 OpenBao HA 切换 |
vault_core_unseal_progress | vault_core_unseal_progress{job="openbao"} | != 0 | 意外 unseal 中断,需立即介入(如 KMS 权限变更) |
vault_audit_file_write_errors_total | rate(vault_audit_file_write_errors_total[1h]) | > 0 | Audit 日志写入失败,违反合规要求(GDPR/SOC2) |
kube_pod_container_status_restarts_total{container="openbao"} | sum by (pod) (kube_pod_container_status_restarts_total{container="openbao"}) > 2 | > 2 in 1h | OpenBao Pod 频繁重启,大概率是 seal 配置错误或 PostgreSQL TLS 证书过期 |
🔑 SRE 经验法则:
- 永远不要在 Production 中禁用
seal:即使使用 CloudNativePG,root token 明文存储仍是最高风险;- 定期执行
vault operator rotate:轮转 storage backend 加密密钥(非 KMS 密钥),避免密钥长期暴露;- 将
pg_dump备份与vault operator generate-rootrecovery key 分离存储:前者存 S3,后者存离线 HSM,满足“3-2-1 备份原则”。
延伸阅读:超越 Secret 存储的架构演进
OpenBao + CloudNativePG 的组合,实则是云原生可信基础设施的“锚点”。下一步可延伸至:
🔹 动态凭证(Dynamic Secrets)与 Pod Identity 深度绑定:利用 CloudNativePG 的 pg_hba.conf 动态生成 + OpenBao database secrets engine,实现“Pod 启动即获 DB 凭据,销毁即 revoke”,消除静态密码;
🔹 AI 模型权重安全分发:将 vLLM 推理服务所需的 HuggingFace Token、S3 Access Key 等注入 initContainer,通过 OpenBao transit 引擎实时解密,避免 GPU Pod 内存泄露风险;
🔹 合规自动化:结合 OpenBao 的 audit endpoint 与 CloudNativePG 的 pg_log,构建统一审计湖(Audit Lake),用 Loki + Promtail 实现 vault.auth.method.jwt.login 与 pg_log_statement='all' 的跨系统 trace 关联。
最后提醒一句:技术选型不是拼参数,而是比控制力。当你能用
kubectl get cluster查看 Secret backend 健康状态,用vault status验证 HA leader,用barman list-backup openbao-pg回溯任意时间点快照——你才真正拥有了云原生时代的 Secret 主权。
参考链接:
- OpenBao 官方文档
- CloudNativePG GitHub
- CNCF Interactive Architecture Map: Secret Management
- 《K8s Native Security Engineering》Chapter 7: "Stateful Secrets at Scale"(O’Reilly, 2026)