管理配置、密钥与数据
镜像应尽量保持环境无关。地址、开关和日志级别属于配置;密码、令牌和证书属于密钥;数据库文件和上传内容属于持久化数据。三者生命周期和访问控制不同,应分别管理。
本篇目标:能正确使用 ConfigMap 的环境变量和文件注入方式,理解 Secret 的安全边界,区分 PV/PVC/StorageClass 的职责。

1. ConfigMap:非敏感配置
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: learning
data:
LOG_LEVEL: info
FEATURE_CACHE: "true"
# 也可以存配置文件内容
app.yaml: |
server:
port: 8080
cache:
ttl: 300
1.1 两种注入方式
# 方式 1:环境变量注入(启动时读取,之后修改 ConfigMap 不会更新)
envFrom:
- configMapRef:
name: api-config
# 方式 2:文件挂载(ConfigMap 更新后,kubelet 会在几十秒内同步到挂载目录)
volumeMounts:
- name: config
mountPath: /etc/app
volumes:
- name: config
configMap:
name: api-config
| 方式 | 热更新 | 适用场景 |
|---|---|---|
| 环境变量 | ❌ 只在启动时读取 | 启动参数、少量开关 |
| 文件挂载 | ✅ kubelet 自动同步(有延迟) | 配置文件、需要热更新的开关 |
文件挂载热更新不等于应用自动重载
ConfigMap 更新后,挂载文件内容会变化,但应用不会自动重启或重载配置。需要应用自身支持文件监听(如 inotify),或通过 kubectl rollout restart 触发滚动重启。
1.2 Immutable ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config-v2
namespace: learning
immutable: true # 创建后不可修改,避免误操作
data:
LOG_LEVEL: info
Immutable ConfigMap 配合版本化命名(如 api-config-v1、api-config-v2),每次变更创建新的、更新 Deployment 引用新的。这比修改同一个 ConfigMap 更可控、更有审计痕迹。
2. Secret:降低暴露面,不等于保险箱
apiVersion: v1
kind: Secret
metadata:
name: api-credentials
namespace: learning
type: Opaque
stringData:
API_TOKEN: replace-in-cd-or-external-secret
2.1 Secret 类型
| 类型 | 用途 | 示例 |
|---|---|---|
Opaque | 通用键值对 | API Key、数据库密码 |
kubernetes.io/tls | TLS 证书和私钥 | Ingress 证书 |
kubernetes.io/dockerconfigjson | 私有镜像仓库凭据 | imagePullSecrets |
kubernetes.io/basic-auth | 基本认证 | 用户名/密码 |
kubernetes.io/service-account-token | ServiceAccount Token | 自动管理,一般不需手工创建 |
2.2 Secret 的安全边界
Secret 的默认 data 只是 Base64 编码,不是加密。echo "cGFzc3dvcmQ=" | base64 -d 就能解码。
生产基线应至少包括:
| 层面 | 做法 |
|---|---|
| 静态加密 | 开启 etcd 静态加密或使用云厂商 KMS |
| 访问控制 | RBAC 限制谁能 get secrets,审计 Secret 读取日志 |
| 不入 Git | 真实 Secret 不进 Git、终端历史或 CI 日志 |
| 外部密钥 | 对接 External Secrets、Vault 或云 Secret Manager,工作负载运行时读取 |
| 短期身份 | 能用 OIDC/STS 临时凭据的,不放长期密钥 |
# 查看谁有权限读某 Namespace 的 Secret
kubectl auth can-i get secrets -n learning
kubectl get rolebinding,clusterrolebinding -A -o wide | grep -i secret
3. 注入到 Pod
envFrom:
- configMapRef:
name: api-config
- secretRef:
name: api-credentials
只把所需键注入给所需容器。不要把整份平台级 Secret 挂给每个应用,也不要用 kubectl describe pod、调试脚本或日志打印环境变量。
# 更精细:只取 Secret 中的特定 Key
env:
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: api-credentials
key: DB_PASSWORD
4. PersistentVolumeClaim:申请存储
4.1 核心概念
| 概念 | 职责 | 谁来创建 |
|---|---|---|
| PV(PersistentVolume) | 集群可用的一块具体存储资源 | 管理员或 StorageClass 动态供给 |
| PVC(PersistentVolumeClaim) | Namespace 内应用对容量和访问模式的申请 | 应用开发者 |
| StorageClass | 动态供给、性能与回收策略模板 | 平台团队 |
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: uploads
namespace: learning
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard # 指定 StorageClass
resources:
requests:
storage: 20Gi
4.2 StorageClass 关键参数
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: fast-ssd
provisioner: pd.csi.storage.gke.io # 取决于 CSI 驱动
parameters:
type: pd-ssd # 供应商特定参数
reclaimPolicy: Retain # 删除 PVC 时保留 PV
volumeBindingMode: WaitForFirstConsumer # 等 Pod 调度后再创建卷(避免跨 AZ)
allowVolumeExpansion: true # 允许在线扩容
| 参数 | 含义 | 建议 |
|---|---|---|
reclaimPolicy: Delete | 删除 PVC 时自动删除 PV 和云盘 | 开发/测试环境,注意数据丢失风险 |
reclaimPolicy: Retain | 删除 PVC 后 PV 保留,需手动清理 | 生产环境首选 |
volumeBindingMode: Immediate | PVC 创建后立即绑定 PV | 可能跨 AZ 绑定,导致 Pod 无法挂载 |
volumeBindingMode: WaitForFirstConsumer | Pod 调度后才在 Pod 所在 AZ 创建卷 | 生产首选,避免跨 AZ 挂载问题 |
allowVolumeExpansion: true | 允许在线扩容 PVC | 建议开启,避免扩容需要重建 |
4.3 临时存储
不是所有存储都需要持久化:
| 类型 | 生命周期 | 典型场景 |
|---|---|---|
emptyDir | 随 Pod 创建,Pod 删除时清空 | Pod 内容器间共享临时数据、缓存 |
emptyDir.medium: Memory | 同上,但用 tmpfs(内存) | 高性能临时缓存 |
hostPath | 绑定宿主机路径 | 日志采集(DaemonSet 只读挂载)、Docker socket |
volumes:
- name: cache
emptyDir:
medium: Memory
sizeLimit: 256Mi
5. 数据安全检查
- 先确认访问模式:
ReadWriteOnce不表示任何节点都可同时读写,它只允许单节点挂载为读写; - 确认
reclaimPolicy、PVC 保留策略和备份恢复流程; - 数据库优先使用托管服务,或采用经过验证的 Operator;
- 删除 Namespace、PVC 或 StatefulSet 前,先确认数据卷和快照影响;
- 用恢复演练验证备份,而不只验证"备份任务成功"。
6. 练习
练习 A
- 创建一个 ConfigMap,用环境变量注入到一个 Deployment 中,进入 Pod 用
env | grep确认变量可见 - 修改 ConfigMap,再次进入 Pod 确认环境变量未变化
- 改用 volume mount 方式挂载 ConfigMap,修改 ConfigMap 后等 30 秒,进入 Pod 确认文件内容已更新
练习 B
- 创建一个 PVC(1Gi),挂载到一个 busybox Pod 的
/data目录 - 在
/data中写入文件,删除 Pod,重建 Pod 挂载同一 PVC,确认数据还在 - 创建
emptyDir卷(不要 PVC),重复上述操作,确认删除 Pod 后数据丢失
验收清单
- 会区分 ConfigMap、Secret 和 PVC 的用途
- 知道 Secret Base64 编码不等于加密,了解至少 3 项 Secret 安全实践
- 知道 ConfigMap 环境变量 vs 文件挂载的热更新差异
- 知道 PVC 是申请,StorageClass 决定动态供给方式
- 理解
WaitForFirstConsumer的作用和reclaimPolicy的取舍 - 会在删除资源前检查存储与备份影响
下一篇:控制调度、资源与权限。