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 消费的完整数据流,以及每个环节的安全边界。

Kubernetes Secret 数据流与安全边界 Secret 数据流与安全边界 用户 / CI 工具 kubectl / API API Server etcd Pod(容器) Volume Mount 安全边界: ① RBAC 控制谁可以读取 Secret;② etcd 静态加密保护磁盘数据;③ Volume Mount 使用 tmpfs 避免写入节点磁盘;④ 容器内以只读方式挂载。

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)来弥补轮换与审计短板。

3.6 本章小结