这篇文章已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已不再准确。

使用容器进行配置管理

编者按:这是我们一系列深入文章中的第七篇,探讨 Kubernetes 1.2 中的新特性

编写应用时的一个良好实践是将应用代码与配置分开。我们希望让应用作者能够轻松地在 Kubernetes 中采用这种模式。虽然 Secrets API 允许将凭证和密钥等信息与应用分开,但过去没有针对普通非敏感配置的对象。在Kubernetes 1.2 中,我们新增了一个名为 ConfigMap 的 API 资源来处理这类配置数据。

ConfigMap 的基础

ConfigMap API 在概念上很简单。从数据角度来看,ConfigMap 类型只是一组键值对。应用有不同的配置方式,因此我们需要灵活处理如何让用户存储和消费配置数据。在 Pod 中消费 ConfigMap 有三种方式:

  • 命令行参数
  • 环境变量
  • 卷中的文件

这些不同的方法适合不同的数据消费建模方式。为了尽可能灵活,我们设计 ConfigMap 可以容纳细粒度或粗粒度的数据,或两者皆有。此外,由于应用可以从环境变量和包含配置数据的文件中读取配置设置,我们构建了 ConfigMap 以支持这两种访问方式。让我们看一个包含这两种配置类型的 ConfigMap 示例:

apiVersion: v1

kind: ConfigMap

metadata:

  Name: example-configmap

data:

  # property-like keys

  game-properties-file-name: game.properties

  ui-properties-file-name: ui.properties

  # file-like keys

  game.properties: |

    enemies=aliens

    lives=3

    enemies.cheat=true

    enemies.cheat.level=noGoodRotten

    secret.code.passphrase=UUDDLRLRBABAS

    secret.code.allowed=true

    secret.code.lives=30

  ui.properties: |

    color.good=purple

    color.bad=yellow

    allow.textmode=true

    how.nice.to.look=fairlyNice

使用过 Secrets 的用户会发现 ConfigMap 很容易上手 — 它们非常相似。这些 API 的一个主要区别是,Secret 的值存储为字节数组,以支持存储 SSH 密钥等二进制文件。在 JSON 和 YAML 中,字节数组被序列化为 base64 编码的字符串。这意味着通过查看序列化形式不容易知道 Secret 的内容。由于 ConfigMap 仅用于存放配置信息而非二进制文件,其值存储为字符串,因此在序列化形式下是可读的。

我们希望创建 ConfigMap 与在其中存储数据一样灵活。为了创建 ConfigMap 对象,我们添加了一个名为 kubectl create configmap 的 kubectl 命令,它提供了三种指定键值对的不同方式:

  • 指定字面量键和值
  • 指定单个文件
  • 指定目录,为每个文件创建键

这些不同的选项可以在一个命令中组合、匹配和重复使用

    $ kubectl create configmap my-config \

    --from-literal=literal-key=literal-value \

    --from-file=ui.properties \
    --from=file=path/to/config/dir

消费 ConfigMap 很简单,并且对于 Secrets 用户来说也很熟悉。下面是一个 Deployment 示例,它使用上述 ConfigMap 运行一个虚构的游戏服务器:

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

  name: configmap-example-deployment

  labels:

    name: configmap-example-deployment

spec:

  replicas: 1

  selector:

    matchLabels:

      name: configmap-example

  template:

    metadata:

      labels:

        name: configmap-example

    spec:

      containers:

      - name: game-container

        image: imaginarygame

        command: ["game-server", "--config-dir=/etc/game/cfg"]

        env:

        # consume the property-like keys in environment variables

        - name: GAME\_PROPERTIES\_NAME

          valueFrom:

            configMapKeyRef:

              name: example-configmap

              key: game-properties-file-name

        - name: UI\_PROPERTIES\_NAME

          valueFrom:

            configMapKeyRef:

              name: example-configmap

              key: ui-properties-file-name

        volumeMounts:

        - name: config-volume

          mountPath: /etc/game

      volumes:

      # consume the file-like keys of the configmap via volume plugin

      - name: config-volume

        configMap:

          name: example-configmap

          items:

          - key: ui.properties

            path: cfg/ui.properties

         - key: game.properties

           path: cfg/game.properties
      restartPolicy: Never

在上面的示例中,Deployment 通过两种不同的可用机制使用 ConfigMap 的键。ConfigMap 中类似属性的键被用作 Deployment 模板中单个容器的环境变量,而类似文件的键则填充到一个卷中。更多详情,请参阅ConfigMap 文档

我们希望这些基本原语易于使用,并期待看到人们使用 ConfigMap 构建出什么。感谢为该特性提供反馈的社区成员。还要特别感谢 Tamer Tas,他为 ConfigMap 的提案和实现做出了巨大贡献。

如果您对 Kubernetes 和配置感兴趣,可以参与以下活动:

当然,有关该项目的更多信息,请访问 www.kubernetes.io 并在 Twitter 上关注我们 @Kubernetesio