• ConfigMap
    • 创建
    • 使用

    ConfigMap

    前面的课程中我们学习了Servie的使用,ServiceKubernetes系统中非常重要的一个核心概念,我们还会在后面
    的课程中继续学习Service的一些使用方法的。这节课我们来学习另外一个非常重要的资源对象:ConfigMap,我们知道许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息,这些配置信息我们肯定不会直接写死到应用程序中去的,比如你一个应用连接一个redis服务,下一次想更换一个了的,还得重新去修改代码,重新制作一个镜像,这肯定是不可取的,而ConfigMap就给我们提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,也可以用来保存整个配置文件,比如我们可以用来配置一个redis服务的访问地址,也可以用来保存整个redis的配置文件。

    创建

    ConfigMap 资源对象使用key-value形式的键值对来配置数据,这些数据可以在Pod里面使用,ConfigMap和我们后面要讲到的Secrets比较类似,一个比较大的区别是ConfigMap可以比较方便的处理一些非敏感的数据,比如密码之类的还是需要使用Secrets来进行管理。我们来举个例子说明下ConfigMap的使用方法:

    1. kind: ConfigMap
    2. apiVersion: v1
    3. metadata:
    4. name: cm-demo
    5. namespace: default
    6. data:
    7. data.1: hello
    8. data.2: world
    9. config: |
    10. property.1=value-1
    11. property.2=value-2
    12. property.3=value-3

    其中配置数据在data属性下面进行配置,前两个被用来保存单个属性,后面一个被用来保存一个配置文件。

    当然同样的我们可以使用kubectl create -f xx.yaml来创建上面的ConfigMap对象,但是如果我们不知道怎么创建ConfigMap的话,不要忘记kubectl是我们最好的老师,可以使用kubectl create configmap -h来查看关于创建ConfigMap的帮助信息,

    1. Examples:
    2. # Create a new configmap named my-config based on folder bar
    3. kubectl create configmap my-config --from-file=path/to/bar
    4. # Create a new configmap named my-config with specified keys instead of file basenames on disk
    5. kubectl create configmap my-config --from-file=key1=/path/to/bar/file1.txt --from-file=key2=/path/to/bar/file2.txt
    6. # Create a new configmap named my-config with key1=config1 and key2=config2
    7. kubectl create configmap my-config --from-literal=key1=config1 --from-literal=key2=config2

    我们可以看到可以从一个给定的目录来创建一个ConfigMap对象,比如我们有一个testcm的目录,该目录下面包含一些配置文件,redismysql的连接信息,如下:

    1. $ ls testcm
    2. redis.conf
    3. mysql.conf
    4. $ cat testcm/redis.conf
    5. host=127.0.0.1
    6. port=6379
    7. $ cat testcm/mysql.conf
    8. host=127.0.0.1
    9. port=3306

    然后我们可以使用from-file关键字来创建包含这个目录下面所以配置文件的ConfigMap

    1. $ kubectl create configmap cm-demo1 --from-file=testcm
    2. configmap "cm-demo1" created

    其中from-file参数指定在该目录下面的所有文件都会被用在ConfigMap里面创建一个键值对,键的名字就是文件名,值就是文件的内容。

    创建完成后,同样我们可以使用如下命令来查看ConfigMap列表:

    1. $ kubectl get configmap
    2. NAME DATA AGE
    3. cm-demo1 2 17s

    可以看到已经创建了一个cm-demo1ConfigMap对象,然后可以使用describe命令查看详细信息:

    1. kubectl describe configmap cm-demo1
    2. Name: cm-demo1
    3. Namespace: default
    4. Labels: <none>
    5. Annotations: <none>
    6. Data
    7. ====
    8. mysql.conf:
    9. ----
    10. host=127.0.0.1
    11. port=3306
    12. redis.conf:
    13. ----
    14. host=127.0.0.1
    15. port=6379
    16. Events: <none>

    我们可以看到两个keytestcm目录下面的文件名称,对应的value值的话就是文件内容,这里值得注意的是如果文件里面的配置信息很大的话,describe的时候可能不会显示对应的值,要查看键值的话,可以使用如下命令:

    1. $ kubectl get configmap cm-demo1 -o yaml
    2. apiVersion: v1
    3. data:
    4. mysql.conf: |
    5. host=127.0.0.1
    6. port=3306
    7. redis.conf: |
    8. host=127.0.0.1
    9. port=6379
    10. kind: ConfigMap
    11. metadata:
    12. creationTimestamp: 2018-06-14T16:24:36Z
    13. name: cm-demo1
    14. namespace: default
    15. resourceVersion: "3109975"
    16. selfLink: /api/v1/namespaces/default/configmaps/cm-demo1
    17. uid: 6e0f4d82-6fef-11e8-a101-525400db4df7

    除了通过文件目录进行创建,我们也可以使用指定的文件进行创建ConfigMap,同样的,以上面的配置文件为例,我们创建一个redis的配置的一个单独ConfigMap对象:

    1. $ kubectl create configmap cm-demo2 --from-file=testcm/redis.conf
    2. configmap "cm-demo2" created
    3. $ kubectl get configmap cm-demo2 -o yaml
    4. apiVersion: v1
    5. data:
    6. redis.conf: |
    7. host=127.0.0.1
    8. port=6379
    9. kind: ConfigMap
    10. metadata:
    11. creationTimestamp: 2018-06-14T16:34:29Z
    12. name: cm-demo2
    13. namespace: default
    14. resourceVersion: "3110758"
    15. selfLink: /api/v1/namespaces/default/configmaps/cm-demo2
    16. uid: cf59675d-6ff0-11e8-a101-525400db4df7

    我们可以看到一个关联redis.conf文件配置信息的ConfigMap对象创建成功了,另外值得注意的是--from-file这个参数可以使用多次,比如我们这里使用两次分别指定redis.confmysql.conf文件,就和直接指定整个目录是一样的效果了。

    另外,通过帮助文档我们可以看到我们还可以直接使用字符串进行创建,通过--from-literal参数传递配置信息,同样的,这个参数可以使用多次,格式如下:

    1. $ kubectl create configmap cm-demo3 --from-literal=db.host=localhost --from-literal=db.port=3306
    2. configmap "cm-demo3" created
    3. $ kubectl get configmap cm-demo3 -o yaml
    4. apiVersion: v1
    5. data:
    6. db.host: localhost
    7. db.port: "3306"
    8. kind: ConfigMap
    9. metadata:
    10. creationTimestamp: 2018-06-14T16:43:12Z
    11. name: cm-demo3
    12. namespace: default
    13. resourceVersion: "3111447"
    14. selfLink: /api/v1/namespaces/default/configmaps/cm-demo3
    15. uid: 06eeec7e-6ff2-11e8-a101-525400db4df7

    使用

    ConfigMap创建成功了,那么我们应该怎么在Pod中来使用呢?我们说ConfigMap这些配置数据可以通过很多种方式在Pod里使用,主要有以下几种方式:

    • 设置环境变量的值
    • 在容器里设置命令行参数
    • 在数据卷里面创建config文件

    首先,我们使用ConfigMap来填充我们的环境变量:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: testcm1-pod
    5. spec:
    6. containers:
    7. - name: testcm1
    8. image: busybox
    9. command: [ "/bin/sh", "-c", "env" ]
    10. env:
    11. - name: DB_HOST
    12. valueFrom:
    13. configMapKeyRef:
    14. name: cm-demo3
    15. key: db.host
    16. - name: DB_PORT
    17. valueFrom:
    18. configMapKeyRef:
    19. name: cm-demo3
    20. key: db.port
    21. envFrom:
    22. - configMapRef:
    23. name: cm-demo1

    这个Pod运行后会输出如下几行:

    1. $ kubectl logs testcm1-pod
    2. ......
    3. DB_HOST=localhost
    4. DB_PORT=3306
    5. mysql.conf=host=127.0.0.1
    6. port=3306
    7. redis.conf=host=127.0.0.1
    8. port=6379
    9. ......

    我们可以看到DB_HOSTDB_PORT都已经正常输出了,另外的环境变量是因为我们这里直接把cm-demo1给注入进来了,所以把他们的整个键值给输出出来了,这也是符合预期的。

    另外我们可以使用ConfigMap来设置命令行参数,ConfigMap也可以被用来设置容器中的命令或者参数值,如下Pod:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: testcm2-pod
    5. spec:
    6. containers:
    7. - name: testcm2
    8. image: busybox
    9. command: [ "/bin/sh", "-c", "echo $(DB_HOST) $(DB_PORT)" ]
    10. env:
    11. - name: DB_HOST
    12. valueFrom:
    13. configMapKeyRef:
    14. name: cm-demo3
    15. key: db.host
    16. - name: DB_PORT
    17. valueFrom:
    18. configMapKeyRef:
    19. name: cm-demo3
    20. key: db.port

    运行这个Pod后会输出如下信息:

    1. $ kubectl logs testcm2-pod
    2. localhost 3306

    另外一种是非常常见的使用ConfigMap的方式:通过数据卷使用,在数据卷里面使用ConfigMap,就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: testcm3-pod
    5. spec:
    6. containers:
    7. - name: testcm3
    8. image: busybox
    9. command: [ "/bin/sh", "-c", "cat /etc/config/redis.conf" ]
    10. volumeMounts:
    11. - name: config-volume
    12. mountPath: /etc/config
    13. volumes:
    14. - name: config-volume
    15. configMap:
    16. name: cm-demo2

    运行这个Pod的,查看日志:

    1. $ kubectl logs testcm3-pod
    2. host=127.0.0.1
    3. port=6379

    当然我们也可以在ConfigMap值被映射的数据卷里去控制路径,如下Pod定义:

    1. apiVersion: v1
    2. kind: Pod
    3. metadata:
    4. name: testcm4-pod
    5. spec:
    6. containers:
    7. - name: testcm4
    8. image: busybox
    9. command: [ "/bin/sh","-c","cat /etc/config/path/to/msyql.conf" ]
    10. volumeMounts:
    11. - name: config-volume
    12. mountPath: /etc/config
    13. volumes:
    14. - name: config-volume
    15. configMap:
    16. name: cm-demo1
    17. items:
    18. - key: mysql.conf
    19. path: path/to/msyql.conf

    运行这个Pod的,查看日志:

    1. $ kubectl logs testcm4-pod
    2. host=127.0.0.1
    3. port=3306

    另外需要注意的是,当ConfigMap以数据卷的形式挂载进Pod的时,这时更新ConfigMap(或删掉重建ConfigMap),Pod内挂载的配置信息会热更新。这时可以增加一些监测配置文件变更的脚本,然后reload对应服务。