Kubernetes-配置字典ConfigMap

1、ConfigMap概述

很多生产环境中的应用程序配置较为复杂,可能需要多个config文件、命令行参数和环境变量的组合。使用容器部署时,把配置应该从应用程序镜像中解耦出来,以保证镜像的可移植性。尽管Secret允许类似于验证信息和秘钥等信息从应用中解耦出来,但在K8S1.2前并没有为了普通的或者非secret配置而存在的对象。在K8S1.2后引入ConfigMap来处理这种类型的配置数据。

ConfigMap是存储通用的配置变量的,类似于配置文件,使用户可以将分布式系统中用于不同模块的环境变量统一到一个对象中管理;而它与配置文件的区别在于它是存在集群的“环境”中的,并且支持K8S集群中所有通用的操作调用方式。从数据角度来看,ConfigMap的类型只是键值组,用于存储被Pod或者其他资源对象(如RC)访问的信息。这与secret的设计理念有异曲同工之妙,主要区别在于ConfigMap通常不用于存储敏感信息,而只存储简单的文本信息。

创建pod时,对configmap进行绑定,pod内的应用可以直接引用ConfigMap的配置。相当于configmap为应用/运行环境封装配置。pod使用ConfigMap,通常用于:设置环境变量的值、设置命令行参数、创建配置文件。

Kubernetes是为了解决“如何合理使用容器支撑企业级复杂应用”这个问题而诞生的,所以它的设计理念是要支持绝大多数应用的原生形态。例如,很多应用程序的配置需要通过配置文件,命令行参数和环境变量的组合配置来完成(“十二要素应用”等均要求去配置)。这些配置应该从image内容中解耦,以此来保持容器化应用程序的可移植性。ConfigMap API资源提供了将配置数据注入容器的方式,同时保证该机制对容器来说是透明的。ConfigMap可以被用来保存单个属性,也可以用来保存整个配置文件或者JSON二进制大对象。

ConfigMap API以键值对的方式存储配置数据。ConfigMap的数据可以被Pod和控制器等系统组件使用。onfigMap和Secret类似,但ConfigMap用于存储不包含敏感信息的数据。用户和系统组件一样能够在ConfigMap中存储配置数据。ConfigMap可以保存环境变量的属性,也可以保存配置文件。ConfigMap的data field包含配置数据。如下面例子所示,ConfigMap可以包含细粒度的配置项,如:example.property.1;也可以包含粗粒度的配置文件,如:example.property.file。

kind: ConfigMap
apiVersion: v1
metadata:
  creationTimestamp: 2016-02-18T19:14:38Z
  name: example-config
  namespace: default
data:
  # example of a simple property defined using --from-literal
  example.property.1: hello
  example.property.2: world
  # example of a complex property defined using --from-file
  example.property.file: |-
    property.1=value-1
    property.2=value-2

在使用Config时需要注意的事项:

  • 在Pod 规格应用ConfigMap之前,ConfigMap必须存在。如果Pod引用的ConfigMap不存在,Pod将不能启动。
  • ConfigMap只能被在同一一个命名空间中的Pod所引用。

2、创建ConfigMap

在Kubernetes中,可以使用kubectl create configmap命令,通过目录、文件和指定值(literal value)来创建:

$ kubectl create configmap <map-name> <data-source>

这里的 <map-name> 是希望创建的ConfigMap的名称,<data-source>是一个目录、文件和具体值。

在ConfigMap中,键值对的数据源如下所述:

  • key = 文件名或者在命令行中提供的键
  • value = 文件内容或者在命令行中提供的具体值

能够使用kubectl describe或者kubectl get获取ConfigMap的信息。

2.1 通过目录创建ConfigMaps

1)通过在一个目录下的多个文件创建ConfigMap,例如:

$kubectl create configmap game-config \
--from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl

2)docs/tasks/configure-pod-container/configmap/kubectl/目录下的文件包括:

$ ls docs/tasks/configure-pod-container/configmap/kubectl/ 
  • game.properties
  • ui.properties

3)查看game-config ConfigMap的信息:

$ kubectl describe configmaps game-config

4)在docs/tasks/configure-pod-container/configmap/kubectl/ 目录下的game.properties和ui.properties文件的内容在ConfigMap中的data区域进行显示:

$ kubectl get configmaps game-config -o yaml

2.2 通过文件创建ConfigMaps

2.2.1 通过单个文件创建

1)通过单个文件创建ConfigMap,例如:

$ kubectl create configmap game-config-2 \
--from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties

2)查看生产的ConfigMap信息:

$ kubectl describe configmaps game-config-2

2.2.2 通过多个文件生成

1)通过多个文件创建ConfigMap

$ kubectl create configmap game-config-3 \
--from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties \
--from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/ui.properties

2)查看生产的ConfigMap信息:

$ kubectl describe configmaps game-config-3

2.2.3 通过文件创建ConfigMap时可以定义文件的键

$ kubectl create configmap game-config-4 --from-file=<my-key-name>=<path-to-file>

这里的<my-key-name>是在ConfigMap里想要被使用的键,<path-to-file>是文件的路径。例如:

$ kubectl create configmap game-config-4 \
--from-file=game-special-key=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties
$ kubectl get configmaps game-config-4 -o yaml

2.3 通过具体值创建ConfigMaps

通过kubectl create configmap命令,能够使用–from-literal参数来定义具体值来创建ConfigMap:

$ kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm

在命令行中可以输入多个键-值对。每一一个键值对会成为ConfigMap data部分的一条记录。

$ kubectl get configmaps special-config -o yaml

3、使用ConfigMap

3.1 使用ConfigMap数据定义Pod环境变量

3.1.1 Pod环境变量的值来自于单一ConfigMap

1)在ConfigMap中定义一个环境变量作为键值对:

$ kubectl create configmap special-config --from-literal=special.how=very

2)指派ConfigMap中定义的special.how的值给Pod中SPECIAL_LEVEL_KEY环境变量:

$ kubectl edit pod dapi-test-pod
apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","env"]
    env:
    # Define the environment variable
    - name:SPECIAL_LEVEL_KEY
      valueFrom:
        configMapKeyRef:
        # The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY
          name:special-config
          # Specify the key associated with the value
          key:special.how
   restartPolicy:Never

保存Pod规格的变化,Pod将输出SPECIAL_LEVEL_KEY=very。

3.1.2 Pod环境变量的值来自于多个ConfigMap

首先创建两个ConfigMap:

apiVersion:v1
kind:ConfigMap
metadata:
   name:special-config
   namespace:default
data:
   special.how:very
apiVersion:v1
kind:ConfigMap
metadata:
   name:env-config
   namespace:default
data:
   log_level:INFO

在Pod规格中定义环境变量:

apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","env"]
    env:
    - name:SPECIAL_LEVEL_KEY
      valueFrom:
        configMapKeyRef:
           name:special-config
           key:special.how
     - name:LOG_LEVEL
       valueFrom:
          configMapKeyRef:
              name:env-config
              key:log_level
  restartPolicy:Never

保存变更后的Pod,Pod将会输出SPECIAL_LEVEL_KEY=very和LOG_LEVEL=info。

3.2 在一个ConfigMap中配置的键值对都作为一个Pod的环境变量

注意:此能力在Kubernetes v1.6+可用。创建包含多个键-值对的ConfigMap。

apiVersion:v1
kind:ConfigMap
metadata:
  name:special-config
  namespace:default
data:
  SPECIAL_LEVEL:very
  SPECIAL_TYPE:charm

使用envFrom定义所有的ConfigMap数据作为Pod的环境变量。来自于Config的键成为Pod中环境变量的名。

apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","env"]
      envFrom:
      - configMapRef:
          name:special-config
   restartPolicy:Never

保存Pod规范的变更,现在Pod的输出包括:SPECIAL_LEVEL=very 和 SPECIAL_TYPE=charm

3.3 在Pod命令行中使用ConfigMap定义的环境变量

在Pod规范的command 中使用$(VAR_NAME) ,获取ConfigMap定义的环境变量。例如:下面的Pod规范:

apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)"]
    env:
    - name:SPECIAL_LEVEL_KEY
      valueFrom:
         configMapKeyRef:
            name:special-config
            key:SPECIAL_LEVEL
    - name:SPECIAL_TYPE_KEY
      valueFrom:
          configMapKeyRef:
            name:special-config
            key:SPECIAL_TYPE
  restartPolicy:Never

test-container容器的输入如下:

very charm

4、添加ConfigMap数据至存储卷

当通过–from-file创建的ConfigMap时,文件将作为一个键保存在ConfigMap中,而此文件的内容将作为值。

apiVersion:v1
kind:ConfigMap
metadata:
  name:special-config
  namespace:default
data:
  special.level:very
  special.type:charm

4.1 将ConfigMap中的数据传播到指定目录

在Pod的存储卷区域添加ConfigMap的名称。这将添加ConfigMap数据到volumeMounts.mountPath指定的目录下(在此例子为/etc/config)。command区域将引用保存在ConfigMap中的special.level条目。

apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","ls /etc/config/"]
    volumeMounts:
    - name:config-volume
      mountPath:/etc/config
  volumes:
  - name:config-volume
    configMap:
        # Provide the name of the ConfigMap containing the files you want
        # to add to the container
      name:special-config
  restartPolicy:Never

当Pod运行时,command (“ls /etc/config/”)将输出下面的内容:

special.level
special.type

注意:如果在/etc/config/目录下存在文件,将不会删除。

4.2 添加ConfigMap数据至存储卷指定的目录

为ConfigMap条目,使用path指定文件路径。在此示例中,special.level将在config-volume存储卷中被挂接至/etc/config/keys。

apiVersion:v1
kind:Pod
metadata:
  name:dapi-test-pod
spec:
  containers:
  - name:test-container
    image:k8s.gcr.io/busybox
    command:["/bin/sh","-c","cat /etc/config/keys"]
    volumeMounts:
     - name:config-volume
       mountPath:/etc/config
  volumes:
  - name:config-volume
    configMap:
       name:special-config
       items:
       - key:special.level
         path:keys
   restartPolicy:Never

当Pod运行时,(“cat /etc/config/keys”) 将输出:

very

 

参考材料

1.《Configure a Pod to Use a ConfigMap》 地址:https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/

作者简介:
季向远,北京神舟航天软件技术有限公司产品经理。本文版权归原作者所有。

K8S中文社区微信公众号