ConfigMap实战:Pod挂载ConfigMap作为环境变量、作为卷挂载、热更新机制
说实话,ConfigMap 这东西刚出来的时候,我第一反应是:这不就是个键值对存储吗?有啥好学的?直到我在一个生产环境里,因为配置改完忘了重建 Pod,导致线上服务挂了半小时……嗯,从那以后我再也不敢小看它了。
今天咱们就把它掰开揉碎,讲清楚三种核心用法:环境变量挂载、卷挂载、还有那个让人又爱又恨的热更新机制。
一、ConfigMap 是什么?
说白了,ConfigMap 就是 Kubernetes 里专门用来存配置的“小仓库”。它把配置和镜像解耦,你改配置不用重新打包镜像,也不用重启整个集群。
我个人习惯,所有非敏感配置都扔进 ConfigMap。比如:
- 应用的环境变量(
APP_ENV=production) - 日志级别(
LOG_LEVEL=info) - 数据库连接地址(非密码部分)
- Nginx 配置文件、Prometheus 告警规则等
二、创建 ConfigMap 的几种姿势
创建 ConfigMap 其实很简单,我一般用这三种方式:
1. 直接写 YAML 文件
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: production
LOG_LEVEL: info
DB_HOST: db.example.com
DB_PORT: "3306"
2. 从文件创建
你有个 nginx.conf 文件?直接导入:
kubectl create configmap nginx-config --from-file=nginx.conf
3. 从 .env 文件创建
我特别喜欢这个方式,因为本地开发用的 .env 文件可以直接复用:
kubectl create configmap app-env --from-env-file=.env
三、Pod 挂载 ConfigMap 作为环境变量
这是最常用的方式。你想想看,应用启动时读环境变量,多自然。
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app
image: my-app:latest
envFrom:
- configMapRef:
name: app-config
这样 Pod 启动后,APP_ENV、LOG_LEVEL 这些变量就自动注入进去了。
四、Pod 挂载 ConfigMap 作为卷
这种方式就灵活多了。你可以把整个配置文件挂载进去,也可以只挂载某个 key。
完整挂载示例
apiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: app
image: my-app:latest
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: app-config
这样 /etc/config 目录下就会有 APP_ENV、LOG_LEVEL 等文件,每个 key 对应一个文件。
只挂载某个 key
有时候你只想挂载某个配置文件,比如 nginx.conf:
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config
items:
- key: nginx.conf
path: nginx.conf
五、热更新机制——这个才是重点
好,终于到热更新了。为什么我要单独拿出来讲?因为这里坑最多。
卷挂载方式支持热更新。你改了 ConfigMap,Pod 里的文件会自动同步。但注意,是“文件”同步,不是“进程”同步。
什么意思呢?举个例子:
- 你挂载了一个
nginx.conf到/etc/nginx/nginx.conf - ConfigMap 更新后,文件内容变了
- 但 Nginx 进程不会自动 reload
- 你需要手动执行
nginx -s reload或者发 SIGHUP 信号
我曾经遇到过一个场景:改了日志级别配置,以为热更新会自动生效,结果排查了半天才发现应用没有监听文件变化。嗯,从那以后我养成了一个习惯——热更新只保证文件更新,不保证进程感知。
- 热更新有延迟,通常几秒到几分钟不等(取决于 kubelet 同步周期)
- 如果应用不监听文件变化,热更新等于没用
- 环境变量方式不支持热更新,别指望它
- SubPath 挂载也不支持热更新,这个坑我踩过两次
六、实战:一个完整的例子
咱们来个完整的,从创建 ConfigMap 到 Pod 挂载,再到热更新验证。
1. 创建 ConfigMap
kubectl create configmap game-config --from-literal=game.properties=level=3 --from-literal=ui.properties=color=blue
2. 创建 Pod 挂载卷
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo
spec:
containers:
- name: test
image: busybox
command: ["/bin/sh", "-c", "while true; do cat /etc/config/game.properties; sleep 10; done"]
volumeMounts:
- name: config
mountPath: /etc/config
volumes:
- name: config
configMap:
name: game-config
3. 验证热更新
# 查看当前内容
kubectl logs configmap-demo
# 修改 ConfigMap
kubectl edit configmap game-config
# 把 level=3 改成 level=5
# 等一会儿,再看日志
kubectl logs configmap-demo
# 你会发现内容已经变了
七、总结一下
| 挂载方式 | 是否支持热更新 | 适用场景 |
|---|---|---|
| 环境变量 | ❌ 不支持 | 启动时固定的配置 |
| 卷挂载(完整) | ✅ 支持 | 需要动态更新的配置文件 |
| 卷挂载(SubPath) | ❌ 不支持 | 挂载单个文件且不需要更新 |
我个人建议:
- 如果配置基本不变,用环境变量,简单粗暴
- 如果需要动态更新,用卷挂载,但应用要支持监听文件变化
- 千万别把敏感信息放 ConfigMap,那是 Secret 的活
好了,ConfigMap 实战就讲到这里。下一章咱们聊聊 Secret,那个比 ConfigMap 更敏感、也更容易踩坑的东西。