配置映射

ConfigMap 是一个 API 对象,用于以键值对的形式存储非机密数据。 Pods 可以将 ConfigMaps 作为环境变量、命令行参数或 中的配置文件使用。

ConfigMap 允许您将特定于环境的配置与 容器镜像 解耦,以便您的应用程序易于移植。

动机

使用 ConfigMap 将配置数据与应用程序代码分开。

例如,假设您正在开发一个可以在您自己的计算机上(用于开发)和云中(用于处理真实流量)运行的应用程序。您编写代码在名为 DATABASE_HOST 的环境变量中查找。在本地,您将该变量设置为 localhost。在云中,您将其设置为引用 Kubernetes 服务,该服务将数据库组件公开到您的集群。这使您能够在云中获取正在运行的容器镜像,并在需要时在本地调试完全相同的代码。

ConfigMap 对象

ConfigMap 是一个 API 对象,它允许您存储其他对象可使用的配置。与大多数具有 spec 的 Kubernetes 对象不同,ConfigMap 具有 databinaryData 字段。这些字段接受键值对作为其值。data 字段和 binaryData 字段都是可选的。data 字段旨在包含 UTF-8 字符串,而 binaryData 字段旨在包含以 base64 编码的字符串形式的二进制数据。

ConfigMap 的名称必须是有效的 DNS 子域名称

databinaryData 字段下的每个键必须由字母数字字符、-_. 组成。存储在 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 内的容器

  1. 在容器命令和参数中
  2. 容器的环境变量
  3. 添加只读卷中的文件,供应用程序读取
  4. 编写在 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

  1. 创建 ConfigMap 或使用现有的 ConfigMap。多个 Pod 可以引用同一个 ConfigMap。
  2. 修改您的 Pod 定义以在 .spec.volumes[] 下添加一个卷。为卷命名任何名称,并设置一个 .spec.volumes[].configMap.name 字段以引用您的 ConfigMap 对象。
  3. 为每个需要 ConfigMap 的容器添加一个 .spec.containers[].volumeMounts[]。指定 .spec.containers[].volumeMounts[].readOnly = true.spec.containers[].volumeMounts[].mountPath 到您希望 ConfigMap 出现的位置的未使用目录名称。
  4. 修改您的镜像或命令行,以便程序在该目录中查找文件。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 作为环境变量

在 Pod 中使用 环境变量 中使用 ConfigMap

  1. 在您的 Pod 规范中,为每个容器添加一个环境变量,对应于您想要使用的每个 ConfigMap 密钥,并将它们添加到 env[].valueFrom.configMapKeyRef 字段。
  2. 修改您的镜像和/或命令行,以便程序在指定的環境變數中查找值。

这是一个将 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 被标记为不可变,就无法撤消此更改,也无法修改 databinaryData 字段的内容。您只能删除和重新创建 ConfigMap。由于现有的 Pod 保持到已删除的 ConfigMap 的挂载点,建议重新创建这些 Pod。

下一步

上次修改时间:2024 年 3 月 26 日下午 11:15 PST:删除无用的换行符 (7eb2db584e)