K8S ConfigMap 快速开始

一、什么是 ConfigMap

ConfigMap 是 Kubernetes 中用于存储非敏感配置数据的 API 对象,支持以键值对(Key-Value)或文件的形式存储配置,允许将配置与镜像解耦,实现配置的集中管理和动态更新。

二、主要用途

  • 存储配置数据
  • 应用的配置文件(如 config.propertiesapp.yaml)。
  • 环境变量(如数据库连接字符串、API 地址)。
  • 命令行参数或启动脚本。
  • 解耦配置与镜像
  • 同一镜像可通过不同 ConfigMap 适配不同环境(如开发环境使用本地数据库,生产环境使用远程数据库)。
  • 使用 ConfigMap 可以统一管理不同环境(开发、测试、生产)的配置差异。
  • 解耦应用配置与镜像,避免硬编码配置到镜像中。
  • 动态更新配置
  • 修改 ConfigMap 后,可通过重启 Pod 或热加载(依赖应用支持)使新配置生效。

三、局限性

  • ConfigMap 并不提供保密或者加密功能。 如果你想存储的数据是机密的,请使用 Secret。
  • 在 ConfigMap 中保存的数据不可超过 1 MiB。如果你需要保存超出此尺寸限制的数据,你可能希望考虑挂载存储卷 或者使用独立的数据库或者文件服务。
  • ConfigMap 的热加载依赖应用自己实现。

四、创建 ConfigMap 的方式

ConfigMap 可通过 kubectl 命令YAML 文件 创建,支持三种数据源:文件目录字面量

4.1、通过 kubectl 命令创建

4.1.1、使用字面量创建

bash 复制代码
kubectl create configmap my-config --from-literal=username=admin --from-literal=password=123456
  • --from-literal=key1=config1 --from-literal=key2=config2
  • literal 字面量的意思
  • configmap 可以简写为 cm
bash 复制代码
kubectl describe cm my-config

4.1.2、使用文件创建

bash 复制代码
# 单个文件
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt

# 文件名 file1.txt 作为 key
kubectl create configmap my-config --from-file=/path/to/bar/file1.txt

# 多个文件
kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
  • 单个文件
javascript 复制代码
vim config.properties

### 文件内容如下
server.port=8080
application.name=myapp
bash 复制代码
kubectl create configmap my-config --from-file=config=./config.properties
bash 复制代码
# 文件名作为 key
kubectl create cm my-config --from-file=config.properties
  • 多个文件
javascript 复制代码
vim db.properties

### 文件内容如下
datasource.username=root
datasource.password=123456
datasource.url=jdbc:mysql://localhost:3306/order
bash 复制代码
kubectl create configmap my-config --from-file=config.properties --from-file=db.properties

4.1.3、使用目录创建

bash 复制代码
kubectl create configmap my-config --from-file=path/to/bar
bash 复制代码
mkdir conf
cd conf
vim application.yaml
### 文件内容如下
server:
  port: 8080

spring:
  cloud:
    nacos:
      discovery:
        username: nacos
        password: nacos
        group: DEFAULT_GROUP
        server-addr: 127.0.0.1:8848
  application:
    name: order-service
###
vim db.properties
### 文件内容如下
datasource.username=root
datasource.password=123456
datasource.url=jdbc:mysql://localhost:3306/order
###
cd ..
bash 复制代码
kubectl create cm my-config --from-file=conf

4.2、通过 YAML 文件创建

configmap.yaml

javascript 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  username: "admin"
  password: "123456"
  application.yaml: |
    server:
      port: 8080
  db.properties: |
    datasource.username=root
    datasource.password=123456

| 表示下面的内容为多行。

bash 复制代码
kubectl apply -f configmap.yaml

五、在 Pod 中使用 ConfigMap

ConfigMap 可通过 环境变量Volume 挂载注入到容器中。

我们以 4.2 节创建的 my-config 为例,来讲解如何在 Pod 中使用 ConfigMap。

5.1、作为环境变量注入 env

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: envcm-pod
spec:
  restartPolicy: Never
  containers:
  - name: envcm-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["sleep", "3600"]
    env:
    - name: USERNAME # 定义容器中的环境变量
      valueFrom:
        configMapKeyRef:
          name: my-config # ConfigMap 的名字
          key: username # ConfigMap 中的 key 
    - name: PASSWORD
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: password 
  • 像 Alpine 镜像,或者基于 Alpine 制作的工具镜像,容器内没有运行服务,需要启动后休眠一段时间,防止容器被 K8S 杀掉。
  • restartPolicy: Never 休眠结束后容器退出就退出了,不需要 K8S 重启该容器。默认是 Always 总是重启。设为 Never 防止浪费系统资源。
  • 进入容器查看环境变量
bash 复制代码
kubectl exec -it envcm-pod -- /bin/sh
/# env
USERNAME=admin
PASSWORD=123456

5.2、作为环境变量注入 envFrom

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: envfrom-pod
spec:
  restartPolicy: Never
  containers:
  - name: envcm-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["sleep", "3600"]
    envFrom:
    - configMapRef:
        name: my-config

以整个 ConfigMap 作为环境变量数据源。

  • 进入容器查看环境变量
bash 复制代码
kubectl exec -it envfrom-pod -- /bin/sh
/ # env

5.3、环境变量方式使用的 ConfigMap 数据不会被自动更新

以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要重新启动 Pod。

bash 复制代码
# 编辑 ConfigMap
kubectl edit cm my-config
# 把 password 从 123456 -> 456789
# 像 vim 一样 wq 保存退出
  • 进入容器查看环境变量
bash 复制代码
kubectl exec -it envcm-pod -- /bin/sh
/# env
USERNAME=admin
# 还是 123456
PASSWORD=123456 

kubectl exec -it envfrom-pod -- /bin/sh
# 还是 123456
password=123456

5.4、通过 Volume 挂载为文件

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: volumes-pod
spec:
  restartPolicy: Never
  volumes:
  - name: volumes-name # 卷的名字
    configMap:
      name: my-config # ConfigMap 的名字
  containers:
  - name: volumes-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["sleep", "3600"]
    volumeMounts:
    - name: volumes-name
      mountPath: /data/conf # 挂载到容器哪个目录
  • 进入容器查看文件
bash 复制代码
kubectl exec -it volumes-pod -- /bin/sh

以 Volume 形式挂载 ConfigMap,ConfigMap 每一个 key 都会生成一个文件。

  • 进入容器查看环境变量
bash 复制代码
kubectl exec -it volumes-pod -- /bin/sh
/# env
环境变量中不会有配置信息

5.5、热加载

bash 复制代码
# 编辑 ConfigMap
kubectl edit cm my-config
# 把 password 从 456789 -> 111111
# 像 vim 一样 wq 保存退出
  • 进入容器查看文件
bash 复制代码
kubectl exec -it volumes-pod -- /bin/sh

容器内文件的值被更新了。但是会有一定的延迟。具体延迟多少,官方介绍取决于高速缓存类型。

5.6、items 选取 key

我们知道,以 Volume 形式挂载 ConfigMap,ConfigMap 的每一个 key 都会生成一个文件。

对于 4.2 的 ConfigMap:

javascript 复制代码
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config
data:
  username: "admin"
  password: "123456"
  application.yaml: |
    server:
      port: 8080
  db.properties: |
    datasource.username=root
    datasource.password=123456

会生成 username、password、application.yaml、db.properties 这四个文件。

那么,如果我们希望普通的属性,像 username、password 注入到环境变量,而 application.yaml、db.properties 这种,生成文件,要怎么做呢?

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: volumes-items-pod
spec:
  restartPolicy: Never
  volumes:
  - name: volumes-name # 卷的名字
    configMap:
      name: my-config # ConfigMap 的名字
      items:
      - key: "application.yaml" # ConfigMap 的 key
        path: "application.yaml" # key 映射成的文件
      - key: "db.properties"
        path: "db.properties" 
  containers:
  - name: volumes-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["sleep", "3600"]
    env:
    - name: USERNAME # 定义容器中的环境变量
      valueFrom:
        configMapKeyRef:
          name: my-config # ConfigMap 的名字
          key: username # ConfigMap 中的 key 
    - name: PASSWORD
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: password 
    volumeMounts:
    - name: volumes-name
      mountPath: /data/conf

通过 .volumes.configMap.items 选取需要做成卷的 ConfigMap key-value。

bash 复制代码
kubectl exec -it volumes-items-pod -c volumes-pod -- /bin/sh
/ # env
USERNAME=admin
PASSWORD=111111

5.7、名称空间限定

ConfigMap 是一种名称空间限定的资源。某一名称空间下的 Pod,只能引用同一名称空间下的 ConfigMap。

对于 4.2 的 ConfigMap,我们没有写,就是默认 default 名称空间下。现在我们 dev 名称空间下的一个 Pod:

javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: cmns-pod
  namespace: dev
spec:
  restartPolicy: Never
  containers:
  - name: cmns-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["sleep", "3600"]
    env:
    - name: USERNAME # 定义容器中的环境变量
      valueFrom:
        configMapKeyRef:
          name: my-config # ConfigMap 的名字
          key: username # ConfigMap 中的 key 
    - name: PASSWORD
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: password

容器会报 CreateContainerConfigError 起不来。

5.8、多环境配置

ConfigMap 是名称空间限定的资源,所以在多名称空间环境下(比如 dev、prod),我们可以给每个名称空间创建同名的配置,然后在不同名称空间下的 Pod 引用这些配置。

javascript 复制代码
# 创建名称空间
kubectl create ns dev
kubectl create ns prod
# 创建 ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: dev
data:
  username: "dev"
  password: "123456"
###
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
  namespace: prod
data:
  username: "prod"
  password: "123456"
  • dev 下启动 Pod:
javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: cmns-pod
  namespace: dev
spec:
  restartPolicy: Never
  containers:
  - name: cmns-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["env"]
    env:
    - name: USERNAME # 定义容器中的环境变量
      valueFrom:
        configMapKeyRef:
          name: app-config # ConfigMap 的名字
          key: username # ConfigMap 中的 key 
    - name: PASSWORD
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: password 
  • prod 下启动 Pod:
javascript 复制代码
apiVersion: v1
kind: Pod
metadata:
  name: cmns-pod
  namespace: prod
spec:
  restartPolicy: Never
  containers:
  - name: cmns-pod
    image: alpine:latest  
    imagePullPolicy: IfNotPresent
    command: ["env"]
    env:
    - name: USERNAME # 定义容器中的环境变量
      valueFrom:
        configMapKeyRef:
          name: app-config # ConfigMap 的名字
          key: username # ConfigMap 中的 key 
    - name: PASSWORD
      valueFrom:
        configMapKeyRef:
          name: app-config
          key: password 

六、Java 项目使用 ConfigMap 热加载配置

到此,我们知道了 ConfigMap 如果作为 Spring Boot 项目的配置的话,存在一些不足:

1、时效性不高。ConfigMap 可以作为配置文件挂载进容器文件系统,但是这中间会有一些延迟。而且,Spring Boot 项目在启动的时候加载了一次 application.yml 之类的配置文件后,就不会再加载了。这个时候 ConfigMap 再更新配置文件其实没什么意义。

2、时效性更好的环境变量的方式,ConfigMap 却无法更新。

所以,Spring Boot 项目需要自己监听 ConfigMap 变化,然后更新 Environment。

相关推荐
研究司马懿21 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
Harvey9031 天前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
logocode_li3 天前
OCI/CRI 双标准下:从 dockerd 到 containerd 的 K8s 运行时迭代史
docker·云原生·容器·k8s
人间打气筒(Ada)3 天前
k8s:CNI网络插件flannel与calico
linux·云原生·容器·kubernetes·云计算·k8s
回忆是昨天里的海5 天前
k8s整体架构及核心组件
架构·k8s
没有bug.的程序员5 天前
Docker 与 K8s 生产级实战:从镜像极致优化到集群自动化部署全流程
spring cloud·docker·kubernetes·自动化·k8s·镜像·集群自动化
骂我的人都死了6 天前
DevOps架构部署
运维·ubuntu·docker·k8s·github·devops·python3.11
青衫客366 天前
从 TLS 到 Kubernetes PKI:一条证书链如何支撑整个集群安全(问题合集)
容器·kubernetes·k8s·tls
小白不想白a10 天前
pod调度--预选阶段(重点说容忍)
k8s·运维开发
_运维那些事儿12 天前
GitLabCI-CD入门
运维·ci/cd·容器·云计算·k8s·运维开发