CFN Cloud
2025-10-08

Kubernetes ConfigMap 与 Secret:配置管理和敏感信息实践

讲清 ConfigMap 与 Secret 的使用边界、挂载方式与安全注意事项,减少配置漂移和敏感信息泄露风险。

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

然后依次确认:

  1. 资源是不是在正确的 namespace?
  2. key 名称是否写对?
  3. 应用用的是 env 还是文件挂载?
  4. 应用支持热加载还是必须重启?

什么情况下该考虑外部密钥管理

如果你遇到下面这些需求,就该考虑超出原生 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 表面上只是“配置对象”,但它们实际会影响发布流程、安全边界、排障效率和回滚方式。把它们当成工作负载契约的一部分来设计,后面会省很多事。

参考链接