技术文章2026 年 6 月 20 日约 2.9 分钟

Kubernetes ConfigMap 与 Secret:分离配置和镜像

ConfigMap 与 Secret 的注入、挂载、变更联动,以及「Secret 不是加密」这条底线。

把配置从镜像里拆出来,是 12-Factor 的基本要求:同一个镜像,靠注入的配置跑不同环境。ConfigMap 装普通配置,Secret 装敏感配置。但很多人对 Secret 有个致命误解——Secret 不是加密的。

#基本用法:env 注入和文件挂载

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: demo-api-config
data:
  LOG_LEVEL: info
  API_MODE: production
  CONFIG_FILE: |
    retries=3
    timeout=5s
---
apiVersion: v1
kind: Secret
metadata:
  name: demo-api-secret
type: Opaque
stringData:
  DATABASE_URL: postgresql://app:change-me@example-db:5432/app

注意 stringData 是明文写入,写进 etcd 之前 Kubernetes 会帮你 base64 编码;data 则要求你自己先 base64。用 stringData 写清单更不容易错,因为不需要手动 base64。

容器里两种消费方式:

yaml
# 方式一:整包注入成环境变量
envFrom:
  - configMapRef: {name: demo-api-config}
  - secretRef: {name: demo-api-secret}

# 方式二:挂载成文件(Secret 更新后文件自动同步)
volumeMounts:
  - name: tls
    mountPath: /etc/app/tls
    readOnly: true
volumes:
  - name: tls
    secret:
      secretName: demo-api-tls

挂载成文件 > 注入成环境变量:env 注入在 Pod 启动时就定死了,改 ConfigMap 不会更新已运行 Pod 的环境变量;文件挂载则能自动同步。但要注意:envFrom 里的键值如果和环境已有的变量重名,会被覆盖,出过不少「配置怎么没生效」的排查事故。

#先分清三件事:编码、加密、访问控制

  • 编码 ≠ 加密:Secret 的 data 只是 base64。kubectl get secret -o yaml 人人可读,echo xxx | base64 -d 就是明文。它最多防「日志里意外出现」。
  • 静态加密:默认 etcd 里也是 base64 明文。生产要开 apiserver 的 --encryption-provider-config(aescbc / kms)才能落盘加密。
  • 访问控制:Secret 默认在 namespace 内所有 Pod 都能通过 API 读取,需要 RBAC 收紧(限制 get/list secrets 权限),或者用 --secret-ref 类的外部方案。

我在一个项目里见过真实事故:CI 脚本把 kubectl get secret -o jsonpath='{.data.DATABASE_URL}' | base64 -d 打进了日志,然后日志被同步到第三方平台,数据库口令直接外泄。凡是含 Secret 的命令,一律不允许 echo 到 stdout,这个规则要写进 CI 模板。

#变更联动:Secret 改了,Pod 要不要重启

很多应用只读环境变量,不读文件。这类应用改 ConfigMap/Secret 后必须重启 Pod 才生效。最常用的技巧是给 Deployment 加一个 sha256 校验注释:

yaml
template:
  metadata:
    annotations:
      checksum/config: 8b1a9953c4611296a827abf8c47804d7

把 ConfigMap 内容 hash 填进去,kubectl apply 时 hash 变了,template 就变了,Deployment 自动滚动更新。可以配合 kubectl create configmap --from-literal 后用 kubectl get cm -o jsonpath 取 hash,或者用 Helm 的 sha256sum 模板函数。别写「每次发布都重启」的脚本,checksum 注释是最优雅的自动化方式。

#可维护性:命名和来源

  • ConfigMap 用 {app}-config、Secret 用 {app}-secret 命名,别叫 config 这种一抓一大把的名字。
  • 用 kubectl create configmap demo-api-config --from-file=app.conf 从文件生成,比手写 YAML 更不容易漏。
  • 清单文件里永远不放真实 Secret。开发用 kubectl create secret generic ... --dry-run=client -o yaml 生成后再手动替换占位符,或者接外部 Secret Operator(External Secrets / Vault),生产强推后者。

#经验

ConfigMap/Secret 的问题大多是「改了不生效」和「以为是加密的」。记住三条:改配置要触发滚动更新(checksum 注释);Secret 默认只是 base64;真实凭据永远走外部密钥管理,不进 Git、不进镜像、不进日志。这三条守住,配置管理就稳了。

写于 2026 年 6 月 20 日

栏目
技术文章
约
2.9 分钟
字数
2.2K
阅读
212

本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。

同题 · related

留言 · remarks

00 条

还没有留言,来说点什么吧。

Kubernetes ConfigMap 与 Secret:分离配置和镜像 · LXH·BLOG