ConfigMap
ConfigMap 是一个 API 对象,用于以键值对的形式存储非机密数据。 Pod 可以将 ConfigMap 用作环境变量、命令行参数或 卷中的配置文件。
ConfigMap 允许您将特定于环境的配置与您的容器镜像解耦,从而使您的应用程序易于移植。
注意
ConfigMap 不提供保密性或加密。 如果您要存储的数据是机密的,请使用Secret而不是 ConfigMap,或者使用其他(第三方)工具来保护您的数据隐私。动机
使用 ConfigMap 将配置数据与应用程序代码分开设置。
例如,假设您正在开发一个可以在您自己的计算机上(用于开发)和在云中(用于处理实际流量)运行的应用程序。 您编写代码以查找名为DATABASE_HOST
的环境变量。 在本地,您将该变量设置为localhost
。 在云中,您将其设置为引用 Kubernetes Service,该服务将数据库组件暴露给您的集群。 这使您可以获取在云中运行的容器镜像,并在需要时在本地调试完全相同的代码。
注意
ConfigMap 不适用于保存大量数据。 ConfigMap 中存储的数据不能超过 1 MiB。 如果您需要存储大于此限制的设置,则可以考虑挂载卷或使用单独的数据库或文件服务。ConfigMap 对象
ConfigMap 是一个API 对象,可让您存储供其他对象使用的配置。 与大多数具有spec
的 Kubernetes 对象不同,ConfigMap 具有data
和binaryData
字段。 这些字段接受键值对作为其值。 data
字段和binaryData
都是可选的。 data
字段旨在包含 UTF-8 字符串,而binaryData
字段旨在包含 base64 编码的二进制数据。
ConfigMap 的名称必须是有效的DNS 子域名。
data
或binaryData
字段下的每个键必须由字母数字字符、-
、_
或.
组成。 data
中存储的键不得与binaryData
字段中的键重叠。
从 v1.19 开始,您可以向 ConfigMap 定义添加一个immutable
字段以创建一个不可变的 ConfigMap。
ConfigMap 和 Pod
您可以编写一个 Pod spec
,该规范引用 ConfigMap,并根据 ConfigMap 中的数据配置该 Pod 中的容器。Pod 和 ConfigMap 必须在同一个命名空间中。
这是一个 ConfigMap 的示例,其中包含一些具有单个值的键,以及其他值看起来像配置格式片段的键。
apiVersion: v1
kind: ConfigMap
metadata:
name: game-demo
data:
# property-like keys; each key maps to a simple value
player_initial_lives: "3"
ui_properties_file_name: "user-interface.properties"
# file-like keys
game.properties: |
enemy.types=aliens,monsters
player.maximum-lives=5
user-interface.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
您可以使用四种不同的方式使用 ConfigMap 来配置 Pod 内的容器
- 在容器命令和参数中
- 容器的环境变量
- 添加只读卷中的文件,供应用程序读取
- 编写在 Pod 中运行的代码,该代码使用 Kubernetes API 读取 ConfigMap
这些不同的方法适用于不同方式的数据建模。 对于前三种方法,kubelet在为 Pod 启动容器时使用 ConfigMap 中的数据。
第四种方法意味着您必须编写代码来读取 ConfigMap 及其数据。 但是,由于您直接使用 Kubernetes API,因此您的应用程序可以订阅以在 ConfigMap 发生更改时获取更新,并在发生这种情况时做出反应。 通过直接访问 Kubernetes API,此技术还允许您访问不同命名空间中的 ConfigMap。
这是一个使用game-demo
中的值来配置 Pod 的示例 Pod
apiVersion: v1
kind: Pod
metadata:
name: configmap-demo-pod
spec:
containers:
- name: demo
image: alpine
command: ["sleep", "3600"]
env:
# Define the environment variable
- name: PLAYER_INITIAL_LIVES # Notice that the case is different here
# from the key name in the ConfigMap.
valueFrom:
configMapKeyRef:
name: game-demo # The ConfigMap this value comes from.
key: player_initial_lives # The key to fetch.
- name: UI_PROPERTIES_FILE_NAME
valueFrom:
configMapKeyRef:
name: game-demo
key: ui_properties_file_name
volumeMounts:
- name: config
mountPath: "/config"
readOnly: true
volumes:
# You set volumes at the Pod level, then mount them into containers inside that Pod
- name: config
configMap:
# Provide the name of the ConfigMap you want to mount.
name: game-demo
# An array of keys from the ConfigMap to create as files
items:
- key: "game.properties"
path: "game.properties"
- key: "user-interface.properties"
path: "user-interface.properties"
ConfigMap 不区分单行属性值和多行文件式值。重要的是 Pod 和其他对象如何使用这些值。
在本例中,定义一个卷并将其作为 /config
挂载到 demo
容器内部会创建两个文件,/config/game.properties
和 /config/user-interface.properties
,即使 ConfigMap 中有四个键。这是因为 Pod 定义在 volumes
部分指定了一个 items
数组。如果完全省略 items
数组,则 ConfigMap 中的每个键都会成为一个与键同名的文件,您将得到 4 个文件。
使用 ConfigMap
ConfigMap 可以作为数据卷挂载。ConfigMap 也可以被系统的其他部分使用,而无需直接暴露给 Pod。例如,ConfigMap 可以保存系统的其他部分应该用于配置的数据。
使用 ConfigMap 的最常见方式是配置在同一命名空间中的 Pod 中运行的容器的设置。您也可以单独使用 ConfigMap。
例如,您可能会遇到 插件 或 操作器,它们会根据 ConfigMap 调整其行为。
在 Pod 中将 ConfigMap 用作文件
要在 Pod 中的卷中使用 ConfigMap:
- 创建 ConfigMap 或使用现有的 ConfigMap。多个 Pod 可以引用同一个 ConfigMap。
- 修改您的 Pod 定义,在
.spec.volumes[]
下添加一个卷。为该卷命名,并将.spec.volumes[].configMap.name
字段设置为引用您的 ConfigMap 对象。 - 向每个需要 ConfigMap 的容器添加一个
.spec.containers[].volumeMounts[]
。指定.spec.containers[].volumeMounts[].readOnly = true
和.spec.containers[].volumeMounts[].mountPath
,指向您希望 ConfigMap 出现的未使用目录名称。 - 修改您的镜像或命令行,以便程序在该目录中查找文件。ConfigMap
data
映射中的每个键都将成为mountPath
下的文件名。
这是一个在卷中挂载 ConfigMap 的 Pod 示例
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
configMap:
name: myconfigmap
您要使用的每个 ConfigMap 都需要在 .spec.volumes
中引用。
如果 Pod 中有多个容器,则每个容器都需要自己的 volumeMounts
块,但每个 ConfigMap 只需要一个 .spec.volumes
。
挂载的 ConfigMap 会自动更新
当卷中当前使用的 ConfigMap 更新时,投影的键最终也会更新。kubelet 会在每次定期同步时检查挂载的 ConfigMap 是否是最新的。但是,kubelet 使用其本地缓存来获取 ConfigMap 的当前值。缓存的类型可以使用 KubeletConfiguration 结构 中的 configMapAndSecretChangeDetectionStrategy
字段进行配置。ConfigMap 可以通过监视(默认)、基于 TTL 或将所有请求直接重定向到 API 服务器来传播。因此,从 ConfigMap 更新到新键投影到 Pod 的总延迟可能长达 kubelet 同步周期 + 缓存传播延迟,其中缓存传播延迟取决于选择的缓存类型(它分别等于监视传播延迟、缓存的 TTL 或零)。
作为环境变量使用的 ConfigMap 不会自动更新,需要重启 Pod。
注意
使用 ConfigMap 作为 子路径 卷挂载的容器将不会收到 ConfigMap 更新。将 ConfigMap 用作环境变量
要在 Pod 中的 环境变量 中使用 ConfigMap:
- 对于 Pod 规范中的每个容器,为要使用的每个 ConfigMap 键向
env[].valueFrom.configMapKeyRef
字段添加一个环境变量。 - 修改您的镜像和/或命令行,以便程序在指定的环境变量中查找值。
这是一个将 ConfigMap 定义为 Pod 环境变量的示例
以下 ConfigMap (myconfigmap.yaml) 存储两个属性:username 和 access_level
apiVersion: v1
kind: ConfigMap
metadata:
name: myconfigmap
data:
username: k8s-admin
access_level: "1"
以下命令将创建 ConfigMap 对象
kubectl apply -f myconfigmap.yaml
以下 Pod 将 ConfigMap 的内容作为环境变量使用
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: app
command: ["/bin/sh", "-c", "printenv"]
image: busybox:latest
envFrom:
- configMapRef:
name: myconfigmap
envFrom
字段指示 Kubernetes 从其中嵌套的源创建环境变量。内部的 configMapRef
通过名称引用 ConfigMap 并选择其所有键值对。将 Pod 添加到您的集群,然后检索其日志以查看 printenv 命令的输出。这应确认 ConfigMap 中的两个键值对已设置为环境变量
kubectl apply -f env-configmap.yaml
kubectl logs pod/ env-configmap
输出类似于此
...
username: "k8s-admin"
access_level: "1"
...
有时,Pod 不需要访问 ConfigMap 中的所有值。例如,您可能还有另一个 Pod,它仅使用 ConfigMap 中的 username 值。对于此用例,您可以使用 env.valueFrom
语法,它可以让您选择 ConfigMap 中的单个键。环境变量的名称也可以与 ConfigMap 中的键不同。例如
apiVersion: v1
kind: Pod
metadata:
name: env-configmap
spec:
containers:
- name: envars-test-container
image: nginx
env:
- name: CONFIGMAP_USERNAME
valueFrom:
configMapKeyRef:
name: myconfigmap
key: username
在从此清单创建的 Pod 中,您将看到环境变量 CONFIGMAP_USERNAME
设置为 ConfigMap 中 username
的值。ConfigMap 数据中的其他键不会复制到环境中。
请务必注意,Pod 中环境变量名称允许的字符范围是受限的。如果任何键不符合规则,则这些键将无法用于您的容器,尽管允许 Pod 启动。
不可变 ConfigMap
Kubernetes v1.21 [稳定]
Kubernetes 功能 _不可变 Secret 和 ConfigMap_ 提供了一个选项,可以将单个 Secret 和 ConfigMap 设置为不可变。对于大量使用 ConfigMap 的集群(至少有数万个唯一的 ConfigMap 到 Pod 的挂载),防止更改其数据具有以下优点
- 保护您免受可能导致应用程序中断的意外(或不需要的)更新的影响
- 通过关闭标记为不可变的 ConfigMap 的监视,显著降低 kube-apiserver 的负载,从而提高集群的性能。
您可以通过将 immutable
字段设置为 true
来创建不可变的 ConfigMap。例如
apiVersion: v1
kind: ConfigMap
metadata:
...
data:
...
immutable: true
一旦 ConfigMap 被标记为不可变,就 _无法_ 撤销此更改,也无法更改 data
或 binaryData
字段的内容。您只能删除并重新创建 ConfigMap。由于现有 Pod 维护到已删除 ConfigMap 的挂载点,因此建议重新创建这些 Pod。
下一步
- 阅读有关Secret的内容。
- 阅读配置 Pod 以使用 ConfigMap。
- 阅读有关更改 ConfigMap(或任何其他 Kubernetes 对象)的内容
- 阅读The Twelve-Factor App,了解将代码与配置分离的动机。