配置映射
ConfigMap 是一个 API 对象,用于以键值对的形式存储非机密数据。 Pods 可以将 ConfigMaps 作为环境变量、命令行参数或 卷 中的配置文件使用。
ConfigMap 允许您将特定于环境的配置与 容器镜像 解耦,以便您的应用程序易于移植。
注意
ConfigMap 不提供机密性或加密。如果您要存储的数据是机密的,请使用 Secret 而不是 ConfigMap,或使用其他(第三方)工具来保护您的数据隐私。动机
使用 ConfigMap 将配置数据与应用程序代码分开。
例如,假设您正在开发一个可以在您自己的计算机上(用于开发)和云中(用于处理真实流量)运行的应用程序。您编写代码在名为 DATABASE_HOST
的环境变量中查找。在本地,您将该变量设置为 localhost
。在云中,您将其设置为引用 Kubernetes 服务,该服务将数据库组件公开到您的集群。这使您能够在云中获取正在运行的容器镜像,并在需要时在本地调试完全相同的代码。
注意
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。
ConfigMaps 和 Pods
您可以编写一个引用 ConfigMap 的 Pod spec
,并根据 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 不会区分单行属性值和多行文件式值。重要的是 Pods 和其他对象如何使用这些值。
对于此示例,定义一个卷并将其作为 /config
挂载到 demo
容器中会创建两个文件:/config/game.properties
和 /config/user-interface.properties
,即使 ConfigMap 中有四个键。这是因为 Pod 定义在 volumes
部分指定了一个 items
数组。如果您完全省略 items
数组,则 ConfigMap 中的每个键都会成为与键同名的文件,您将获得 4 个文件。
使用 ConfigMaps
ConfigMaps 可以作为数据卷挂载。ConfigMaps 也可以由系统的其他部分使用,而无需直接暴露给 Pod。例如,ConfigMaps 可以保存系统其他部分应用于配置的数据。
使用 ConfigMaps 最常见的方式是配置运行在相同命名空间的 Pod 中的容器的设置。您也可以单独使用 ConfigMap。
例如,您可能会遇到 附加组件 或 运算符,它们根据 ConfigMap 调整其行为。
将 ConfigMaps 作为 Pod 中的文件使用
要在 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
。
挂载的 ConfigMaps 会自动更新
当当前在卷中使用的 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 环境变量的示例。
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 中环境变量名称允许的字符范围是 有限的。如果任何键不符合规则,这些键将不会提供给您的容器,尽管 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 对象) 的信息。
- 阅读 十二要素应用 以了解将代码与配置分离的动机。