讲解

Secret 和 ConfigMap 的结构几乎一样(键值对、环境变量或卷挂载消费、同命名空间、1MB 上限),区别在于定位:它专门存密码、Token、TLS 证书这类敏感数据。需要立刻澄清的认知是:Secret 默认只是 base64 编码,不是加密——base64 任何人都能解码。它的真实价值在于配套机制:可以开启 etcd 静态加密(EncryptionConfiguration)、有更细的 RBAC 控制、在 Pod 的 YAML 和日志里不易被误打印、卷挂载时以内存文件系统(tmpfs)形式存在不落盘。别把「用了 Secret」当成「信息已加密」。

Secret 有几种内置类型:Opaque(通用,任意键值,最常用)、kubernetes.io/tls(TLS 证书私钥对,Ingress 的 TLS 用它)、kubernetes.io/dockerconfigjson(私有镜像仓库凭据,配在 ServiceAccount 或 Pod 的 imagePullSecrets 上)。创建方式:YAML 里用 stringData 字段可以写明文(API Server 会自动转成 base64 存起来),用 data 字段则要自己先 base64 编码——写 YAML 时用 stringData 省心,读出来的时候拿到的永远是 base64。

消费方式和 ConfigMap 完全对称:env 的 valueFrom.secretKeyRef 注单个键,envFrom.secretRef 整体导入,或卷挂载成文件。安全实践上还有几件事:清单文件别提交进 Git(用 sealed-secrets、External Secrets 或 CI 注入);RBAC 里 get/list secrets 权限要严格收敛;etcd 层面开启静态加密;能不用环境变量就不用(crash dump、/proc 里可能泄露),卷挂载相对更好。

示例

用 stringData 写明文创建一个 Secret(存储时自动转 base64),Pod 用环境变量消费:

# wait: pod/ohmydocs-verify-dbapp
apiVersion: v1
kind: Secret
metadata:
  name: ohmydocs-verify-db-secret
type: Opaque
stringData:
  DB_USER: "appuser"
  DB_PASSWORD: "s3cure!pass"
---
apiVersion: v1
kind: Pod
metadata:
  name: ohmydocs-verify-dbapp
  labels:
    app: ohmydocs-verify-dbapp
spec:
  containers:
    - name: busybox
      image: busybox:1.36
      command: ["sleep", "3600"]
      env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: ohmydocs-verify-db-secret
              key: DB_USER
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: ohmydocs-verify-db-secret
              key: DB_PASSWORD

API 里读出来的是 base64(看 DATA 列与解码过程):

kubectl get secret ohmydocs-verify-db-secret
decoded=$(kubectl get secret ohmydocs-verify-db-secret -o jsonpath='{.data.DB_PASSWORD}' | base64 -d)
echo "base64 解码后: $decoded"

容器内环境变量拿到的是解码后的明文——Secret 的 base64 只存在于存储和传输层:

kubectl exec ohmydocs-verify-dbapp -- sh -c 'echo "容器内 DB_USER=$DB_USER DB_PASSWORD=$DB_PASSWORD"'

常见坑

  • 以为 base64 是加密:任何能 get secret 的人一条 base64 -d 就看到明文;权限控制和 etcd 加密才是防线。
  • Secret 清单提交进 Git:stringData 明文或 base64(等于明文)进版本库 = 泄露;用 .gitignore 排除,生产用专门的密钥管理方案。
  • 环境变量方式泄露面大:容器 crash dump、kubectl exec ... env、应用打日志都可能带出环境变量;敏感数据优先卷挂载。
  • 跨命名空间引用:Secret 只能被同命名空间的 Pod 使用,多命名空间共享要复制或用 External Secrets 这类工具。

小结

Secret = 敏感信息的 ConfigMap,base64 编码而非加密,靠 RBAC + etcd 静态加密 + 不进 Git 守住安全;消费方式与 ConfigMap 对称。应用能跑、能配、能拿密钥了,下一章解决数据落地:存储卷。