概述

ConfigMap 是以一个或多个 key:value 的形式保存在 Kubernetes 系统中的信息,供应用使用。既可以用于表示变量的值,也可以用于表示配置文件的内容。

创建

通过yaml配置文件方式创建

#简单内容示例
# cat cm-appvars.yaml

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. name: cm-appvars
  5. data:
  6. apploglevel: info
  7. appdatadir: /var/data

kubectl create -f cm-appvars.yaml

#复杂内容(配置文件)示例
cm-appconfigfiles.yaml 描述了将两个配置文件 server.xml 和 logging.properties 定义为 ConfigMap 的用法,设置 key 为配置文件的别名,value是配置文件的全部文本内容。

apiVersion: v1
kind: ConfigMap
metadata:
  name: cm-appconfigfiles
data:
  key-serverxml: |
    <?xml version='1.0' enconding='utf-8'?>
    <Server port="8005" shutdown="SHUTDOWN">
  key-loggingproperties: |
    handlers=lcatalina.ory.apache.juli

kubectl create -f cm-appconfigfiles.yaml

通过kubectl命令行方式创建

使用参数 —from-file 或 —from-literal 指定内容,—from-file这个参数可以使用多次,可多次使用指定多个文件,效果如同指定整个目录。

]# ls cm-files/
game.properties  ui.properties

]# cat cm-files/game.properties
enemies=aliens
lives=3
enemies.cheat=true

]# cat cm-files/ui.properties
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice

]# kubectl create configmap game-config --from-file=cm-files/
等效于
]# kubectl create configmap game-config1 --from-file=cm-files/game.properties --from-file=cm-files/ui.properties

使用

通过环境变量方式使用

以前面创建的 ConfigMap “cm-appvars” 为例,cm-test-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-pod
spec:
  containers:
  - name: cm-test
    image: busybox
    command: [ "/bin/sh", "-c", "env| grep APP" ]
    env:
    - name: APPLOGLEVEL     # 定义环境变量的名称
      valueFrom: 
        configMapKeyRef:
          name: cm-appvars    # 基于指定的ConfigMap
          key: apploglevel    # ConfigMap中的key值
    - name: APPDATADIR
      valueFrom:
        configMapKeyRef:
          name: cm-appvars
          key: appdatadir
  restartPolicy: Never

应用后查看日志,输出对应的环境变量信息

]# kubectl apply -f cm-test-pod.yaml

]# kubectl  logs -f cm-test-pod
APPLOGLEVEL=info
APPDATADIR=/var/data

通过volumeMount使用

在 Pod “cm-test-app” 的定义中,将 ConfigMap “cm-appconfigfiles” 中的内容以文件的形式 mount 到容器内部的 /configfiles 目录下。cm-test-app.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-app
spec:
  containers:
  - name: cm-test-app
    image: kubeguide/tomcat-app:v1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: serverxml  # 引用volume的名称
      mountPath: /configfiles  # 挂载到容器内的目录
  volumes:
  - name: serverxml  # 定义volume的名称
    configMap:
      name: cm-appconfigfiles  # 使用ConfigMap ‘cm-appconfigfiles’
      items:
      - key: key-serverxml
        path: server.xml  # value将以server.xml文件名进行挂载
      - key: key-loggingproperties
        path: logging.properties

创建pod
kubectl create -f cm-test-app.yaml

容器中/configfiles目录下存在server.xml和logging.properties文件

]# kubectl exec -it cm-test-app -- bash
root@cm-test-app:/usr/local/tomcat# ls /configfiles/
logging.properties  server.xml
root@cm-test-app:/usr/local/tomcat# cat /configfiles/server.xml  
<?xml version='1.0' enconding='utf-8'?>
<Server port="8005" shutdown="SHUTDOWN">

#不指定items的情况说明
若引用ConfigMap时不指定items,则使用volumeMount方式在容器内的目录下为每个item都生成一个文件名为key的文件。示例如下:

cm-test-app.yaml

apiVersion: v1
kind: Pod
metadata:
  name: cm-test-app
spec:
  containers:
  - name: cm-test-app
    image: kubeguide/tomcat-app:v1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: serverxml  # 引用volume的名称
      mountPath: /configfiles  # 挂载到容器内的目录
  volumes:
  - name: serverxml  # 定义volume的名称
    configMap:
      name: cm-appconfigfiles  # 使用ConfigMap ‘cm-appconfigfiles’

应用后查看

]# kubectl exec -it cm-test-app -- bash
root@cm-test-app:/usr/local/tomcat# ls /configfiles/
key-loggingproperties key-serverxml

限制条件

使用 ConfigMap 的限制条件:

  • ConfigMap必须在Pod之前创建。
  • ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它。
  • kubelet只支持可以被API Server管理的Pod使用ConfigMap。kubelet在节点上通过 —manifest-url 或 —config 自动创建的静态Pod无法引用ConfigMap。
  • 在Pod对ConfigMap进行挂载(volumeMount)到容器内部后,在目录下将包含ConfigMap定义的每个item,如果在该目录下原来还有其他文件,则容器内的该目录将被挂载的ConfigMap覆盖。如果应用程序需要保留原来的其他文件,可将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接到(cp或link命令)应用所用的实际配置目录下。

ConfigMap配置文件挂载使用场景

单文件挂载到空目录

假如业务应用有一个配置文件,名为 application.yml,如果想将此配置挂载到pod的/etc/application/目录中。

$ cat application.yml
spring:
  application:
    name: svca-service
  cloud:
    config:
      uri: http://config:8888
      fail-fast: true
      username: user
      password: ${CONFIG_SERVER_PASSWORD:password}
      retry:
        initial-interval: 2000
        max-interval: 10000
        multiplier: 2
        max-attempts: 10

有两种方式生成对应的configmap:

1、通过 kubectl 命令行生成

# 通过文件直接创建
$ kubectl -n default create configmap application-config --from-file=application.yml

# 会生成配置文件,查看内容,configmap的key为文件名字
$ kubectl -n default get cm application-config -oyaml

2、通过yaml文件直接创建

$ cat application-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: application-config
  namespace: default
data:
  application.yml: |
    spring:
      application:
        name: svca-service
      cloud:
        config:
          uri: http://config:8888
          fail-fast: true
          username: user
          password: ${CONFIG_SERVER_PASSWORD:password}
          retry:
            initial-interval: 2000
            max-interval: 10000
            multiplier: 2
            max-attempts: 10

# 创建configmap
$ kubectl apply -f application-config.yaml

准备demo-deployment.yaml文件,挂载上述 configmap 到/etc/application/

$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
  namespace: default
spec:
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      volumes:
      - configMap:
          name: application-config
        name: config
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "/etc/application"
          name: config
#创建
$ kubectl apply -f demo-deployment.yaml

#修改configmap文件内容
$ kubectl edit cm application-config

当configmap内容发生变化时,pod会自动感知并更新到pod内部。但pod内的进程不会自动重启加载配置,所以很多服务会实现一个内部的reload接口,用来加载最新的配置文件到进程中。

多文件挂载

假如有多个配置文件,都需要挂载到pod内部,且都在一个目录中

$ cat application.yml
spring:
  application:
    name: svca-service
  cloud:
    config:
      uri: http://config:8888
      fail-fast: true
      username: user
      password: ${CONFIG_SERVER_PASSWORD:password}
      retry:
        initial-interval: 2000
        max-interval: 10000
        multiplier: 2
        max-attempts: 10

$ cat supervisord.conf
[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700

[supervisord]
logfile=/var/logs/supervisor/supervisord.log
logfile_maxbytes=200MB
logfile_backups=10
loglevel=info
pidfile=/var/run/supervisord.pid
childlogdir=/var/cluster_conf_agent/logs/supervisor
nodaemon=false

有两种方式创建:

$ kubectl create cm application-config --from-file=application.yml --from-file=supervisord.conf

$ kubectl get cm application-config -oyaml

观察Pod已经自动获取到最新的变化

$ kubectl exec demo-55c649865b-gpkgk ls /etc/application/
application.yml
supervisord.conf

当前是挂载到pod内的空目录中/etc/application,假如想挂载到pod已存在的目录中,比如:

$  kubectl exec   demo-55c649865b-gpkgk ls /etc/profile.d
color_prompt
locale

更改deployment的挂载目录:

$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
  namespace: default
spec:
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      volumes:
      - configMap:
          name: application-config
        name: config
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "/etc/profile.d"
          name: config
# 重建pod
$ kubectl apply -f demo-deployment.yaml

# 查看pod内的/etc/profile.d目录,发现已有文件被覆盖
$ kubectl exec demo-77d685b9f7-68qz7 ls /etc/profile.d
application.yml
supervisord.conf

挂载子路径

不同配置文件挂载到pod内的不同目录,比如:

  • application.yml挂载到/etc/application/
  • supervisord.conf挂载到/etc/profile.d

configmap保持不变,修改deployment文件:

$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo
  namespace: default
spec:
  selector:
    matchLabels:
      app: demo
  template:
    metadata:
      labels:
        app: demo
    spec:
      volumes:
      - name: config
        configMap:
          name: application-config
          items:
          - key: application.yml
            path: application
          - key: supervisord.conf
            path: supervisord
      containers:
      - name: nginx
        image: nginx:alpine
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: "/etc/application/application.yml"
          name: config
          subPath: application
        - mountPath: "/etc/profile.d/supervisord.conf"
          name: config
          subPath: supervisord

验证:

$ kubectl apply -f demo-deployment.yaml

$ kubectl exec demo-78489c754-shjhz ls /etc/application
application.yml

$ kubectl exec demo-78489c754-shjhz ls /etc/profile.d/
supervisord.conf
color_prompt
locale

说明:使用subPath挂载到Pod内部的文件,不会自动感知原有ConfigMap的变更。