本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。
使用容器进行配置管理
编者按:这是我们关于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旨在仅保存配置信息而非二进制文件,因此值以字符串形式存储,因此在序列化形式中是可读的。
我们希望创建ConfigMaps能够像在其中存储数据一样灵活。为了创建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
使用ConfigMaps很简单,对于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和配置感兴趣,您会想要参与
- 我们的配置Slack频道
- 我们的Kubernetes配置特别兴趣小组电子邮件列表
- 配置“特别兴趣小组”,该小组每周三太平洋时间上午10点(10时00分)在SIG-Config视频群聊举行会议
当然,有关该项目的更多信息,请访问www.kubernetes.io并在Twitter上关注我们@Kubernetesio。