1、Configmap概述
Configmap是k8s中的资源对象,用于保存非机密性的配置的,数据可以用key/value键值对的形式保存,也可通过文件的形式保存。
1.1 Configmap能解决哪些问题?
我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。所以,k8s中引入了Configmap资源对象,可以当成volume挂载到pod中,实现统一的配置管理。

1、Configmap是k8s中的资源,相当于配置文件,可以有一个或者多个Configmap;
2、Configmap可以做成Volume,k8s pod启动之后,通过volume形式映射到容器内部指定目录上;
3、容器中应用程序按照原有方式读取容器特定目录上的配置文件。
4、在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
1.2 Configmap应用场景
1、使用k8s部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap可以将配置信息和docker镜像解耦,以便实现镜像的可移植性和可复用性,因为一个configMap其实就是一系列配置信息的集合,可直接注入到Pod中给容器使用。configmap注入方式有两种,一种将configMap做为存储卷,一种是将configMap通过env中configMapKeyRef注入到容器中。
2、使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配
置的话,那么更新配置就很麻烦,使用configmap可以友好的进行配置共享。
1.3 Configmap局限性
ConfigMap在设计上不是用来保存大量数据的。在ConfigMap中保存的数据不可超过1MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
2、Configmap创建方法
2.1 命令行直接创建
直接在命令行中指定configmap参数创建,通过--from-literal指定参数
bash
kubectl create configmap tomcat-config \
--from-literal=tomcat_port=8080 \
--from-literal=server_name=myapp.tomcat.com
查看configmap
bash
# yaml方式查看
kubectl get configmap tomcat-config -o yaml
# describe方式查看
kubectl describe configmap tomcat-config


命令说明
-
kubectl create configmap:创建一个 ConfigMap 资源。 -
tomcat-config:ConfigMap 的名称。 -
--from-literal=tomcat_port=8080:添加一个键值对,键为tomcat_port,值为8080。 -
--from-literal=server_name=myapp.tomcat.com:添加另一个键值对,键为server_name,值为myapp.tomcat.com。
执行后,Kubernetes 会创建一个名为 tomcat-config 的 ConfigMap,包含两个数据项:
-
tomcat_port: "8080"(注意值是字符串) -
server_name: "myapp.tomcat.com"
仅生成 YAML 而不实际创建(便于版本控制):
bash
kubectl create configmap tomcat-config \
--from-literal=tomcat_port=8080 \
--from-literal=server_name=myapp.tomcat.com \
--dry-run=client -o yaml > tomcat-config.yaml
2.2 通过文件创建
bash
vim nginx.conf
# 填入以下内容
server {
server_name www.nginx.com;
listen 80;
root /home/nginx/www/
}
创建 查看configmap
bash
# 创建configmap
kubectl create configmap www-nginx --from-file=www=./nginx.conf
# yaml方式查看
kubectl get configmap www-nginx -o yaml
# describe方式查看
kubectl describe configmap www-nginx
参数说明
| 部分 | 含义 |
|---|---|
kubectl create configmap |
创建 ConfigMap 资源 |
www-nginx |
ConfigMap 的名称 |
--from-file=www=./nginx.conf |
从文件创建数据,格式为 键名=文件路径 |
www |
在 ConfigMap 中存储的键名 |
./nginx.conf |
本地文件路径,其内容会作为该键的值 |

2.3 指定目录创建
bash
# 创建目录
mkdir test-a
# 创建一个文件
vi my-server.cnf
# 填入
server-id=1
# 创建一个文件
vi my-slave.cnf
# 填入
server-id=2
#指定目录创建configmap
kubectl create configmap mysql-config --from-file=/tmp/configmap/test-a
kubectl get configmap mysql-config -o yaml
kubectl describe configmap mysql-config

注意:子目录不会被包含,假设test-a下面还有子目录,则子目录中的文件不会作为configmap中的keyvalue。
2.3 编写configmap资源清单YAML文件
bash
# 创建配置文件
vi mysql-configmap.yaml
#填入以下内容
apiVersion: v1 # API 版本,v1 表示核心 API 组
kind: ConfigMap # 资源类型为 ConfigMap,用于存储非机密配置数据
metadata: # 资源元数据
name: mysql # ConfigMap 名称
labels: # 标签集合
app: mysql # 标签 app=mysql,便于选择和分组
data: # 配置数据,键值对形式,值均为字符串
master.cnf: | # 主库配置文件,键名为 master.cnf,| 表示保留换行符的多行字符串
[mysqld] # MySQL 服务端配置段
log-bin # 开启二进制日志,用于主从复制
log_bin_trust_function_creators=1 # 允许创建存储函数,避免主从复制因函数报错
lower_case_table_names=1 # 表名不区分大小写(通常用于兼容 Windows 或特定需求)
slave.cnf: | # 从库配置文件,键名为 slave.cnf
[mysqld] # MySQL 服务端配置段
super-read-only # 开启超级只读模式,从库仅允许超级用户写入(MySQL 8.0+)
log_bin_trust_function_creators=1 # 允许创建存储函数,与主库保持一致
bash
# 创建configmap
kubectl apply -f mysql-configmap.yaml
# 查看configmap
kubectl describe configmap mysql-configmap

3、使用Configmap
3.1 通过环境变量引入:使用configMapKeyRef
bash
# 创建yaml
vi mysql-configmap.yaml
# 填入以下内容
apiVersion: v1 # API 版本,v1 表示核心 API 组
kind: ConfigMap # 资源类型为 ConfigMap,用于存储非机密配置数据
metadata: # 资源元数据
name: mysql # ConfigMap 名称
labels: # 标签集合
app: mysql # 标签 app=mysql,便于选择和分组
data: # 配置数据,键值对形式,值均为字符串
log: "1" # 键 log,值为字符串 "1",对应 Pod 环境变量 log_bin 的引用
lower: "1" # 键 lower,值为字符串 "1",对应 Pod 环境变量 lower 的引用
master.cnf: | # 主库配置文件,键名为 master.cnf,| 表示保留换行符的多行字符串
[mysqld] # MySQL 服务端配置段
log-bin # 开启二进制日志,用于主从复制
log_bin_trust_function_creators=1 # 允许创建存储函数,避免主从复制因函数报错
lower_case_table_names=1 # 表名不区分大小写(通常用于兼容 Windows 或特定需求)
slave.cnf: | # 从库配置文件,键名为 slave.cnf
[mysqld] # MySQL 服务端配置段
super-read-only # 开启超级只读模式,从库仅允许超级用户写入(MySQL 8.0+)
log_bin_trust_function_creators=1 # 允许创建存储函数,与主库保持一致
bash
# 更新configmap
kubectl apply -f mysql-configmap.yaml
# 查看configmap
kubectl describe configmap mysql

bash
# 创建mysql-pod.yaml
vi mysql-pod.yaml
#填入以下内容
apiVersion: v1 # API 版本,Pod 属于核心 API 组 v1
kind: Pod # 资源类型:Pod
metadata: # Pod 元数据
name: mysql-pod # Pod 名称
spec: # Pod 规格
containers: # 容器列表
- name: mysql # 容器名称
image: busybox # 容器镜像
command: [ "/bin/sh", "-c", "sleep 3600" ] # 容器启动命令:休眠 3600 秒
env: # 环境变量列表
- name: log_bin # 定义环境变量 log_bin
valueFrom: # 环境变量值来源
configMapKeyRef: # 从 ConfigMap 的某个键引用
name: mysql # 指定 ConfigMap 的名字
key: log # 指定 ConfigMap 中的 key
- name: lower # 定义环境变量 lower
valueFrom: # 环境变量值来源
configMapKeyRef: # 从 ConfigMap 的某个键引用
name: mysql # 指定 ConfigMap 的名字(同上)
key: lower # 指定 ConfigMap 中的 key
restartPolicy: Never # 重启策略:Never,Pod 终止后不重启
bash
# 应用 Pod
kubectl apply -f mysql-pod.yaml
# 查看 Pod 状态
kubectl get pod mysql-pod
# 查看环境变量是否注入成功
kubectl exec mysql-pod -- env | grep -E 'log_bin|lower'

3.2 通过环境变量引入:使用envfrom
bash
# 创建 mysql-pod-envfrom.yaml
vi mysql-pod-envfrom.yaml
#填入以下内容
apiVersion: v1 # API 版本,Pod 属于核心 API 组 v1
kind: Pod # 资源类型:Pod
metadata: # Pod 元数据
name: mysql-pod-envfrom # Pod 名称
spec: # Pod 规格
containers: # 容器列表
- name: mysql # 容器名称
image: busybox # 容器镜像
imagePullPolicy: IfNotPresent # 镜像拉取策略:本地存在则不拉取
command: [ "/bin/sh", "-c", "sleep 3600" ] # 容器启动命令:休眠 3600 秒
envFrom: # 从 ConfigMap/Secret 批量注入环境变量
- configMapRef: # 引用一个 ConfigMap 作为环境变量来源
name: mysql # 指定 ConfigMap 的名字
restartPolicy: Never # 重启策略:Never,Pod 终止后不重启
bash
# 应用 Pod
kubectl apply -f mysql-pod-envfrom.yaml
# 查看 Pod 状态
kubectl get pod mysql-pod-envfrom
# 查看注入的环境变量
kubectl exec mysql-pod-envfrom -- env | grep -E 'log|lower'

envFrom 与 env 的区别
-
env:逐个指定环境变量,可精确控制变量名和来源键。 -
envFrom:批量注入,将 ConfigMap 中所有键值对直接作为环境变量,键名即变量名,值即变量值。无需逐个列出。
本示例使用 envFrom,因此 ConfigMap mysql 中的所有合法键都会成为环境变量。
⚠️ 注意事项
envFrom支持prefix字段,可为所有注入的变量加统一前缀,例如:
bash
envFrom:
- configMapRef:
name: mysql
prefix: MYSQL_
这样变量名会变成 MYSQL_log、MYSQL_lower。
3.3 把configmap做成volume,挂载到pod
bash
vi mysql-configmap.yaml
# 填入以下内容
apiVersion: v1 # API 版本,ConfigMap 属于核心 API 组 v1
kind: ConfigMap # 资源类型:ConfigMap,用于存储非机密配置
metadata: # 资源元数据
name: mysql # ConfigMap 名称,Pod 中通过该名称引用
labels: # 标签集合,用于分类和选择
app: mysql # 标签 app=mysql
data: # 配置数据,键值对形式;值必须是字符串
log: "1" # 键 log,值为字符串 "1";可通过 envFrom 注入为环境变量
lower: "1" # 键 lower,值为字符串 "1";同样可注入为环境变量
my.cnf: | # 键 my.cnf,值为多行字符串;| 表示保留换行
[mysqld] # 以下两行是 my.cnf 文件内容,不能加行尾注释
Welcome=eminem # 否则注释会变成配置文件的一部分
bash
#更新mysql-configmap.yaml
kubectl apply -f mysql-configmap.yaml
# 创建 mysql-pod-volume.yaml
vi mysql-pod-volume.yaml
# 填入以下内容
apiVersion: v1 # API 版本,Pod 属于核心 API 组 v1
kind: Pod # 资源类型:Pod
metadata: # Pod 元数据
name: mysql-pod-volume # Pod 名称
spec: # Pod 规格
containers: # 容器列表
- name: mysql # 容器名称
image: busybox # 容器镜像
command: [ "/bin/sh", "-c", "sleep 3600" ] # 容器启动命令:休眠 3600 秒
volumeMounts: # 容器内卷挂载配置
- name: mysql-config # 挂载名为 mysql-config 的卷
mountPath: /tmp/config # 挂载到容器内 /tmp/config 目录
volumes: # Pod 卷定义(与 containers 同级)
- name: mysql-config # 定义卷名 mysql-config
configMap: # 卷类型为 ConfigMap
name: mysql # 引用名为 mysql 的 ConfigMap
restartPolicy: Never # 重启策略:Never,Pod 终止后不重启
bash
# 应用 Pod
kubectl apply -f mysql-pod-volume.yaml
# 查看 Pod 状态
kubectl get pod mysql-pod-volume
# 查看挂载目录下的文件
kubectl exec mysql-pod-volume -- ls -l /tmp/config
# 查看 my.cnf 内容
kubectl exec mysql-pod-volume -- cat /tmp/config/my.cnf

⚠️ 注意事项
-
只读挂载:ConfigMap 卷默认是只读的,容器内无法修改这些文件。
-
文件名包含
.:my.cnf作为文件名完全合法,但作为环境变量名不合法,因此这种配置更适合用卷挂载而非envFrom。 -
更新同步 :ConfigMap 更新后,挂载的文件内容会自动同步(有延迟),但以
subPath挂载的不会同步。 -
卷名与 ConfigMap 名 :卷名
mysql-config是 Pod 内自定义的,ConfigMap 名mysql是实际资源名称,两者不必相同。
3.4 Configmap热更新
bash
kubectl edit configmap mysql
把logs: "1"变成log:"2"

| 使用方式 | 是否自动同步 | 说明 |
|---|---|---|
环境变量(env / envFrom) |
❌ 不会 | 容器启动时注入,之后不可变 |
卷挂载(volumeMounts) |
✅ 会,但有延迟 | kubelet 周期性同步,通常几秒到一分钟 |
卷挂载 + subPath |
❌ 不会 | subPath 挂载不会随 ConfigMap 更新 |
环境变量方式:为什么不会更新?
当 Pod 使用 env 或 envFrom 从 ConfigMap 读取数据时,kubelet 在创建容器的那一刻,会把ConfigMap 中的值读取出来,作为环境变量写入容器进程的环境。一旦容器启动,环境变量就固定了,后续 ConfigMap 再变化,也不会影响已运行的容器。
要让环境变量生效,必须重建 Pod:
-
对于直接创建的 Pod:删除后重新创建。
-
对于 Deployment/DaemonSet/StatefulSet:触发滚动更新(例如修改 Pod 模板,或使用
kubectl rollout restart)。
卷挂载方式:为什么会延迟更新?
当 ConfigMap 以卷的方式挂载到容器时,kubelet 会持续监听 ConfigMap 的变化,并最终把新内容同步到容器内的文件中。这个过程不是瞬时的,因为:
-
kubelet 同步周期:kubelet 有一个默认的同步周期(通常为 1 分钟),会定期检查挂载的 ConfigMap 是否更新。
-
Watch 机制:kubelet 也会通过 API Server 的 watch 事件感知 ConfigMap 变化,这可能让更新更快(你实测的 10 秒左右是合理的)。
-
原子替换:更新时,kubelet 会先写入新的文件,然后通过符号链接切换,保证容器内看到的文件内容要么全是旧的,要么全是新的,不会出现半新半旧。
重要限制:subPath 挂载不会更新
如果你在 volumeMounts 中使用了 subPath(例如只挂载 ConfigMap 中的某个键到指定文件),那么该文件在容器启动后永远不会 随 ConfigMap 更新。这是 Kubernetes 的已知行为,因为 subPath 挂载使用的是文件路径的硬链接,不会跟随 ConfigMap 卷的符号链接切换。