
你是不是也踩过这个坑我前年有个业务上线数据库密码配在 ConfigMap 里——对我知道不应该是这样但当时项目进度紧临时紧急上线想着“先跑起来再说”。结果第二天 Security 团队扫描集群敏感信息直接暴露被要求全量整改。更智障的是另一个场景我改了 ConfigMap 里的日志级别等了 20 分钟容器里的配置还是老的以为没生效就给了一纸 restart。后来才搞明白——环境变量注入根本不支持热更新纯属自己给自己加戏。还有一次更离谱的想挂 Secret 里的单个证书文件到 Pod用了 subPath结果改了 Secret 之后容器内文件纹丝不动排查半天才发现 subPath 挂载不支持热更新。坑踩多了就知道这事得彻底捋一遍。今天我把 ConfigMap 和 Secret 从里到外扒干净。一、是什么干了什么一句话定性ConfigMap存非敏感明文配置。环境变量、日志级别、配置文件往里塞。记住敏感信息别往里塞。Secret存敏感数据。密码、API Key、TLS 证书用这个。但要清醒——默认情况下 Secret 是 base64 编码不是加密。血的教训。速览对比特性ConfigMapSecret存什么非敏感配置敏感数据存储格式明文Base64 编码默认不是加密大小限制1MB1MB卷挂载默认权限064404000644用途环境变量、日志级别、app.properties密码、Token、证书都支持两种使用方式环境变量注入、卷挂载。二、两种使用方式你选哪一种方式一环境变量注入ConfigMapapiVersion: v1 kind: ConfigMap metadata: name: app-config data: LOG_LEVEL: DEBUG DB_HOST: postgres-svc MAX_CONNECTIONS: 100 --- apiVersion: apps/v1 kind: Deployment metadata: name: my-app spec: template: spec: containers: - name: app image: my-app:v1 env: - name: LOG_LEVEL valueFrom: configMapKeyRef: name: app-config key: LOG_LEVEL - name: DB_HOST valueFrom: configMapKeyRef: name: app-config key: DB_HOST # 也可以一把梭哈envFrom envFrom: - configMapRef: name: app-configSecret密码apiVersion: v1 kind: Secret metadata: name: db-secret type: Opaque data: DB_PASSWORD: dXNlcjEyM3Bhc3N3b3Jk # base64 编码的密码 --- apiVersion: apps/v1 kind: Deployment spec: template: spec: containers: - name: app envFrom: - secretRef: name: db-secret提醒环境变量方式ConfigMap/Secret 变更后Pod 需要重启才能生效。线上见过有人改了 ConfigMap 等 20 分钟最后发现重启 Pod 才生效。方式二卷挂载——推荐生产环境使用基础挂载apiVersion: v1 kind: Pod metadata: name: configmap-demo spec: containers: - name: app image: nginx volumeMounts: - name: config-vol mountPath: /etc/config # 整个目录会被覆盖 volumes: - name: config-vol configMap: name: app-config⚠️大坑整个mountPath目录会被 ConfigMap 的内容覆盖。原本目录里的文件全部消失。subPath精准挂载单个文件场景只想把nginx.conf放进去保留/etc/nginx/下的其他文件。volumeMounts: - name: nginx-config-vol mountPath: /etc/nginx/nginx.conf # 直接挂到目标文件路径 subPath: nginx.conf # 指定 ConfigMap 里的 key坑爹的是subPath 挂载不支持热更新。改了 ConfigMap/Secret容器里对应文件不会同步必须重启 Pod。我的做法需要热更新的配置用目录挂载全量覆盖不需要热更新或超敏感的单文件用 subPath。两者分开别混在一起。三、热更新——别再拍脑袋了卷挂载目录方式——支持热更新ConfigMap 改了之后kubelet 会在同步周期 缓存传播延迟后将新内容挂载进容器默认 1-2 分钟。如果等不及kubectl rollout restart deployment my-app环境变量方式——不支持热更新改了 ConfigMap/SecretPod 里的环境变量纹丝不动。必须重建 Pod。环境变量与卷挂载的行为差异使用方式更新是否自动同步延迟适用场景是否需要重启 Pod环境变量注入❌—简单配置、启动参数✅ 必须重启卷挂载目录✅~1分钟 缓存TTL配置文件、可重载场景❌subPath 挂载❌—精准替换单个文件✅ 必须重启Reloader配置变更自动重启 Pod不想手动 rolloutStakater 的 Reloader 工具可以自动监测 ConfigMap/Secret 变更并触发 Pod 重启# 在 Deployment 的 annotations 中加入 annotations: secret.reloader.stakater.com/reload: db-secret configmap.reloader.stakater.com/reload: app-config改了对应的 ConfigMap/SecretReloader 自动滚动更新 Pod。四、敏感数据管理——这几条线必须守住1. Secret 是 Base64 编码不是加密这是个致命问题默认情况下 Secret 只是 base64 编码存 etcd 里未经加密。任何人能访问 etcd 或 kube-apiserver就能直接读取你的明文密码。2. 启用 etcd 静态加密# EncryptionConfiguration 示例 apiVersion: apiserver.config.k8s.io/v1 kind: EncryptionConfiguration resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: 32字节 base64 密钥 - identity: {}kube-apiserver 启动时加参数--encryption-provider-config。3. RBAC 最小权限千万别这么干apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole rules: - apiGroups: [] resources: [secrets] verbs: [get, list, watch] # 权限太宽了正确做法只给必要的 namespaces只给必要的 verbs明确到某个 Secret 名称。4. 外部方案Sealed Secrets把 Secret 加密后安全提交到 GitExternal Secrets Operator从外部 KMSAWS Secrets Manager、HashiCorp Vault同步 SecretSecrets Store CSI Driver直接从外部 KMS 挂载Secret 不在 etcd 落地说实话如果你的团队能接受外部方案我强烈推荐 BeyondCorp CSI Driver 的路线敏感数据根本不落地 K8s安全水位直接拉满。五、故障排查两则报错 1CreateContainerConfigError$ kubectl get pod NAME READY STATUS RESTARTS AGE my-app 0/1 CreateContainerConfigError 0 10s $ kubectl describe pod my-app Events: Warning Failed Error: secret db-secret not found原因引用的 ConfigMap/Secret 不存在。解决检查名字和命名空间kubectl get cm -n namespace kubectl get secret -n namespace报错 2Annotation 长度超限metadata.annotations: Too long: must have at most 262144 bytes原因kubectl apply会把整个 spec 塞进 annotationConfigMap/Secret 太大塞不下。解决用kubectl create/replace代替kubectl apply或者拆分配置。六、三个原则 一句忠告原则一ConfigMap 和 Secret 根本目的是解耦——代码和配置分离镜像才能通用。原则二热更新不是想有就有——环境变量方式不支持subPath 方式也不支持。原则三Secret 不是安全的——Base64 编码不是加密请开启 etcd 加密或接入 CSI 等外部方案。你还有什么更好的办法来管理 K8s 的敏感配置比如 Sealed Secrets 踩过什么坑、CSI 驱动在生产环境的表现如何评论区聊聊一起把这套配置管理的坑填平