Kubernetes ConfigMap 与 Secret:分离配置和镜像
ConfigMap 与 Secret 的注入、挂载、变更联动,以及「Secret 不是加密」这条底线。
把配置从镜像里拆出来,是 12-Factor 的基本要求:同一个镜像,靠注入的配置跑不同环境。ConfigMap 装普通配置,Secret 装敏感配置。但很多人对 Secret 有个致命误解——Secret 不是加密的。
#基本用法:env 注入和文件挂载
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。
容器里两种消费方式:
# 方式一:整包注入成环境变量
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 校验注释:
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
- 把博客从 docker-compose 搬到 k3s:单机迁移与上线全过程在 4C3.6G 的云主机上把博客从 docker-compose 迁到单机 k3s。附完整 YAML 清单(Deployment、Service、PVC、Ingress、Certificate 等)与全部配置命令,记录部署、数据迁移与切换上线的踩坑过程。
- 5 台服务器,从二进制装 K8s 到 Spring Cloud 上线用 5 台服务器把整套平台搭出来:二进制部署 Kubernetes 1.36 高可用集群,装完 Harbor、Gitea、Nexus、Jenkins、Argo CD、监控日志链路追踪,最后把 Spring Cloud 微服务项目发布上线。每一步都给可执行命令。
- DevOps 运维中 AI 那些事把 AI 放进运维的真实分工:从服务器硬件、网络、GPU、内存,到虚拟化、Kubernetes、应用构建、CI/CD、可观测性、资源分配,再到 AI 自身的部署与算力调度。讲清楚哪些活它能接、边界划在哪、以及我踩过的那些坑。
留言 · remarks
00 条还没有留言,来说点什么吧。