Kubernetes ConfigMap 配置管理详解
ConfigMap 是 Kubernetes 中一种核心的 API 对象,它允许你以键值对的形式存储非敏感配置数据。这些配置数据可以被 Pod 以多种方式使用,包括作为环境变量、命令行参数,或者挂载到卷中作为配置文件。ConfigMap 的主要目的是将应用程序的配置信息与其容器镜像分离,从而简化配置的更新和管理。
注意: ConfigMap 不提供数据加密或保密功能。对于敏感信息,应使用 Kubernetes Secrets。此外,ConfigMap 不适合存储大量数据,其大小限制为 1 MiB。对于超过此限制的数据,建议考虑使用持久化存储卷或外部服务。
ConfigMap 的四种创建方式
1. 通过键值对创建
可以使用 kubectl create configmap 命令配合 --from-literal 选项直接创建包含键值对的 ConfigMap。
# 示例:创建一个名为 redis-conf 的 ConfigMap,包含两个配置项
$ kubectl create configmap redis-conf --from-literal=maxmemory='256mb' --from-literal=timeout=300
另一种快捷方式是使用 --from-env-file 选项,从一个包含键值对的 `.env` 文件中导入配置。
# 假设存在一个 redis-env 文件,内容为:
# MAXMEMORY=256mb
# TIMEOUT=300
$ kubectl create configmap redis-conf --from-env-file=./redis-env
2. 通过单个配置文件创建
使用 --from-file 选项可以将一个或多个文件的内容直接创建为 ConfigMap。如果挂载该 ConfigMap 为卷,每个文件将成为卷中的一个独立文件。
# 示例:将本地的 redis.conf 文件内容创建为 ConfigMap
$ kubectl create configmap redis-config-file --from-file=./redis.conf
3. 通过配置文件目录创建
使用 --from-file 选项并指定一个目录,可以将该目录下的所有文件都作为 ConfigMap 的一部分。挂载到 Pod 后,这些文件将出现在挂载点。
# 示例:将当前目录下的所有文件创建为 ConfigMap
$ kubectl create configmap redis-config-dir --from-file=.
4. 直接编写 ConfigMap YAML 文件
可以直接定义 ConfigMap 的 YAML 文件,使用 data 字段来存储键值对。对于包含多行配置或二进制数据,可以使用 data 或 binaryData 字段。
apiVersion: v1
kind: ConfigMap
metadata:
name: redis-manual-conf
data:
redis.conf: |
maxmemory 256mb
timeout 300
another-config.txt: |
This is another configuration setting.
data 字段用于存储 UTF-8 编码的文本数据,而 binaryData 字段则用于存储 Base64 编码的二进制数据。
ConfigMap 的三种挂载方式
1. 通过 Volume 挂载
ConfigMap 可以作为 Volume 挂载到 Pod 中,使得 Pod 内的应用程序可以直接访问配置文件。
a. 挂载键值对创建的 ConfigMap (示例 1)
当使用 --from-literal 或 --from-env-file 创建的 ConfigMap 以 Volume 方式挂载时,每个键会成为一个单独的文件。
apiVersion: v1
kind: Pod
metadata:
name: pod-volume-literal
spec:
containers:
- name: app-container
image: redis
volumeMounts:
- name: config-volume
mountPath: /etc/redis/conf
volumes:
- name: config-volume
configMap:
name: redis-conf # 引用前面创建的 redis-conf ConfigMap
访问 /etc/redis/conf 目录会看到 maxmemory 和 timeout 两个文件。
b. 挂载文件创建的 ConfigMap (示例 2 & 4)
当使用 --from-file 或直接 YAML 定义文件内容时,挂载后的文件结构与原始文件一致。
apiVersion: v1
kind: Pod
metadata:
name: pod-volume-file
spec:
containers:
- name: app-container
image: redis
command: ["redis-server", "/etc/redis/redis.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/redis
volumes:
- name: config-volume
configMap:
name: redis-config-file # 引用前面创建的 redis-config-file ConfigMap
在容器中,/etc/redis/redis.conf 文件将包含原始 redis.conf 的内容。
c. 挂载目录创建的 ConfigMap (示例 3)
挂载目录创建的 ConfigMap,会将目录下所有文件都作为卷内容的一部分。
apiVersion: v1
kind: Pod
metadata:
name: pod-volume-dir
spec:
containers:
- name: app-container
image: redis
command: ["redis-server", "/etc/redis/redis.conf"]
volumeMounts:
- name: config-volume
mountPath: /etc/redis
volumes:
- name: config-volume
configMap:
name: redis-config-dir # 引用前面创建的 redis-config-dir ConfigMap
挂载点 /etc/redis 将包含源目录下的所有文件。
2. 通过环境变量挂载
ConfigMap 中的数据可以被注入到容器的环境变量中。
a. 挂载单个键值对
使用 env 字段和 valueFrom.configMapKeyRef 来指定要注入的环境变量名及其对应的 ConfigMap 键。
apiVersion: v1
kind: Pod
metadata:
name: pod-env-single
spec:
containers:
- name: app-container
image: redis
env:
- name: MAX_MEMORY_SETTING
valueFrom:
configMapKeyRef:
name: redis-conf # ConfigMap 名称
key: maxmemory # ConfigMap 中的键
- name: REDIS_TIMEOUT
valueFrom:
configMapKeyRef:
name: redis-conf
key: timeout
b. 挂载整个 ConfigMap
使用 envFrom 字段可以一次性将 ConfigMap 中的所有键值对注入为环境变量。
apiVersion: v1
kind: Pod
metadata:
name: pod-env-all
spec:
containers:
- name: app-container
image: redis
envFrom:
- configMapRef:
name: redis-conf # 引用整个 ConfigMap
注意: 以环境变量方式使用的 ConfigMap 数据在 ConfigMap 更新后不会自动生效,需要重启 Pod。
3. 通过命令行参数挂载
ConfigMap 的数据也可以直接作为容器启动命令的参数。
apiVersion: v1
kind: Pod
metadata:
name: pod-cmd-args
spec:
containers:
- name: busybox-container
image: busybox
command: ["/bin/sh","-c"]
args:
- "echo Redis maxmemory is: $MAX_MEMORY_SETTING; echo Redis timeout is: $REDIS_TIMEOUT"
envFrom: # 通过 envFrom 注入环境变量
- configMapRef:
name: redis-conf
restartPolicy: Never
subPath 配置
当使用 Volume 挂载 ConfigMap 时,默认情况下,挂载点下的所有内容会被 ConfigMap 的内容覆盖。如果只想覆盖挂载点下的特定文件,可以使用 subPath 来指定。
ConfigMap 内容自动更新
通过 Volume 挂载的 ConfigMap,当 ConfigMap 对象本身更新后,挂载到 Pod 中的内容也会在一定延迟后自动更新。Kubelet 会定期检查 ConfigMap 的变化,更新的延迟取决于 Kubelet 的同步周期和缓存策略。
重要提示: 通过环境变量注入的 ConfigMap 数据不会自动更新,需要重启 Pod 才能生效。
不可变更的 ConfigMap
从 Kubernetes v1.19 开始,可以通过在 ConfigMap 定义中添加 immutable: true 字段来创建不可变更的 ConfigMap。
apiVersion: v1
kind: ConfigMap
metadata:
name: immutable-config
data:
config.setting: "value"
immutable: true
一旦 ConfigMap 被标记为不可变更,其内容将无法修改。任何试图修改的操作都将被拒绝,只能通过删除并重新创建 ConfigMap 来实现更新。对于已挂载此类 ConfigMap 的 Pod,通常也需要重新创建以确保它们引用新的 ConfigMap。
不可变更的 ConfigMap 具有以下优势:
- 防止应用因意外的配置更新而受到影响。
- 减少对 Kubernetes API Server 的压力,因为系统不再需要监视这些不可变更对象的变更。