ConfigMap 和 Secret 解决的是同一个根问题:镜像应该尽量保持不可变,但不同环境里的配置和凭据又必须能独立变化。普通配置放 ConfigMap,敏感信息放 Secret,看起来很简单,真正麻烦的地方在于怎么让它们安全、可追踪、可更新。
这两个对象分别适合放什么
- ConfigMap:日志级别、功能开关、业务配置等非敏感信息
- Secret:密码、Token、证书、密钥等敏感数据
它们都属于命名空间级资源,但风险等级绝对不能一样看待。
为什么要把配置从镜像里拆出来
如果环境参数直接写进镜像,每次改配置都要重新构建和发布镜像,密钥轮换也会变得非常笨重。
把配置和镜像解耦之后,应用镜像可以更稳定,环境差异也更容易管理。
最小示例
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
LOG_LEVEL: "info"
---
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
stringData:
DB_PASSWORD: "changeme"
工作负载怎么消费它们
主要有两种方式。
环境变量
适合:
- 配置项少
- 应用本身就用 env 读取配置
- 场景简单、上线快
缺点是:环境变量通常只在进程启动时读取,配置变更往往意味着要重启 Pod。
文件挂载
适合:
- 配置文件
- TLS 证书和密钥
- 支持热加载文件配置的应用
挂载文件能在磁盘层面更新,但应用自己是否会重新加载,仍然要单独确认。
环境变量示例
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: db-secret
或者只映射指定键:
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVEL
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: DB_PASSWORD
文件挂载示例
volumes:
- name: config
configMap:
name: app-config
- name: secret
secret:
secretName: db-secret
volumeMounts:
- name: config
mountPath: /etc/app/config
readOnly: true
- name: secret
mountPath: /etc/app/secret
readOnly: true
配置变更为什么经常“没生效”
这是最常见的坑之一:
- 挂载成文件时,文件内容可能更新了,但应用没有自动 reload
- 作为环境变量注入时,Pod 通常必须重启才能读到新值
所以很多团队会在 Deployment 上加 checksum 注解,让配置变化自动触发一次可控滚动更新。
ConfigMap 和 Secret 最不该怎么用
不要把 Secret 当成“默认已经安全”
Secret 只是 base64 编码,不是天然安全。你仍然需要加密、权限控制和审计。
不要把大文件全塞进 ConfigMap
ConfigMap 不是对象存储,更不适合装大型二进制或大量静态资产。
不要让所有 Pod 都有权限读所有 Secret
这样一旦某个 Pod 出问题,影响范围会被你自己无意义地放大。
命名空间与作用域
ConfigMap 和 Secret 都是命名空间级别的。Pod 和它引用的配置必须在同一个命名空间里,默认并不存在跨 namespace 读取这回事。
很多配置问题其实不是内容错了,而是资源根本不在一个 namespace。
越早建立越好的安全习惯
- 开启 Secret at-rest 加密
- 用 RBAC 收窄读取范围
- 按应用拆分 Secret,不要大锅烩
- 不把 Secret 提交到 git
- 对高敏感场景尽早引入外部密钥管理系统
Secret 管理的本质不只是“藏起来”,更是降低爆炸半径。
一套实用排障顺序
kubectl describe pod <pod-name>
kubectl get configmap app-config -o yaml
kubectl get secret db-secret -o yaml
kubectl exec -it <pod-name> -- ls -l /etc/app/config
kubectl exec -it <pod-name> -- ls -l /etc/app/secret
然后依次确认:
- 资源是不是在正确的 namespace?
- key 名称是否写对?
- 应用用的是 env 还是文件挂载?
- 应用支持热加载还是必须重启?
什么情况下该考虑外部密钥管理
如果你遇到下面这些需求,就该考虑超出原生 Secret 的方案:
- 需要更强审计能力
- 密钥轮换频繁
- 多集群复用同一套密钥流程
- 需要更严格的集中式策略控制
Kubernetes 原生 Secret 是很好的起点,但不一定是终点。
FAQ
Q: 所有敏感信息都应该直接放进 Kubernetes Secret 吗? A: 不一定。原生 Secret 很方便,但高安全等级或多集群环境通常更适合接入外部密钥系统。
Q: 为什么 ConfigMap 改了,应用还是没变化? A: 很可能是应用只在启动时读取配置,或者虽然文件更新了,但应用没有 reload 机制。
Q: 什么时候更适合文件挂载,而不是环境变量? A: 当配置比较复杂、需要放证书文件,或者应用支持文件热加载时,文件挂载通常更合适。
下一步阅读
- 接着读
kubernetes-quickstart-probes.md - 再读
kubernetes-quickstart-declarative-config.md - 如果你关心权限与生产安全,继续看 RBAC / Secret 管理相关 tips
收个尾
ConfigMap 和 Secret 表面上只是“配置对象”,但它们实际会影响发布流程、安全边界、排障效率和回滚方式。把它们当成工作负载契约的一部分来设计,后面会省很多事。