深色模式
Secret 管理与 KMS 加密
摘要:本文面向集群管理员与安全负责人,澄清 Secret 默认不加密的真相,讲清 etcd 静态加密的
EncryptionConfiguration配置、KMS v2 信封加密原理与厂商集成,以及密钥轮换、回滚与排障。覆盖版本:Kubernetes v1.28+(KMS v2 推荐)。
适用版本与前提
- Kubernetes:v1.28+(KMS v2 推荐;KMS v1 自 v1.28 弃用、v1.29 默认禁用)
- 工具:kubectl、etcdctl(校验用)、集群控制面节点 root 权限
- 前提:可访问 kube-apiserver 静态 Pod 清单与加密配置文件
背景与问题
Secret 用来存放密码、token、key 等少量敏感数据。但官方文档明确指出:默认情况下 Secret 以未加密形式存于 etcd。任何拥有 API 访问权(或 etcd 访问权)的人都能读取或修改 Secret;任何能在某命名空间创建 Pod 的人(包括通过 Deployment 间接创建)都能读取该命名空间任意 Secret。
最大误解
Secret 的 data 字段只是 base64 编码,不是加密。echo 'xxx' | base64 -d 即可还原。base64 不提供任何机密性。
核心概念
Secret 内置类型:Opaque(默认任意数据)、kubernetes.io/tls、kubernetes.io/dockerconfigjson、kubernetes.io/basic-auth、kubernetes.io/ssh-auth、bootstrap.kubernetes.io/token 等。immutable: true 自 v1.21 Stable,可防误改并降低 apiserver 负载(不可回退)。
架构与原理
etcd 静态加密的层级
KMS v2 使用信封加密(envelope encryption):数据用数据加密密钥(DEK,AES-CBC)加密;DEK 再用外部 KMS 中的密钥加密密钥(KEK)包装。根信任(KEK)在集群之外,比把密钥写在本地文件更强。KMS v2 下每个加密生成单用 DEK(由 seed + 随机数据经 KDF 派生),KEK 轮换时 seed 随之轮换。
版本相关
KMS v2 在 v1.29 GA;KMS v1 自 v1.28 弃用、v1.29 默认禁用(需 --feature-gates=KMSv1=true)。新集群一律用 apiVersion: v2。[版本相关:老于 v1.29 的控制面行为不同]
EncryptionConfiguration 结构
providers 为有序列表:第一个用于加密新写入;读取时按顺序尝试解密。identity: {} 表示不加密,若排第一则 etcd 中明文存储。
生产实践
本地密钥方案(aescbc,入门/过渡)
yaml
# /etc/kubernetes/encryption-config.yaml 控制面节点
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64 编码的 32 字节随机密钥>
- identity: {}1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
生成密钥:head -c 32 /dev/urandom | base64。
KMS v2 方案(生产推荐)
yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- kms:
apiVersion: v2
name: my-kms-plugin
endpoint: unix:///path/to/kms-plugin.sock
timeout: 3s1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
endpoint 为 KMS 插件监听的 UNIX domain socket。插件以 gRPC 与 apiserver 同机部署,负责与外部 KMS 通信。云厂商(AWS KMS、GCP KMS、Azure Key Vault)提供各自的 KMS 插件,[厂商特定]配置请查阅对应云文档。
启用加密
在 kube-apiserver 静态 Pod 清单加:
yaml
spec:
containers:
- command:
- kube-apiserver
- --encryption-provider-config=/etc/kubernetes/encryption-config.yaml
volumeMounts:
- mountPath: /etc/kubernetes/encryption-config.yaml
name: encryption-config
readOnly: true
volumes:
- name: encryption-config
hostPath:
path: /etc/kubernetes/encryption-config.yaml
type: File1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
生产危险
修改 kube-apiserver 静态清单会触发 kubelet 重启 apiserver,控制面有短暂中断。操作前必须备份清单与加密配置,并在维护窗口执行。
加密存量 Secret
启用后已有 Secret 仍以旧格式留存,需重写触发加密:
bash
kubectl get secrets --all-namespaces -o json | kubectl replace -f -1
大集群
全量 replace 在大规模集群会产生大量 apiserver 写入,建议在低峰期执行,并监控 apiserver 延迟。
校验 etcd 中确为密文
bash
ETCDCTL_API=3 etcdctl get /registry/secrets/default/my-secret \
--cacert=/etc/kubernetes/pki/etcd/ca.crt \
--cert=/etc/kubernetes/pki/etcd/server.crt \
--key=/etc/kubernetes/pki/etcd/server.key
# 加密后值以 k8s:enc:kms:v2:... 或 k8s:enc:aescbc:v1: 开头1
2
3
4
5
2
3
4
5
关键轮换与回滚
密钥轮换(aescbc/secretbox)
先加新 key(排第一用于加密),旧 key 保留用于解密,待全量重写后再删旧 key:
yaml
providers:
- aescbc:
keys:
- name: key2 # 新密钥,先用于加密
secret: <new base64>
- name: key1 # 旧密钥,保留解密
secret: <old base64>
- identity: {}1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
改完配置后需 apiserver 重新加载(KMS 方案可用 --encryption-provider-config-automatic-reload;本地方案需重启 apiserver)。
KMS KEK 轮换
官方建议 KEK 至少每 90 天轮换一次。KMS v2 下插件通过 Status RPC 回报 key_id;变更即被视为 KEK 已换,旧数据在下次 no-op 写时标记过期。apiserver 约每分钟轮询 Status,约 3 分钟容错,故被动迁移建议安排在 KEK 轮换后 3 + N + M 分钟(M 至少 5 分钟)。无需重启 apiserver。
故障排查
| 现象 | 根因 | 解决 |
|---|---|---|
| etcd 中仍是明文 | identity: {} 排第一 | 改为强 provider 排首,重写存量 |
| apiserver 起不来 | 加密配置文件路径/权限错 | 比对静态清单与 hostPath |
| Secret 读失败 | key 被改无法解密 | 提供有效解密 key,否则需直接删 etcd 中该 key |
| KMS 插件不健康 | socket/鉴权失败 | 查插件日志,apiserver 约每 10s 轮询不健康插件 |
数据不可恢复
若所有 provider 都无法解密某资源,唯一补救是直接从 etcd 删除该 key,相关资源将不可读直至提供有效解密密钥。生产务必保留旧 key 一段时间。
安全与合规
仅静态加密不够,还需:RBAC 最小权限(限制 list/watch 对 Secret)、审计规则、外部密钥源(见本站 External Secrets / 泄露防护篇)。Secret 静态加密防 etcd 泄露,但防不住 API 权限过大与 Pod 创建权滥用。
替代方案与权衡
- 本地
aescbc/secretbox:防 etcd 泄露,但根密钥仍在控制面主机,主机被控即失守。 - KMS v2:根信任在集群外,密钥轮换由 KMS 托管,生产首选,但引入插件可用性依赖与调用延迟。
- Secrets Store CSI Driver:把外部密钥挂载进特定 Pod,不经过原生 Secret 存储。
FAQ
Q:KMS v2 会增加多少延迟? 官方要求插件 Encrypt 延迟 < 100ms、Decrypt < 10ms;解密 DEK 会缓存。具体影响[未实测],取决于 KMS 后端网络。
Q:能同时加密 ConfigMap 吗? 可以,在 resources 中加 - configmaps(需 v1.26+ 支持 CRD 扩展 API 加密亦然)。
参考资料
- Secrets - Kubernetes 官方文档,访问日期:2026-10-08。
- Using a KMS provider for data encryption - Kubernetes 官方文档,访问日期:2026-10-08。
- Good practices for Kubernetes Secrets - Kubernetes 官方文档,访问日期:2026-10-08。
- Encrypting Secret Data at Rest(encryption provider 配置示例),访问日期:2026-10-08。