配置图
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
您可以编写一个引用 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。
下面是一个 Pod 示例,它使用 game-demo
中的值来配置 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 调整其行为的 插件 或 运算符。
将 ConfigMap 用作 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
。
挂载的 ConfigMap 会自动更新
当当前在卷中使用的 ConfigMap 更新时,投影键最终也会更新。kubelet 在每次定期同步时都会检查挂载的 ConfigMap 是否是最新的。但是,kubelet 使用其本地缓存来获取 ConfigMap 的当前值。可以使用 KubeletConfiguration 结构 中的 configMapAndSecretChangeDetectionStrategy
字段配置缓存类型。可以通过 watch(默认)、基于 ttl 或通过将所有请求直接重定向到 API 服务器来传播 ConfigMap。因此,从 ConfigMap 更新到新键投影到 Pod 的总延迟时间可能长达 kubelet 同步周期 + 缓存传播延迟,其中缓存传播延迟取决于所选的缓存类型(它等于 watch 传播延迟、缓存的 ttl 或零)。
作为环境变量使用的 ConfigMap 不会自动更新,需要重新启动 Pod。
注意
使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 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 对象) 的信息
- 阅读 十二要素应用 以了解将代码与配置分离的原因。