3. Kubernetes Secrets 原生机制:K8s Secret 资源类型、创建方式、存储与编码原理
Kubernetes Secrets 是云原生环境中管理敏感信息的“第一道防线”。理解其资源类型、创建方式、存储与编码原理,是实施有效 Secrets 轮换与合规准入策略的基础。本章将深入剖析 K8s Secrets 的原生机制,揭示其设计意图与安全边界。
3.1 Secret 资源类型与适用场景
Kubernetes 提供了多种内置的 Secret 类型,每种类型对应不同的数据格式和使用场景。选择正确的类型有助于提升可读性和自动化能力。
| Secret 类型 | kubernetes.io 前缀 | 数据字段要求 | 典型用途 |
|---|---|---|---|
| Opaque | 无(默认) | 任意键值对 | 通用敏感数据,如 、数据库密码 |
| kubernetes.io/service-account- | service-account- | 自动注入 、ca.crt、namespace | ServiceAccount 自动挂载的令牌 |
| kubernetes.io/dockercfg | dockercfg | .dockercfg(序列化 Docker 配置) | 拉取私有镜像仓库(旧格式) |
| kubernetes.io/dockerconfigjson | dockerconfigjson | .dockerconfigjson(序列化 Docker 配置) | 拉取私有镜像仓库(推荐格式) |
| kubernetes.io/basic-auth | basic-auth | username、password | HTTP 基本认证凭据 |
| kubernetes.io/ssh-auth | ssh-auth | ssh-privatekey | SSH 密钥认证 |
| kubernetes.io/tls | tls | tls.crt、tls.key | TLS/SSL 证书与私钥 |
| bootstrap.kubernetes.io/ | bootstrap.kubernetes.io/ | -id、-secret 等 | 节点引导令牌 |
最佳实践: 对于自定义敏感数据,始终使用
Opaque 类型并明确命名键名。避免将非结构化数据塞入不匹配的类型中,否则可能导致 Pod 创建失败或数据解析错误。
3.2 Secret 创建方式对比
Kubernetes 支持多种创建 Secret 的方式,从命令行直接创建到声明式 YAML 管理。不同方式在可审计性、可重复性和安全性上存在显著差异。
- kubectl create secret generic(命令式): 快速创建,适合临时测试。支持
--from-literal、--from-file、--from-env-file。 - kubectl apply -f(声明式 YAML): 推荐用于生产。Secret 数据需提前进行 Base64 编码,便于版本控制与 GitOps 集成。
- kubectl create secret tls/docker-registry(类型专用): 针对 TLS 证书和镜像仓库凭据的快捷方式,自动处理数据格式。
- kubectl create secret generic --from-file=ssh-privatekey=./id_rsa: 从本地文件直接读取原始数据,避免在命令行中暴露明文。
# 命令式创建 Opaque Secret(不推荐用于生产)
kubectl create secret generic db-credentials \
--from-literal=username=admin \
--from-literal=password='S3cur3P@ss'
# 声明式 YAML 创建(推荐)
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
data:
username: YWRtaW4= # echo -n "admin" | base64
password: UzNjdXIzUEBzcw== # echo -n "S3cur3P@ss" | base64
安全警告: 声明式 YAML 中的
data 字段要求值必须是 Base64 编码后的字符串。但 Base64 不是加密,任何拥有 YAML 文件访问权限的人都可以轻松解码。切勿将包含敏感数据的 YAML 文件提交到公开仓库。
3.3 存储与编码原理
Kubernetes Secrets 的核心存储机制基于 etcd,但数据在 etcd 中的保护程度取决于集群配置。理解编码与存储的层次,是评估风险的关键。
3.3.1 Base64 编码:仅混淆,非加密
Secret 对象在 API 服务器和 etcd 中默认以 Base64 编码存储。Base64 是一种可逆的编码方式,用于将二进制数据转换为 ASCII 字符串,以便在 JSON/YAML 中传输。它不提供任何机密性保护。
# 编码示例
$ echo -n "my-password" | base64
bXktcGFzc3dvcmQ=
# 解码示例
$ echo -n "bXktcGFzc3dvcmQ=" | base64 -d
my-password
3.3.2 etcd 存储:静态加密 vs 明文
Secret 数据最终存储在 etcd 中。默认情况下,etcd 可能以明文(Base64 编码后)存储数据。Kubernetes 1.13+ 支持 静态加密(Encryption at Rest),通过 EncryptionConfiguration 资源对 etcd 中的 Secret 进行 AES-CBC 或 AES-GCM 加密。
| 存储层级 | 默认保护 | 增强保护 |
|---|---|---|
| API 服务器内存 | 明文(Base64 解码后) | 无额外保护 |
| etcd 磁盘 | Base64 编码(明文) | 静态加密(AES-CBC/GCM) |
| etcd 网络传输 | TLS(如果启用) | 强制 mTLS |
| Pod 内挂载 | tmpfs(内存)或 emptyDir | 只读挂载 + 卷权限限制 |
关键洞察: 即使启用了 etcd 静态加密,Secret 数据在 API 服务器内存中仍然是明文的。任何能够通过
kubectl get secret 或 API 调用读取 Secret 的用户或组件,都可以获取原始数据。因此,RBAC 权限控制是 Secrets 安全的第一道闸门。
3.4 Secret 数据流与安全边界
下图展示了 Secret 从创建到被 Pod 消费的完整数据流,以及每个环节的安全边界。
3.5 Secret 的局限性:原生机制的安全短板
Kubernetes 原生 Secret 机制虽然提供了基础能力,但在企业级合规与轮换场景中存在明显短板:
- 无自动轮换: Secret 创建后内容不会自动更新,需要外部控制器或手动操作。
- 审计日志不完整: 默认审计日志记录 API 调用,但不记录谁在 Pod 内读取了挂载的 Secret 文件。
- 静态加密配置复杂: 需要手动配置 EncryptionConfiguration,且密钥管理(KMS)集成门槛较高。
- 数据大小限制: Secret 对象最大 1MB(受 etcd 限制),不适合存储大型证书链或配置文件。
- 删除后数据残留: 即使删除 Secret 对象,etcd 中已存储的数据可能仍存在于磁盘快照中。
合规启示: 对于需要满足 SOC 2、PCI DSS 或 HIPAA 等标准的集群,原生 Secret 机制通常需要配合外部 Secrets 管理工具(如 HashiCorp Vault、AWS Secrets Manager、Azure Key Vault)或 Kubernetes 增强组件(如 Sealed Secrets、External Secrets Operator)来弥补轮换与审计短板。