4. Secret 实战:Secret 类型、编解码与 Pod 挂载

Kubernetes Secret 是云原生配置管理中处理敏感数据的核心对象。本章将深入剖析三种最常用的 Secret 类型——Opaque、dockerconfigjson 与 TLS,并演示如何通过编码、解码将数据安全地挂载到 Pod 中。理解这些实战操作,是构建蓝绿发布与 Secrets 审计方案的基础。

4.1 Secret 类型对比与适用场景

Kubernetes 内置了多种 Secret 类型,每种类型对应不同的数据格式和使用场景。下表列出了三种核心类型的差异:

类型 用途 数据格式 典型场景
Opaque 通用敏感数据 键值对(Key-Value),值需 Base64 编码 数据库密码、、应用配置
kubernetes.io/dockerconfigjson 容器镜像仓库认证 Docker 配置文件(.dockerconfigjson)的 Base64 编码 从私有仓库拉取镜像
kubernetes.io/tls TLS/SSL 证书与私钥 tls.crt(证书)和 tls.key(私钥) Ingress 证书、服务间 mTLS
最佳实践:在蓝绿发布中,Opaque Secret 常用于存储不同环境(蓝/绿)的差异化配置;TLS Secret 用于保护服务间通信;dockerconfigjson 则确保发布流程能顺利从私有仓库拉取新版本镜像。

4.2 Secret 编码与解码原理

Secret 的数据在 Kubernetes API 中以 Base64 编码存储。这并非加密,而是一种简单的编码方式,用于避免二进制数据在 YAML/JSON 中传输时出现乱码。真正的安全依赖于 RBAC、加密存储(如 etcd 加密)和审计日志。

以下是一个 Opaque Secret 的 YAML 定义示例,展示了编码过程:

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
type: Opaque
data:
  username: YWRtaW4=          # "admin" 的 Base64 编码
  password: cGFzc3dvcmQxMjM=  # "password123" 的 Base64 编码

使用 Linux 命令进行编码与解码:

# 编码
echo -n "admin" | base64
# 输出: YWRtaW4=

# 解码
echo -n "YWRtaW4=" | base64 --decode
# 输出: admin
安全警告:Base64 编码不是加密。切勿将编码后的 Secret 直接提交到 Git 仓库。应使用 Sealed Secrets、External Secrets Operator 或 Vault 等工具进行加密管理。

4.3 三种 Secret 类型的创建与验证

4.3.1 创建 Opaque Secret

Opaque 是最通用的 Secret 类型,可通过命令行或 YAML 文件创建。

# 命令行创建(推荐用于快速测试)
kubectl create secret generic app-config \
  --from-literal=="sk-abc123" \
  --from-literal=db_host="mysql.internal"

# 从文件创建
kubectl create secret generic app-config-file \
  --from-file=./config.properties

4.3.2 创建 dockerconfigjson Secret

用于向 kubelet 提供私有仓库的认证凭据。

# 命令行创建
kubectl create secret docker-registry private-registry \
  --docker-server=https://index.docker.io/v1/ \
  --docker-username=myuser \
  --docker-password=mypassword \
  --docker-email=user@example.com

验证 Secret 内容:

kubectl get secret private-registry -o jsonpath="{.data.\.dockerconfigjson}" | base64 --decode

4.3.3 创建 TLS Secret

用于存储证书和私钥,通常由 Ingress 控制器使用。

# 生成自签名证书(仅用于测试)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=example.com"

# 创建 TLS Secret
kubectl create secret tls my-tls-secret \
  --cert=tls.crt \
  --key=tls.key

验证 TLS Secret 内容:

kubectl get secret my-tls-secret -o yaml

4.4 将 Secret 挂载到 Pod

Secret 可以通过两种方式注入到 Pod:环境变量和卷挂载。卷挂载方式更安全,因为 Secret 更新后,Pod 内的文件会自动同步(需等待 kubelet 同步周期)。

以下是一个 Pod 定义,演示了如何将 Opaque Secret 和 TLS Secret 挂载为卷:

apiVersion: v1
kind: Pod
metadata:
  name: secret-consumer
spec:
  containers:
  - name: app
    image: nginx:latest
    volumeMounts:
    - name: config-volume
      mountPath: "/etc/config"
      readOnly: true
    - name: tls-volume
      mountPath: "/etc/tls"
      readOnly: true
  volumes:
  - name: config-volume
    secret:
      secretName: app-config
  - name: tls-volume
    secret:
      secretName: my-tls-secret

挂载后,Pod 内的文件结构如下:

/etc/config/
├── 
└── db_host

/etc/tls/
├── tls.crt
└── tls.key
关键点:挂载为卷时,Secret 的每个键都会成为一个文件,文件内容即为解码后的值。这比环境变量更安全,因为环境变量可能在进程列表或日志中泄露。

4.5 Secret 挂载与数据流架构

下图展示了 Secret 从创建到挂载到 Pod 的完整数据流,以及三种 Secret 类型在集群中的典型使用路径。

Secret 创建与 Pod 挂载数据流架构 Secret 创建方式 kubectl create secret YAML 声明式定义 外部 Operator 同步 (如 External Secrets) Secret 类型 Opaque(通用) dockerconfigjson(镜像) TLS(证书) Base64 编码存储于 etcd Pod 挂载方式 卷挂载(推荐) 环境变量注入 自动解码为明文 文件或变量形式 关键安全说明 Base64 编码仅用于传输兼容,不提供加密保护 生产环境应启用 etcd 加密 + RBAC + 审计日志 蓝绿发布中的 Secret 实践 为蓝/绿环境创建独立 Secret → 通过命名空间或标签隔离 切换流量时自动切换 Secret 挂载,实现配置随发布同步

4.6 实战:挂载 dockerconfigjson 到 Pod 拉取私有镜像

在蓝绿发布中,新版本的镜像通常存储在私有仓库。以下步骤演示如何将 dockerconfigjson Secret 挂载到 Pod 中,使 kubelet 能够拉取私有镜像。

  1. 创建 Secret:使用 kubectl create secret docker-registry 命令创建。
  2. 在 Pod 中引用:在 Pod 的 spec.imagePullSecrets 字段中引用 Secret 名称。
  3. 验证拉取:Pod 启动后,kubelet 会自动使用 Secret 中的凭据进行认证。
apiVersion: v1
kind: Pod
metadata:
  name: private-image-pod
spec:
  containers:
  - name: my-app
    image: myregistry.com/myapp:blue-v2
  imagePullSecrets:
  - name: private-registry
蓝绿发布提示:可以为蓝环境和绿环境分别创建不同的 dockerconfigjson Secret,并在 ServiceAccount 级别绑定,实现环境级别的镜像拉取权限隔离。

4.7 Secret 更新与 Pod 同步机制

当 Secret 被更新时,已挂载该 Secret 的 Pod 中的文件不会立即更新。kubelet 会定期同步(默认 60 秒),将新内容写入卷。如果使用环境变量方式注入,则 Pod 必须重启才能获取新值。

挂载方式 更新后自动同步 是否需要重启 Pod 推荐场景
卷挂载(Volume) 是(60 秒内) 否 证书轮换、配置热更新
环境变量(Env) 否 是 初始化配置、启动后不变的值
审计关注点:Secret 的更新操作应被审计日志记录。在蓝绿发布中,建议在发布流程中显式触发 Pod 滚动更新(如使用 kubectl rollout restart),以确保新 Secret 被正确加载,避免因同步延迟导致配置不一致。