Kubernetes-ConfigMap

1. 简介

ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量命令行参数或者存储卷中的配置文件

ConfigMap 将您的环境配置信息和容器镜像解耦,便于应用配置的修改。

注意:ConfigMap 并不提供保密或者加密功能。 如果你想存储的数据是机密的,请使用 Secret。

ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB。如果你需要保存超出此尺寸限制的数据,你可能希望考虑挂载存储卷 或者使用独立的数据库或者文件服务。

2. 4种创建方式

2.1 通过key-value 创建

$ kubectl create configmap redis-1.conf --from-literal=requirepass=123456 --from-literal=appendonly=yes

创建一个名称为redis-1.conf的cm,且参数信息为

  • requirepass=123456:redis 开启密码认证且密码为123456

  • appendonly=yes:redis 开启aof

2.2 * 通过配置文件创建

--from-file 可以多次使用,挂载进多个文件

$ kubectl create configmap redis-2.conf --from-file=./redis.conf

2.3 通过配置文件的目录创建

$ kubectl create configmap redis-3.conf --from-file=./

2.4 * 直接编写ConfigMap文件

apiVersion: v1
data:
  redis.conf: |
    requirepass 123456
    appendonly yes
kind: ConfigMap
metadata:
  name: redis-4.conf
  namespace: default

ConfigMap 使用 databinaryData 字段。这些字段能够接收键-值对作为其取值。databinaryData 字段都是可选的。data 字段设计用来保存 UTF-8 字节序列,而 binaryData 则 被设计用来保存二进制数据作为 base64 编码的字串。

2.5 小节

以上四种方式都可以创建cm,但是仔细看会发现创建的文件内容其实都不太一样

  • 2.1 创建的cm如果以volume方式挂载到pod中,最终会在pod中生成两个文件 requirepass(内容为123456),appendonly(内容为yes),这种方式即使挂载成功了也不是我们所期望的结果,验证步骤如3.1.1
  • 2.2 创建的cm如果以volume方式挂载到pod中,其效果和2.4一样,最终会生成一个配置文件redis.conf,且文件内容为requirepass 123456 appendonly yes符合所期望的,验证步骤如3.1.2
  • 2.3 则是将制定目录下的文件都囊括到了cm中,将cm挂载到 pod中后,其实和当前的文件夹的内容一致,验证步骤如3.1.3

3. 3种挂载方式

3.1 通过volume方式挂载

3.1.1 挂载2.1中的cm

将2.1中的cm(redis-1.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-1
spec:
  containers:
  - name: redis-1
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    volumeMounts:
    - mountPath: /etc/redis
      name: config
  volumes:
    - name: config
      configMap:
        # 指定cm name
        name: redis-1.conf
        # 如果想挂载特定的key 可以使用以下方式
        #items:
        #  - key: requirepass # data key
        #    path: requirepass.txt # 挂载进pod后的文件名称

3.1.2 挂载2.2中的cm

将2.2中的cm(redis-2.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-2
spec:
  containers:
  - name: redis-2
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    # 指定启动的配置文件
    command:
      - redis-server
      # 指的是redis容器内部的位置
      - "/etc/redis/redis.conf"
    volumeMounts:
    - mountPath: /etc/redis
      name: config
  volumes:
    - name: config
      configMap:
        name: redis-2.conf

3.1.3 挂载2.3中的cm

将2.3中的cm(redis-3.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-3
spec:
  containers:
  - name: redis-3
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    command:
      - redis-server
      - "/etc/redis/redis.conf"
    volumeMounts:
    - mountPath: /etc/redis
      name: config
  volumes:
    - name: config
      configMap:
        name: redis-3.conf

3.1.4 挂载2.4中的cm

将2.4中的cm(redis-4.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-4
spec:
  containers:
  - name: redis-4
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    command:
      - redis-server
      - "/etc/redis/redis.conf"  #指的是redis容器内部的位置
    volumeMounts:
    - mountPath: /etc/redis
      name: config
  volumes:
    - name: config
      configMap:
        name: redis-4.conf

3.2 通过环境变量方式挂载

3.2.1 挂载2.1中的cm

将2.1中的cm(redis-1.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-env-1
spec:
  containers:
  - name: redis-env-1
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    env:
      # 定义环境变量
      - name: REDIS_CONF_PASSWORD # 请注意这里和 ConfigMap 中的键名是不一样的
        valueFrom:
          configMapKeyRef:
            name: redis-1.conf           # 这个值来自 ConfigMap
            key: appendonly # 需要取值的键
      - name: REDIS_CONF_APPENDONLY
        valueFrom:
          configMapKeyRef:
            name: redis-1.conf
            key: requirepass

也可以直接导入ConfigMap中的所有key value

apiVersion: v1
kind: Pod
metadata:
  name: redis-env-1
spec:
  containers:
  - name: redis-env-1
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    envFrom:
    - configMapRef:
        # cm name
        name: redis-1.conf          

3.2.2 挂载2.2中的cm

将2.2中的cm(redis-2.conf)挂载到pod中看下效果

apiVersion: v1
kind: Pod
metadata:
  name: redis-env-2
spec:
  containers:
  - name: redis-env-2
    image: redis
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 6379
    env:
      # 定义环境变量
      - name: REDIS_CONF # 请注意这里和 ConfigMap 中的键名是不一样的
        valueFrom:
          configMapKeyRef:
            name: redis-2.conf           # 这个值来自 ConfigMap
            key: redis.conf # 需要取值的键

从输出内容上看,把文件中的内容转成了一个字符串,所以如果要挂载环境变量的内容,还是使用2.1的cm会更合理点。

3.3 通过命令行参数挂载

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - name: test-pod
      image: busybox
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","--"]
      args:
        # 输出环境变量
        - "echo requirepass':'$requirepass;echo appendonly':'$appendonly"
      envFrom:
        - configMapRef:
            name: redis-1.conf
  restartPolicy: Never

4. subPath

如果我们想挂载配置文件时,只覆盖指定mountPath下的指定文件(因为默认会把ConfigMap中的信息挂载到mountPath下,此时mountPath下只有ConfigMap的配置文件,mountPath下本来有的配置文件会被清除掉),那么需要使用subpath来指定要被覆盖的文件

我在volume的6.0中详细的写了相关的配置,感兴趣的可以了解下。

5. 被挂载的 ConfigMap 内容会被自动更新

当卷中使用的 ConfigMap 被更新时,所投射的键最终也会被更新。 kubelet 组件会在每次周期性同步时检查所挂载的 ConfigMap 是否为最新。 不过,kubelet 使用的是其本地的高速缓存来获得 ConfigMap 的当前值。 高速缓存的类型可以通过 KubeletConfiguration 结构 的 ConfigMapAndSecretChangeDetectionStrategy 字段来配置。

ConfigMap 既可以通过 watch 操作实现内容传播(默认形式),也可实现基于 TTL 的缓存,还可以直接经过所有请求重定向到 API 服务器。 因此,从 ConfigMap 被更新的那一刻算起,到新的主键被投射到 Pod 中去,这一 时间跨度可能与 kubelet 的同步周期加上高速缓存的传播延迟相等。 这里的传播延迟取决于所选的高速缓存类型 (分别对应 watch 操作的传播延迟、高速缓存的 TTL 时长或者 0)。

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

6. 不可变更的 ConfigMap

从 v1.19 开始,你可以添加一个 immutable 字段到 ConfigMap 定义中,创建 不可变更的 ConfigMap

Kubernetes 特性 不可变更的 Secret 和 ConfigMap 提供了一种将各个 Secret 和 ConfigMap 设置为不可变更的选项。对于大量使用 ConfigMap 的 集群(至少有数万个各不相同的 ConfigMap 给 Pod 挂载)而言,禁止更改 ConfigMap 的数据有以下好处:

  • 保护应用,使之免受意外(不想要的)更新所带来的负面影响。
  • 通过大幅降低对 kube-apiserver 的压力提升集群性能,这是因为系统会关闭 对已标记为不可变更的 ConfigMap 的监视操作。

你可以通过将 immutable 字段设置为 true 创建不可变更的 ConfigMap。 例如:

apiVersion: v1
kind: ConfigMap
metadata:
  ...
data:
  ...
immutable: true

一旦某 ConfigMap 被标记为不可变更,则 无法 逆转这一变化,,也无法更改 databinaryData 字段的内容。你只能删除并重建 ConfigMap。 因为现有的 Pod 会维护一个对已删除的 ConfigMap 的挂载点,建议重新创建 这些 Pods。

原文链接:,转发请注明来源!