ConfigMap:非敏感配置
apiVersion: v1
kind: ConfigMap
metadata:
name: webapp-config
data:
LOG_LEVEL: info
FEATURE_NEW_UI: "true"
redis.conf: |
maxmemory 256mb
maxmemory-policy allkeys-lru
注入 Pod 的两种方式:
# 方式 1:作为环境变量
envFrom:
- configMapRef: { name: webapp-config }
# 方式 2:作为文件挂载
volumeMounts:
- name: redis-conf
mountPath: /etc/redis
volumes:
- name: redis-conf
configMap:
name: webapp-config
items:
- key: redis.conf
path: redis.conf
Secret:敏感配置
apiVersion: v1
kind: Secret
metadata:
name: webapp-secret
type: Opaque
stringData: # 用 stringData 比 data 友好(不用先 base64)
db-url: postgres://app:s3cr3t@db:5432/app
api-key: sk-abc...
注入方式和 ConfigMap 一样。
⚠ Secret 不是加密——只是 base64
echo -n "secret123" | base64
# c2VjcmV0MTIz
echo "c2VjcmV0MTIz" | base64 -d
# secret123
任何能读 etcd 或 kubectl get secret -o yaml 的人直接看明文。Secret 提供的是:
- 不会偶然出现在
kubectl describe输出 - RBAC 可以单独管控 Secret 的读权限
- 与 ConfigMap 的语义区分
不是:保护数据不被有权限的人读。
etcd 加密(at-rest)
集群层开启Encryption at Rest——etcd 落盘时加密。配置 EncryptionConfiguration 资源,云托管 K8s(EKS / GKE / ACK)通常默认或一键开启。
只此一项还不够——任何能读 Secret 的 ServiceAccount 都能看到明文。
进阶:替代方案
Sealed Secrets(Bitnami)
- 把 Secret 加密成 SealedSecret 资源
- 可以 commit 到 git——只有集群里的 controller 能解密
- 适合 GitOps:所有东西在 git 里
External Secrets Operator (ESO)
- Secret 实际存在外部(Vault / AWS Secrets Manager / GCP Secret Manager / 1Password)
- ESO 把它们同步到 K8s Secret
- 集中式密钥管理 + K8s 友好
HashiCorp Vault Agent / CSI Driver
- Pod 启动时直接从 Vault 拉
- 不经过 K8s Secret
- 适合极敏感场景
ConfigMap / Secret 改了——Pod 不会自动重启
K8s 对环境变量类型的注入只在 Pod 创建时生效。改了 ConfigMap,运行中的 Pod 看不到。
解决:
kubectl rollout restart deployment/webapp
或装 stakater/Reloader:监听 ConfigMap/Secret 变更自动 rollout。
文件挂载形式的 ConfigMap 会 自动同步到 Pod 文件系统(有延迟,分钟级)——但应用得自己监听文件变化。
不要做的事
- 把 .env 直接 commit 到 git——哪怕仓库 private
- kubectl create secret 时把密码写在命令行——会留在 shell history
- 跨命名空间共享 Secret——明确复制一份过去(或用 ESO 的 ClusterSecretStore)
- 同一份 ConfigMap 里塞所有环境的配置——开发环境的 LOG_LEVEL=debug 可能误推到生产
推荐阅读
- K8s: ConfigMaps / Secrets
- Encryption at Rest
- Sealed Secrets
- External Secrets Operator
- HashiCorp Vault on K8s
下一篇:把上面 yaml 模板化——Helm。