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 |
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
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
4.5 Secret 挂载与数据流架构
下图展示了 Secret 从创建到挂载到 Pod 的完整数据流,以及三种 Secret 类型在集群中的典型使用路径。
4.6 实战:挂载 dockerconfigjson 到 Pod 拉取私有镜像
在蓝绿发布中,新版本的镜像通常存储在私有仓库。以下步骤演示如何将 dockerconfigjson Secret 挂载到 Pod 中,使 kubelet 能够拉取私有镜像。
- 创建 Secret:使用
kubectl create secret docker-registry命令创建。 - 在 Pod 中引用:在 Pod 的
spec.imagePullSecrets字段中引用 Secret 名称。 - 验证拉取: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
4.7 Secret 更新与 Pod 同步机制
当 Secret 被更新时,已挂载该 Secret 的 Pod 中的文件不会立即更新。kubelet 会定期同步(默认 60 秒),将新内容写入卷。如果使用环境变量方式注入,则 Pod 必须重启才能获取新值。
| 挂载方式 | 更新后自动同步 | 是否需要重启 Pod | 推荐场景 |
|---|---|---|---|
| 卷挂载(Volume) | 是(60 秒内) | 否 | 证书轮换、配置热更新 |
| 环境变量(Env) | 否 | 是 | 初始化配置、启动后不变的值 |
kubectl rollout restart),以确保新 Secret 被正确加载,避免因同步延迟导致配置不一致。