配置图

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

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

动机

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

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

ConfigMap 对象

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

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

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

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

  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

挂载的 ConfigMap 会自动更新

当当前在卷中使用的 ConfigMap 更新时,投影键最终也会更新。kubelet 在每次定期同步时都会检查挂载的 ConfigMap 是否是最新的。但是,kubelet 使用其本地缓存来获取 ConfigMap 的当前值。可以使用 KubeletConfiguration 结构 中的 configMapAndSecretChangeDetectionStrategy 字段配置缓存类型。可以通过 watch(默认)、基于 ttl 或通过将所有请求直接重定向到 API 服务器来传播 ConfigMap。因此,从 ConfigMap 更新到新键投影到 Pod 的总延迟时间可能长达 kubelet 同步周期 + 缓存传播延迟,其中缓存传播延迟取决于所选的缓存类型(它等于 watch 传播延迟、缓存的 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:删除无用的换行符 (7eb2db584e)