17、k8s配置管理中心configmap

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 的变化,并最终把新内容同步到容器内的文件中。这个过程不是瞬时的,因为:

  1. kubelet 同步周期:kubelet 有一个默认的同步周期(通常为 1 分钟),会定期检查挂载的 ConfigMap 是否更新。

  2. Watch 机制:kubelet 也会通过 API Server 的 watch 事件感知 ConfigMap 变化,这可能让更新更快(你实测的 10 秒左右是合理的)。

  3. 原子替换:更新时,kubelet 会先写入新的文件,然后通过符号链接切换,保证容器内看到的文件内容要么全是旧的,要么全是新的,不会出现半新半旧。

重要限制:subPath 挂载不会更新

如果你在 volumeMounts 中使用了 subPath(例如只挂载 ConfigMap 中的某个键到指定文件),那么该文件在容器启动后永远不会 随 ConfigMap 更新。这是 Kubernetes 的已知行为,因为 subPath 挂载使用的是文件路径的硬链接,不会跟随 ConfigMap 卷的符号链接切换。

相关推荐
Eminem891 小时前
15、k8s控制器Statefulset
k8s
Eminem893 小时前
16、k8s控制器Daemnonset
k8s
深蓝电商API18 小时前
Docker+K8s部署爬虫:从单机到集群的完整路线
爬虫·docker·k8s
运维开发那些事20 小时前
推理集群稳定性最佳实践
k8s·gpu算力
meijinmeng3 天前
将 Kubernetes 部署扩展到多个Region区域:GitOps 参考架构
k8s·cicd
张洛闻Eren3 天前
Ansible【第二课】:实施 Ansible Playbook
linux·运维·服务器·云原生·kubernetes·k8s·ansible
紫神9 天前
DDS 通信技术说明
网络·云原生·容器·k8s·dds·弱网
Eminem8914 天前
14、k8s持久化存储
k8s
上火的金鱼妹16 天前
higress网关访问+ 模型访问的安全策略管控
k8s·higress·ai网关