ConfigMap
本教程共 65 篇 · 第 32 篇 · 更新于 2026-08-14 · 约 9 分钟阅读
本节目标:搞清楚 ConfigMap 是干什么的,会用两种主流方式把它喂给容器,知道什么数据不该放进去,以及”不可变”配置能帮你避开哪些麻烦。
你写完代码打包成镜像,里面却写死了数据库地址。换一个环境部署,就得重新打一遍包。这种事我早年没少干,后来才知道这叫”配置和代码耦合”。Kubernetes 给出的解法是 ConfigMap(配置映射)。
它就是一个存键值对的 API 对象。你可以把配置数据单独放进去,再让 Pod 去引用。镜像还是那个镜像,换环境只换 ConfigMap,不必重新构建。
32-1 ConfigMap 到底是什么
ConfigMap 跟大多数 Kubernetes 对象不一样,它没有 spec 字段。它只有 data 和 binaryData 两个地方存数据。
data 里放 UTF-8 字符串,binaryData 里放 base64 编码的二进制。大多数时候你用 data 就够了。每个键名只能由字母、数字、-、_、. 组成。
NoteConfigMap 不提供任何加密或保密能力。它只是把配置存起来,谁有 API 权限谁就能看。要存密码、令牌这类机密,请直接看下一章的 Secret。
还有一条要记牢:单个 ConfigMap 存的数据不能超过 1 MiB。如果你要放一大坨配置,老老实实挂个卷或者用别的存储方案,别硬塞。
32-2 怎么创建 ConfigMap
最省事的办法是用命令行。比如把环境变量式的配置直接生成出来:
kubectl create configmap game-demo \
--from-literal=player_initial_lives=3 \
--from-literal=ui_properties_file_name=user-interface.properties
也可以用文件生成,把现成的配置文件内容整段塞进去:
kubectl create configmap game-demo --from-file=game.properties
当然也能写 YAML。下面这个例子把”单行属性”和”整段配置”混在一起放:
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
这里 game.properties 的值看着像一整个文件,但其实它本质还是个字符串。ConfigMap 不区分单行还是多行,关键看 Pod 怎么消费它。
Tip用
--from-file时,键名默认就是文件名。想换个键名,可以写成--from-file=mykey=game.properties,这样键就成了mykey。
32-3 用环境变量注入容器
这是最常见的接法。Pod 里的容器通过 valueFrom.configMapKeyRef 拿到某个键的值:
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: CONFIGMAP_USERNAME
valueFrom:
configMapKeyRef:
name: myconfigmap
key: username
上面的意思是:从 myconfigmap 里取 username 这个键,放进容器环境变量 CONFIGMAP_USERNAME。环境变量名可以跟键名不一样,这点挺灵活。
如果你懒得一个个列,可以用 envFrom 把整个 ConfigMap 一次性展开成环境变量:
envFrom:
- configMapRef:
name: myconfigmap
Warning用环境变量方式引用的 ConfigMap,更新后不会自动刷新到容器里。要生效得重启 Pod。这一点经常被新手忽略,改了配置发现没变,多半是卡在这。
32-4 用卷挂载进容器
另一种方式更稳。把 ConfigMap 当成一个只读卷挂进去,每个键变成挂载目录下的一个文件,文件名就是键名。
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: myconfigmap
容器启动后,在 /etc/foo 目录下就能看到以键名命名的文件,读取它们就是读取配置。
这种方式有个大优点:ConfigMap 改了之后,kubelet 会周期性地把新内容同步进挂载的卷。容器下次读文件,拿到的就是新值。不过同步有延迟,取决于 kubelet 的同步周期和缓存策略,不是秒级生效。
Note如果你用
subPath把某个键单独挂成一个文件,那这个容器收不到更新。要用自动更新,就别用subPath,挂整个目录。
32-5 不可变 ConfigMap 与边界
从 v1.19 起,ConfigMap 支持标记为”不可变”。你只要在对象里加一行:
immutable: true
设成不可变后,这个 ConfigMap 的数据就再也改不了,只能删除重建。好处有两个:一是防止手滑改错配置把应用搞挂;二是集群里上万个 ConfigMap 时,关掉监听能明显降低 API 服务器压力。
最后划一下边界。ConfigMap 适合放不敏感的配置:功能开关、日志级别、服务地址、配置文件片段。密码、证书、令牌请交给 Secret。静态 Pod 不能引用 ConfigMap,这点也要记住。