Skip to content

文档,https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap/

1. ConfigMap基本概念

ConfigMap和Secret的本质是volume的一种形式,k8s旨在把一切资源抽象化

1.1 什么是ConfigMap

ConfigMap资源主要为容器注⼊相关的程序配置信息,⽤来定制程序的运⾏⽅式,⽐如Redis监听端⼝、最⼤客户端连接数等等。

当定义好⼀个ConfigMap资源后,如果Pod需要使⽤,可以通过通过环境变量命令行参数存储卷形式将其挂载并加载相关的配置,降低了配置与镜像⽂件的耦合关系。

ConfigMap 对象将配置数据以键值对的形式进行存储,这些数据可以在 Pod 对象中使用或者为系统组件提供配置。

1.2 为什么需要ConfigMap

应用配置信息与程序进行分离,这样可以使得应用程序被更好地复用,通过不同的配置能实现更灵活的功能,例如:在测试环境中Nginx提供test域名访问,且没配置压缩功能,而在生产环境中则需要提供www域名访问,且需要开启压缩功能,所以将应用容器与配置分离,根据不同的环境调用不同的ConfigMap配置,能有效的降低耦合度和复杂度。

image-20240528115757521

1.3 ConfigMap作用

存储不加密数据到etcd,让Pod以变量或者Volume挂载到容器中。

2. 创建ConfigMap

官方文档,https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/

2.0 资源定义规范

bash
#帮助文档
kubectl explain configmap

或者
kubectl create configmap --help
#帮助文档
kubectl explain configmap

或者
kubectl create configmap --help

2.1 基于命令创建CM

bash
[root@kube-master ~]# kubectl create configmap nginx-command-config --from-literal=ngx.host='0.0.0.θ' --from-literal=nginx.port='8899'
configmap/nginx-command-config created

#查看
[root@kube-master ~]# kubectl get configmaps
NAME                   DATA   AGE
nginx-command-config   2      24s

#查看内容
[root@kube-master ~]# kubectl get configmaps nginx-command-config -oyaml
apiVersion: v1
data:
  nginx.port: "8899"
  ngx.host: 0.0.0.θ
kind: ConfigMap
metadata:
  creationTimestamp: "2024-05-28T06:55:36Z"
  name: nginx-command-config
  namespace: default
  resourceVersion: "1578412"
  uid: a94ec46f-3b93-4600-80f9-fa467a5eb6cd
[root@kube-master ~]# kubectl create configmap nginx-command-config --from-literal=ngx.host='0.0.0.θ' --from-literal=nginx.port='8899'
configmap/nginx-command-config created

#查看
[root@kube-master ~]# kubectl get configmaps
NAME                   DATA   AGE
nginx-command-config   2      24s

#查看内容
[root@kube-master ~]# kubectl get configmaps nginx-command-config -oyaml
apiVersion: v1
data:
  nginx.port: "8899"
  ngx.host: 0.0.0.θ
kind: ConfigMap
metadata:
  creationTimestamp: "2024-05-28T06:55:36Z"
  name: nginx-command-config
  namespace: default
  resourceVersion: "1578412"
  uid: a94ec46f-3b93-4600-80f9-fa467a5eb6cd

💡 说明

ConfigMap资源没有有sepc和status,而是直接使用data字段嵌套键值数据

2.2 基于文件创建(生产推荐)

为 "kubeclt create configmap" 命令使用 "--from-file" 选项即可基于文件内容来创建 ConfigMap 对象,可以重复多次使用 "--from-file" 选项以传递多个文件内容,它的命令格式如下:

bash
Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none] [options]
Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none] [options]
bash
#事先准备好的 Nginx 配置文件模板保存于 ConfigMap 对象 nginx-config
kubectl create configmap nginx-config \
--from-file=/data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=/data/configs/nginx/conf.d/www.bbb.com.conf
#事先准备好的 Nginx 配置文件模板保存于 ConfigMap 对象 nginx-config
kubectl create configmap nginx-config \
--from-file=/data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=/data/configs/nginx/conf.d/www.bbb.com.conf

如果需要自行指定键名,则可在 "--from-file" 选项中直接指定自定义的键,命令格式如下:

bash
kubectl create configmap nginx-config \
--from-file=aaa=/data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=bbb=/data/configs/nginx/conf.d/www.bbb.com.conf
kubectl create configmap nginx-config \
--from-file=aaa=/data/configs/nginx/conf.d/www.aaa.com.conf \
--from-file=bbb=/data/configs/nginx/conf.d/www.bbb.com.conf

2.3 基于目录

如果配置文件数量较多且存储于有限的目录中时,kubeclt 还提供了基于目录直接将多个文件分别纳为键值数据的 ConfigMap 资源创建方式。将 "--from-file" 选项后面所跟的路径指向一个目录路径就能将目录下的所有创建于同一 ConfigMap 资源中,命令格式如下:

bash
Usage:
  kubectl create configmap <configmap_nam>[--from-file=<path-to-directory>]
Usage:
  kubectl create configmap <configmap_nam>[--from-file=<path-to-directory>]
bash
kubect  create configmap nginx-config-file --from-file=/data/confnigs/nginx/conf.d/
kubect  create configmap nginx-config-file --from-file=/data/confnigs/nginx/conf.d/

2.4 使用资源清单创建

基于配置文件创建 ConfigMap 资源时,它所使用的字段包括通常的 apiVersion、kind 和 metadata 字段,以及用于存储数据的关键字段 "data"

yaml
[root@kube-master ~]# cat configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: demoapp-config
data:
  host: 0.0.0.0
  port: "8888"
  my-server.conf: |
    server {
      listen 80;
      server_name go.ikubernetes.net;

     location / {
      root /usr/share/nginx/html;
      index index.html;
    }
    include /etc/nginx/conf.d/*.cfg;
    }
[root@kube-master ~]# cat configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: demoapp-config
data:
  host: 0.0.0.0
  port: "8888"
  my-server.conf: |
    server {
      listen 80;
      server_name go.ikubernetes.net;

     location / {
      root /usr/share/nginx/html;
      index index.html;
    }
    include /etc/nginx/conf.d/*.cfg;
    }

2.5 更新

edit

bash
#查看configmap
kubectl get cm

#修改
kubectl edit cm demoapp-config
#查看configmap
kubectl get cm

#修改
kubectl edit cm demoapp-config

replace

bash
#先把yaml 文件备份出来
kubectl get cm demoapp-config -oyaml > test.yaml

#替换
[root@kube-master ~]# kubectl replace cm -f test.yaml
configmap/demoapp-config replaced
#先把yaml 文件备份出来
kubectl get cm demoapp-config -oyaml > test.yaml

#替换
[root@kube-master ~]# kubectl replace cm -f test.yaml
configmap/demoapp-config replaced

3. Pod引⽤ConfigMap

3.1 通过环境变量引⽤CM键值

env引⽤变量

pod清单中除了使⽤vaule字段直接给定变量之外,还支持vaLueFrom字段嵌套configMapKeyRef来引用ConfigMap对象的键值,具体格式如下

yaml
env:
  name: <string> #要赋值的环境变量名称
  valueFrom: #定义变量的引|用
  	configMapkeyRef: # 变量来自于configmap对象
  	   name: <string> #configmap对象的名称(因为有很多configmap,需要指定具体的名称)
  	   key: <string> #configmap的键名称
env:
  name: <string> #要赋值的环境变量名称
  valueFrom: #定义变量的引|用
  	configMapkeyRef: # 变量来自于configmap对象
  	   name: <string> #configmap对象的名称(因为有很多configmap,需要指定具体的名称)
  	   key: <string> #configmap的键名称

💡 说明

这种⽅式赋值环境变量与直接赋值环境变量⽅式并⽆区别,它们都可以⽤于容器的启动脚本或直接传递给容器应⽤等

案例1

demoapp容器⽀持通过环境变量 HOSTPORT 为其指定监听的地址和端⼝

yaml
[root@kube-master configmaps]# cat demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: busybox-httpd-config
data:
  http_port: "8080"
  verbose_level: "-vv"
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
spec:
  containers:
  - name: demo-configmap
    image: registry.cn-zhangjiakou.aliyuncs.com/hsuing/demoapp:v1
    env:
    - name: PORT   # PORT变量名
      valueFrom:
        configMapKeyRef:
          name: busybox-httpd-config	 # 引⽤dbusybox-httpd-config资源中的http_port
          key: http_port
[root@kube-master configmaps]# cat demo.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: busybox-httpd-config
data:
  http_port: "8080"
  verbose_level: "-vv"
---
apiVersion: v1
kind: Pod
metadata:
  name: configmap-env-demo
spec:
  containers:
  - name: demo-configmap
    image: registry.cn-zhangjiakou.aliyuncs.com/hsuing/demoapp:v1
    env:
    - name: PORT   # PORT变量名
      valueFrom:
        configMapKeyRef:
          name: busybox-httpd-config	 # 引⽤dbusybox-httpd-config资源中的http_port
          key: http_port

❌ 注意

在 command 或 args 字段中引用环境变量要使用 "$(VAR_NAME)" 的格式

  • 验证
bash
[root@kube-master configmaps]# kubectl exec  configmap-env-demo -- netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1/python3
[root@kube-master configmaps]# kubectl exec  configmap-env-demo -- netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      1/python3

❌ 注意

被引⽤的ConfigMap资源必须事先存在,否则⽆法在Pod对象中引⽤ConfigMap资源,另外ConfigMap属于名称空间级别的资源,它必须与引⽤它的Pod资源在同⼀名称空间

案例2

yaml
[root@kube-master configmaps]# cat cm-var.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  special.host: 172.168.1.1
  special.type: world
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-cm-pod
spec:
  containers:
  - name: buxybox
    image: busybox:latest
    command: ["sh", "-c", "echo $(SPECIAL_HOST) $(SPECIAL_TYPE)"]
    env:
      - name: SPECIAL_HOST
        valueFrom:
          configMapKeyRef:
            name: my-configmap
            key: special.host
      - name: SPECIAL_TYPE
        valueFrom:
          configMapKeyRef:
            name: my-configmap
            key: special.type
[root@kube-master configmaps]# cat cm-var.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-configmap
data:
  special.host: 172.168.1.1
  special.type: world
---
apiVersion: v1
kind: Pod
metadata:
  name: demo-cm-pod
spec:
  containers:
  - name: buxybox
    image: busybox:latest
    command: ["sh", "-c", "echo $(SPECIAL_HOST) $(SPECIAL_TYPE)"]
    env:
      - name: SPECIAL_HOST
        valueFrom:
          configMapKeyRef:
            name: my-configmap
            key: special.host
      - name: SPECIAL_TYPE
        valueFrom:
          configMapKeyRef:
            name: my-configmap
            key: special.type
  • 验证结果
bash
[root@kube-master configmaps]# kubectl logs  demo-cm-pod
172.168.1.1 world
[root@kube-master configmaps]# kubectl logs  demo-cm-pod
172.168.1.1 world

3.2 通过卷挂载⽅式引⽤CM

帮助

bash
kubectl explain pod.spec.containers.volumeMounts
kubectl explain pod.spec.containers.volumeMounts

引⽤整个存储卷

  • 创建cm
bash
 kubectl create cm nginx-conf --from-file=nginx.conf
 kubectl create cm nginx-conf --from-file=nginx.conf
  • 创建deploy
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-cm-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-cm-app
  template:
    metadata:
      labels:
        app: my-cm-app
    spec:
      volumes:
      - name: my-cm-volume  # name of the volume
        configMap:
          name: nginx-conf  # name of the ConfigMap object
      containers:
      - name: my-cm-container
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: my-cm-volume
          mountPath: /usr/share/nginx/html/ #容器挂载的目录(空的),这个方式会覆盖这个目录下原有的文件
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-cm-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-cm-app
  template:
    metadata:
      labels:
        app: my-cm-app
    spec:
      volumes:
      - name: my-cm-volume  # name of the volume
        configMap:
          name: nginx-conf  # name of the ConfigMap object
      containers:
      - name: my-cm-container
        image: nginx:latest
        ports:
        - containerPort: 80
        volumeMounts:
        - name: my-cm-volume
          mountPath: /usr/share/nginx/html/ #容器挂载的目录(空的),这个方式会覆盖这个目录下原有的文件
  • 执行
bash
[root@kube-master volumeMounts]# kubectl apply -f demo.yaml
deployment.apps/my-cm-deployment created
[root@kube-master volumeMounts]# kubectl apply -f demo.yaml
deployment.apps/my-cm-deployment created
  • 验证效果
bash
[root@kube-master volumeMounts]# kubectl exec -it my-cm-deployment-588bd59774-42wsw -- ls /usr/share/nginx/html/
nginx.conf
[root@kube-master volumeMounts]# kubectl exec -it my-cm-deployment-588bd59774-42wsw -- ls /usr/share/nginx/html/
nginx.conf

引⽤存储卷部分键值(itmes)

configmap基于目录创建的时候可以使用itmes,调用部分值

yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-2
  namespace: default
spec:
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files
      items:
      - key: myserver.conf   # 要引⽤的键名称(必写)
        path: myserver.conf  # 挂载进 pod 后的文件名(必写)
        mode: 0644
      items:
      - key: youserver.conf
        path: youserver.conf
        mode: 0644
  containers:
  - image: nginx:alpine
    name: nginx-server
    volumeMounts:
    - name: ngxconfig
      mountPath: /etc/nginx/conf.d/
      readOnly: true
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-2
  namespace: default
spec:
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files
      items:
      - key: myserver.conf   # 要引⽤的键名称(必写)
        path: myserver.conf  # 挂载进 pod 后的文件名(必写)
        mode: 0644
      items:
      - key: youserver.conf
        path: youserver.conf
        mode: 0644
  containers:
  - image: nginx:alpine
    name: nginx-server
    volumeMounts:
    - name: ngxconfig
      mountPath: /etc/nginx/conf.d/
      readOnly: true

引⽤存储卷单个键值

前⾯两种⽅式中,⽆论是装在ConfigMap对象中的所有⽂件还是部分⽂件,挂载点⽬录下原有的⽂件都会被隐藏

对于期望将 ConfigMap 对象提供的配置文件补充于挂载点目录下,并且不影响原本就存在的一些文件,这种方式就可以满足需求。

使用容器的 volumeMounts 字段中使用的 subPath 字段来解决,它可以支持用户从存储卷挂载单个文件或单个目录而非整个存储卷

yaml
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-3
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
    volumeMounts:
    - name: ngxconfig  #ConfigMap 的 Key 名称
      mountPath: /etc/nginx/conf.d/myserver.conf
      subPath: myserver.conf
      readOnly: true
    - name: ngxconfig   #ConfigMap 的 Key 名称
      mountPath: /etc/nginx/conf.d/yourserver.conf #挂载之后的名字
      subPath: yourserver.conf  #configmaps 中key
      readOnly: true
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files
apiVersion: v1
kind: Pod
metadata:
  name: configmap-volume-demo-3
  namespace: default
spec:
  containers:
  - image: nginx:alpine
    name: nginx-server
    volumeMounts:
    - name: ngxconfig  #ConfigMap 的 Key 名称
      mountPath: /etc/nginx/conf.d/myserver.conf
      subPath: myserver.conf
      readOnly: true
    - name: ngxconfig   #ConfigMap 的 Key 名称
      mountPath: /etc/nginx/conf.d/yourserver.conf #挂载之后的名字
      subPath: yourserver.conf  #configmaps 中key
      readOnly: true
  volumes:
  - name: ngxconfig
    configMap:
      name: nginx-config-files