Kubernetes ConfigMap与Secret配置管理

Kubernetes ConfigMap与Secret配置管理

_

一、ConfigMap

1. 开发的痛点问题

传统容器部署会将应用配置、环境变量直接写入Dockerfile或打包进镜像,配置与镜像深度耦合。任意微小的配置修改都需要重新构建、推送镜像,还要重建Pod,流程繁琐且运维效率低下。同时项目需要适配开发、测试、生产等多套运行环境,不同环境的配置各不相同,在多环境下还需要维护多套不同的镜像,容易造成镜像冗余混乱。

集群内多个业务Pod存在大量通用配置,但传统模式需要在每个Deployment中单独配置环境变量,重复度高。公共配置更新时需逐一修改所有业务清单,容易出现遗漏、配置不一致的问题。同时,没有统一的配置视图,无法集中管理和快速查询集群公共参数。

若将大量业务配置直接写在Pod资源清单中,会导致配置文件臃肿杂乱、可读性差,容易出现格式错误引发Pod异常。不同的服务、命名空间需要相同配置时,只能复制粘贴,无法直接复用一份配置模板。

Web类应用需要适配开发、测试、生产等多套环境,不同环境的数据库、中间件等配置差异较大。传统模式没有标准化配置方案,迁移至Kubernetes后,甚至需要人工进入Pod手动改配置,操作麻烦、容错率低,无法满足线上业务稳定运行的需求。

2. ConfigMap概述

ConfigMap是Kubernetes内置的配置管理资源,专门用于存放环境变量、启动参数、脚本、JSON/Properties等非敏感明文配置,相当于专属的配置存储目录。核心作用是实现容器镜像与业务配置解耦,支持配置独立管理、动态更新,无需修改镜像、重新打包重构应用。

ConfigMap仅支持存储普通明文数据,不适合用于存放密码、密钥等敏感信息,对应敏感数据需使用Secret。可被Pod、Deployment、StatefulSet挂载使用,主要有两种使用方式:注入环境变量、挂载为容器内文件。

ConfigMap不适用于承载大规模数据,其存储内容上限为1MiB。若业务所需存储数据超出该限制,建议改用存储卷挂载、独立数据库或文件服务。

3. ConfigMap使用事项

  • ConfigMap需要提前创建,若重建Pod时引用了不存在的ConfigMap,Pod会持续处于Pending状态,无法正常启动。

  • ConfigMap具备命名空间隔离特性,Pod仅能调用相同命名空间下的ConfigMap,无法跨命名空间引用其它命名空间的配置资源。

  • 日常运维中,通常基于YAML文件声明式创建ConfigMap;Pod引用ConfigMap通常是volume挂载方式。

  • 采用volume方式挂载ConfigMap后,更新或删除ConfigMap内容,容器挂载目录下配置文件会自动同步变更。实现配置热更新,无需重启Pod即可生效。

二、ConfigMap创建

1. 从目录创建ConfigMap

[Step1] 新建目录用于存储配置文件。

root@k8s-master:~# mkdir -p /configfile/configmap

[Step2] 新建配置文件,模拟服务后端相关参数配置。

root@k8s-master:~# vim /configfile/configmap/server.properties
​
# 写入下列内容
port=8080
timeout=3000
max.connection=200
log.level=info

[Step3] 新建配置文件,模拟用户功能参数配置。

root@k8s-master:~# vim /configfile/configmap/user.properties
​
# 写入下列内容
register.enable=true
vip.discount=0.8
token.expire=86400
avatar.default=system_01

[Step4] 使用kubectl结合“--from-file”参数创建ConfigMap时,指定目录内的全部文件都会自动生成键值对存入ConfigMap。其中键对应文件名称,值对应文件完整内容。

root@k8s-master:~# kubectl create configmap game-config --from-file=/configfile/configmap/

[Step5] 验证:查看当前命名空间下所有的ConfigMap,可以看到上述创建的ConfigMap资源。

root@k8s-master:~# kubectl get configmaps

[Step6] 验证:查看当前命名空间下名为game-config的ConfigMap详情,可以看到该ConfigMap的完整配置信息。

root@k8s-master:~# kubectl describe configmaps game-config

2. 从文件创建ConfigMap

--from-file参数支持重复传入,可一次性读取多个文件来构建ConfigMap。

[Step1] 新建配置文件,模拟聊天服务后台相关参数配置。

root@k8s-master:~# vim chat-server.properties
​
# 写入下列内容
server.port=9000
max.online.user=10000
msg.cache.time=3600
heartbeat.interval=30
log.level=warn

[Step2] 新建配置文件,模拟服务后端相关参数配置。

root@k8s-master:~# vim chat-user.properties
​
# 写入下列内容
register.allow=true
nickname.max.length=16
avatar.upload.size=5242880
token.valid.hour=24
friend.max.count=500

[Step3] 新建配置文件,模拟聊天客户端界面相关参数配置。

root@k8s-master:~# vim chat-ui.properties

# 写入下列内容
theme.default=light
msg.font.size=14
msg.show.time=true
chat.bubble.color=#f5f5f5
notification.enable=true

[Step4] 使用kubectl结合“--from-file”参数指定多个文件创建ConfigMap。

root@k8s-master:~# kubectl create configmap chat-config --from-file=chat-server.poroperties \
> --from-file=chat-ui.properties \
> --from-file=chat-user.properties

[Step5] 验证:查看当前命名空间下所有的ConfigMap,可以看到上述创建的ConfigMap资源。

root@k8s-master:~# kubectl get configmaps

[Step6] 验证:查看当前命名空间下名为chat-config的ConfigMap详情,可以看到该ConfigMap的完整配置信息。

root@k8s-master:~# kubectl get configmaps chat-config

3. 从literal值创建ConfigMap

通过目录、文件方式创建ConfigMap,需要提前编写本地配置文件。Kubernetes提供了无需本地文件的快速创建方式,通过“--from-literal”参数可以直接传入键值对从而生成配置。

[Step1] 使用kubectl结合“--from-literal”参数指定键值对形式创建ConfigMap。

root@k8s-master:~# kubectl create configmap db-config \
> --from-literal=db.host=127.0.0.1 \
> --from-literal=db.port=3306 \
> --from-literal=db.name=root

[Step2] 验证:查看当前命名空间下所有的ConfigMap,可以看到上述创建的ConfigMap资源。

root@k8s-master:~# kubectl get configmaps

[Step3] 验证:查看当前命名空间下名为db-config的ConfigMap详情,可以看到该ConfigMap的完整配置信息。

root@k8s-master:~# kubectl describe configmaps db-config

4. 从YAML文件创建ConfigMap

ConfigMap和Deployment、Pod等资源对象一致,支持通过YAML配置文件完成资源创建。

[Step1] 本地新建YAML清单,定义ConfigMap资源描述模板。

root@k8s-master:~# vim network-sec-config.yml

# 写入下列内容
apiVersion: v1		# 固定语法
kind: ConfigMap		# 资源类型
metadata:
  name: network-sec-config
data:
  # 单行键值对,类似使用 --from-iterial
  vpn-addr-pool: "172.16.0.0/16"
  vpn-encryption: "AES-256-GCM"
  max-conn: "200"
  # 多行键值对,类似使用 --from-file
  security-policy.conf: |
    login-verify-code = on
    access-timeout = 1800

[Step2] 根据YAML清单向Kubernetes集群声明式地创建ConfigMap资源。

root@k8s-master:~# kubectl create -f network-sec-config.yml

[Step3] 验证:查看当前命名空间下所有的ConfigMap,可以看到上述创建的ConfigMap资源。

root@k8s-master:~# kubectl get configmaps

[Step4] 验证:查看当前命名空间下名为network-sec-config的ConfigMap详情,可以看到该ConfigMap的完整配置信息。

root@k8s-master:~# kubectl describe configmaps network-sec-config

三、ConfigMap使用

1. 通过环境变量使用ConfigMap

可以直接将ConfigMap里的配置参数,直接给到容器内部程序当作环境变量使用,一共有两种使用方法:

  • env:按需单独创建环境变量,只引用ConfigMap中的某一项配置;

  • envFrom:一键导入,会将ConfigMap中的全部配置批量转换为容器环境变量。

[Step1] 本地新建YAML清单,定义Pod资源描述模板,并引用network-sec-config和db-config。

root@k8s-master:~# vim busybox-configmap.yml

# 写入下列内容
apiVersion: v1	# 固定语法
kind: Pod		# 资源类型
metadata:
  name: busybox-configmap
spec:
  containers:
    - name: busybox-configmap
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      args: ["/bin/sh","-c","sleep 1000"]
      # 单个环境变量注入配置,仅读取ConfigMap中的某一个键的值
      env:
        - name: max-conn	# 环境变量的名称
          valueFrom:		# 变量值来源于外部
            configMapKeyRef:	# 数据源指定为ConfigMap的单个键
              name: network-sec-config	# 引用的ConfigMap名称
              key: max-conn	# ConfigMap的内部的键名
      # 批量注入环境变量,读取整个ConfigMap中的所有键值对
      envFrom:
        - configMapRef:		# 引用完整的ConfigMap
            name: db-config	# 引用的ConfigMap名称

[Step2] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f busybox-configmap.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。

root@k8s-master:~# kubectl get -f busybox-configmap.yml

[Step4] 验证:登录busybox-configmap,全局过滤环境变量,可以顺利看到注入的环境变量。

root@k8s-master:~# kubectl exec -it busybox-configmap -- /bin/sh
/ # env | grep -E "max-conn|db"

2. 通过Volume使用ConfigMap

采用Volume挂载ConfigMap的方式,与存储管理中的emptyDir、hostPath卷的使用逻辑相似。

ConfigMap挂载完成后会在容器内自动生成独立目录,目录下会自动生成对应配置文件。

其中ConfigMap的键作为文件名称,对应的值即为文本内容。

[Step1] 本地新建YAML清单,定义Pod资源描述模板,并引用network-sec-config。

root@k8s-master:~# vim busybox-network-pod.yml

# 写入下列内容
apiVersion: v1	# 固定语法
kind: Pod		# 资源类型
metadata:
  name: busybox-network-pod
spec:
  containers:
    - name: busybox-network-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      args: ["/bin/sh","-c","sleep 1000"]
      volumeMounts:			# 存储卷挂载配置
        - name: network-sec-config		# Volume卷名称
          mountPath: "/mnt/network-sec-config"	# 容器内挂载目录
          readOnly: true	# 挂载目录为只读
  volumes:			# 定义存储卷
   # 自定义存储卷名称,与[containers.volumeMounts.name]对应
    - name: network-sec-config
      configMap:	# 指定卷的数据源为ConfigMap资源
        # 绑定集群中名为network-sec-config的ConfigMap
        name: network-sec-config

[Step2] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f busybox-network-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。

root@k8s-master:~# kubectl get -f busybox-network-pod.yml

[Step4] 验证:登录busybox-network-pod,可以在预先挂载的目录下查看自动生成的配置文件,读取文件内容可以获取ConfigMap内对应的键值信息。

root@k8s-master:~# kubectl exec -it busybox-network-pod -- /bin/sh
/ # ls -a /mnt/network-sec-config/
/ # cat /mnt/network-sec-config/security-policy.conf

[Step5] 在线编辑ConfigMap,添加一行。

root@k8s-master:~# kubectl edit configmaps network-sec-config

# 在security-policy.conf添加下列内容
log.level = warn

[Step6] 登录busybox-network-pod,查看挂载目录下security-policy.conf文件内容,可以看到已热更新。

root@k8s-master:~# kubectl exec -it busybox-network-pod -- /bin/sh
/ # cat /mnt/network-sec-config/security-policy.conf

四、Secret

1. Secret概述

Secret是Kubernetes内置核心资源,专门用于存储敏感数据,例如密码、token、数据库账号、私钥等。ConfigMap适合存放明文普通数据,Secret用于保管不能直接暴露的私密信息,二者使用方式高度相似,但是Secret有基础脱敏保护机制。

Secret的核心定位是避免敏感数据硬编码写在Pod/YAML中,不将账号密码直接暴露在命令行、日志、镜像内。同时精细化权限控制,限制谁能够读取私密数据。在创建、查看和编辑Pod的流程中Secret暴露风险较小,系统会对Secret对象采取额外的预防措施,例如避免将其写入磁盘中可能的位置。只有Pod请求的Secret在其容器内才是可见的,一个Pod无法访问另外一个Pod的Secret。

和ConfigMap挂载机制一致,Secret通过Volume方式挂载后,修改或删除数据,容器挂载目录中的数据会自动同步更新,实现配置热更新,无需重启Pod即可生效。

2. 数据存储机制

Secret存入etcd时仅对数据做Base64转码,非加密。仅用于隐藏明文展示,不具备数据防护能力。任何人在获取Secret YAML后,通过下列命令即可还原原始敏感内容。

echo "编码字符串" | base64 -d

在生产环境中建议开启etcd静态加密,避免etcd数据泄露造成全部Secret明文泄露。同时,搭配RBAC权限管控,限制普通开发人员查看、解密Secret资源。ApiServer与kubelet、客户端之间采用HTTPS加密通信,Secret在传输链路中不会以明文形式抓包窃取。

五、Secret创建

1. 通过kubectl命令创建Secret

[Step1] 分别创建两个文件,存储用户名和密码。

root@k8s-master:~# echo -n "admin" > username.txt
root@k8s-master:~# echo -n "admin@123" > password.txt

[Step2] 使用kubectl命令创建Secret,指定Secret名称为login-user-passwd。其中generic参数表示从本地的文件、目录或实际值(literal value)读取。

root@k8s-master:~# kubectl create secret generic login-user-passwd \
> --from-file=./username.txt \
> --from-file=./password.txt

[Step3] 验证:查看当前命名空间下所有Secret,可以看到上述创建的资源。其中Opaque为通用Secret类型,内部数据采用Base64编码存储。

root@k8s-master:~# kubectl get secrets

[Step4] 验证:查看当前命名空间下名为login-user-passwd的Secret详情,对比ConfigMap可以发现,Secret不会直接显示原始明文数据。

root@k8s-master:~# kubectl describe secrets login-user-passwd

[Step5] 可以获取Secret并输出YAML,查看Base64编码内容。然后复制编码字符串,手动解密

root@k8s-master:~# kubectl get secrets login-user-passwd -o yaml
root@k8s-master:~# echo "YWRtaW5AMTIz" | base64 -d

2. 使用YAML创建Secret

[Step1] 为了规避YAML文件中的值被直接看到,因此需要先用Base64编码后再写入YAML。

root@k8s-master:~# echo "admin" | base64
root@k8s-master:~# echo "admin@123" | base64

[Step2] 本地新建YAML清单,定义Secret资源描述模板。

root@k8s-master:~# vim admin-secret.yml

# 写入下列内容
apiVersion: v1	# 固定语法
kind: Secret	# 资源类型
metadata:
  name: admin-secret
type: Opaque	# 指定Secret类型
# 存放Base64编码后的敏感数据,禁止直接填写明文
data:
  username: YWRtaW4K
  password: YWRtaW5AMTIzCg==

[Step3] 根据YAML清单向Kubernetes集群声明式地创建Secret资源。

root@k8s-master:~# kubectl create -f admin-secret.yml

[Step4] 验证:查看当前命名空间下所有Secret,可以看到上述创建的资源。

root@k8s-master:~# kubectl get secrets

[Step5] 验证:查看当前命名空间下名为admin-secret的Secret详情,同样无法直接显示原始明文数据。

root@k8s-master:~# kubectl describe secrets admin-secret

六、Secret使用

1. 通过Volume方式使用Secret

通过Volume挂载Secret的使用逻辑与ConfigMap类似。

Secret挂载至容器后会生成独立目录,内部每一组键值对应一个文件:键为文件名,值为文件内容。

Secret挂载至Pod时会自动解码,因此在容器内部是明文显示。

[Step1] 本地新建YAML清单,定义Pod资源描述模板,并引用admin-secret。

root@k8s-master:~# vim admin-secret-pod.yml

# 写入下列内容
apiVersion: v1	# 固定语法
kind: Pod		# 资源类型
metadata:
  name: admin-secret-pod
spec:
  containers:
    - name: admin-secret-pod
      image: busybox
      imagePullPolicy: IfNotPresent
      args: ["/bin/sh","-c","sleep 1000"]
      volumeMounts:		# 存储卷挂载配置
        - name: admin-secret		# Volume卷名称
          mountPath: "/etc/secret"	# 容器内挂载目录
          readOnly: true			# 挂载目录为只读
  volumes:		# 定义存储卷
    # 自定义存储卷名称,与[containers.volumeMounts.name]对应
    - name: admin-secret
      secret:	# 指定卷的数据源为Secret资源
        # 绑定集群中名为admin-secret的Secret
        secretName: admin-secret

[Step2] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f admin-secret-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。

root@k8s-master:~# kubectl get -f admin-secret-pod.yml

[Step4] 验证:登录admin-secret-pod,可直接读取挂载目录下的文件,获取解码后的明文密钥内容

root@k8s-master:~# kubectl exec -it admin-secret-pod -- /bin/sh
/ # cat /etc/secret/username
/ # cat /etc/secret/password

[Step5] 新建键值条目,首先将api_token明文进行Base64编码,然后在线编辑Secret方式新增。

root@k8s-master:~# echo "7s9KdF2n8GpR5tXbQa3zYcV0mN1jL4hU" | base64
root@k8s-master:~# kubectl edit secrets admin-secret

# 在data添加下列内容
N3M5S2RGMm44R3BSNXRYYlFhM3pZY1YwbU4xakw0aFUK

[Step6] 登录admin-secret-pod,查看挂载目录下security-policy.conf文件内容,可以看到已热更新。

root@k8s-master:~# kubectl exec -it admin-secret-pod -- /bin/sh
/ # cat /etc/secret/api_token

2. 仅挂载指定值

在挂载Secret的时候可以指定items,只将Secret中的某些参数传递到Pod。

[Step1] 本地新建YAML清单,定义Pod资源描述模板,并引用admin-secret。

root@k8s-master:~# vim username-secret-pod.yml

# 写入下列内容
apiVersion: v1	# 固定语法
kind: Pod		# 资源类型
metadata:
  name: username-secret-pod
spec:
  containers:
    - name: username-secret-pod
      image: busybox:latest
      imagePullPolicy: IfNotPresent
      args: ["/bin/sh","-c","sleep 1000"]
      volumeMounts:		# 存储卷挂载配置
        - name: admin-secret		# Volume卷名称
          mountPath: "/etc/secret"	# 容器内挂载目录
          readOnly: true			# 挂载目录为只读
  volumes:		# 定义存储卷
    # 自定义存储卷名称,与[containers.volumeMounts.name]对应
    - name: admin-secret
      secret:	# 指定卷的数据源为Secret资源
       # 绑定集群中名为admin-secret的Secret
        secretName: admin-secret
        # 自定义映射规则,仅提取Secret内指定key,并自定义容器内文件名
        items:
          - key: username		# 映射规则名称
            # 将Secret中key=username的值,在挂载目录中生成文件my-username
            path: my-username

[Step2] 根据YAML清单向Kubernetes集群声明式地创建Pod资源。

root@k8s-master:~# kubectl create -f username-secret-pod.yml

[Step3] 验证:基于文件内定义的资源清单,查询集群中该资源的运行状态与基础信息。

root@k8s-master:~# kubectl get -f username-secret-pod.yml

[Step4] 验证:登录username-secret-pod,查看挂载目录可以发现仅挂载username。读取该文件可以直接获取解码后的明文密钥内容。

root@k8s-master:~# kubectl exec -it username-secret-pod -- /bin/sh
/ # ls -a /etc/secret/
/ # cat /etc/secret/my-username

[Step5] 先对新的username进行Base64编码,然后在线编辑Secret更新。

root@k8s-master:~# echo "user01" | base64
root@k8s-master:~# kubectl edit secrets admin-secret

# 将data.usename内容修改为下列值
username: dXNlcjAxCg==

[Step6] 登录username-secret-pod,查看挂载目录下my-username文件内容,可以看到已热更新。

root@k8s-master:~# kubectl exec -it username-secret-pod -- /bin/sh
/ # cat /etc/secret/my-username

Kubernetes 存储管理:PV/PVC与StorageClass 2026-10-27
Kubernetes节点资源驱逐、调度策略与资源管控 2026-10-27

评论区