kubernetes之十: ConfigMap

什么是ConfigMap

ConfigMap是用来存储配置文件的Kubernetes的资源对象,配置对象存储在Etcd中,配置的形式可以是完整的配置文件或者key/value的形式

 

ConfigMap可以带来什么好处

传统的应用服务,每个服务都有自己的配置文件,各自配置文件存储在服务所在节点,对于单体应用,这种存储没有任何问题,
但是随着用户数量的激增,一个节点不能满足线上用户使用,故服务可能从一个节点扩展到十个节点,这就导致,
如果有一个配置出现变更,就需要对应修改十次配置文件。这种人肉处理,显然不能满足线上部署要求,
故引入了各种类似于 ZooKeeper 中间件实现的配置中心,但配置中心属于 “侵入式” 设计,
需要修改引入第三方类库,它要求每个业务都调用特定的配置接口,破坏了系统本身的完整性,
Kubernetes 利用了 Volume 功能,完整设计了一套配置中心,其核心对象就是ConfigMap
使用过程不用修改任何原有设计,即可无缝对 ConfigMap;为什么呢?

 

 

使用configmap的限制条件

 

ConfigMap必须在Pod之前创建

ConfigMap受Namespace限制,只有处于相同Namespace中的Pod才可以引用它。

ConfigMap中的配额管理还未能实现。

kubelet只支持可以被API Server管理的Pod使用ConfigMap

kubelet在本Node上通过 --manifest-url或–config自动创建的静态Pod将无法引用ConfigMap。

在Pod对ConfigMap进行挂载(volumeMount)操作时,在容器内部只能挂载为“目录”,无法挂载为“文件”,在挂载到容器内部后,在目录下将包含ConfigMap定义的每个item,
如果在该目录下原来还有其他文件,则容器内的该目录将被挂载的ConfigMap覆盖 如果应用程序需要保留原来的其他文件,则需要进行额外的处理。可以将ConfigMap挂载到容器内部的临时目录,再通过启动脚本将配置文件复制或者链接到(cp或link命令)应用
所用的实际配置目录下

  

 

ConfigMap 三种创建方式

第一种方式: 指定字面量进行创建,创建命令如下所示

kubectl create configmap configmaptest --from-literal=foo=bar --from-literal=one=two



[root@master01 ~]# kubectl get configmap configmaptest -o yaml
apiVersion: v1
data:
  foo: bar
  one: two
kind: ConfigMap
metadata:
  name: configmaptest
  namespace: default

 

第二种方式: 指定特定文件进行创建

[root@master01 template]# cat db.properties 
driverClassName=com.mysql.jdbc.Driver

kubectl create configmap config-files --from-file=/data/k8s/template/db.properties 



[root@master01 template]# kubectl get configmap config-files -o yaml
apiVersion: v1
data:
  db.properties: |
     driverClassName=com.mysql.jdbc.Driver
kind: ConfigMap
metadata:
  creationTimestamp: "2020-08-12T13:52:35Z"
  managedFields:
  - apiVersion: v1
    fieldsType: FieldsV1
    fieldsV1:
      f:data:
        .: {}
        f:db.properties: {}
    manager: kubectl
    operation: Update
    time: "2020-08-12T13:52:35Z"
  name: config-files
  namespace: default
  resourceVersion: "491983"
  selfLink: /api/v1/namespaces/default/configmaps/config-files
  uid: bfeacb89-fdd7-41d7-8089-ce1a1629b102
You have new mail in /var/spool/mail/root

 第三种:  指定特定文件夹进行创建

kubectl create configmap config-dir --from-file=/data/k8s/template/config/


[root@master01 ~]# kubectl get configmap config-dir -o yaml
apiVersion: v1
data:
  db.properties: |
    driverClassName=com.mysql.jdbc.Driver
  svc.properties: |
    #server
    protocol=tcp
  system.properties: |
    time=100
kind: ConfigMap
metadata:
  name: config-dir
  namespace: default

 

 ConfigMap 作为环境变量三种使用方式

1、单个引用
先创建configmap

kubectl create configmap configmaptest --from-literal=code=25 --from-literal=foo=bar --from-literal=one=two
 


    spec:
      containers:
      - name: demo-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        env:
        - name: CODE-TIME   (env变量名)
          valueFrom:
            configMapKeyRef:
              name: configmaptest   (configmap的名称)
              key: code           (定义的key)

验证

[root@master01 template]# kubectl exec -it demo-nginx-55485d6b97-7wzhq -- /bin/bash
root@demo-nginx-55485d6b97-7wzhq:/# env|grep CO
CODE-TIME=25


  

2)多个引用

一次性传递所有ConfigMap条目作为环境变量

    spec:
      containers:
      - name: demo-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        envFrom:
        - prefix: CODE_     #以CODE前缀
          configMapRef:
            name: configmaptest  #configmap名称

        ports:
        - name: http
          containerPort: 80

验证

[root@master01 template]# kubectl exec -it demo-nginx-6b8dcf7d4f-xzhgk -- /bin/bash
root@demo-nginx-6b8dcf7d4f-xzhgk:/# env|grep CO
CODE_code=25
CODE_one=two
CODE_foo=bar

 

3) args 方式传递环境变量

容器启动时,传递该变量到服务,运行 shell 脚本,可能会用到,具体设置方式如图(5)所示

   spec:
      containers:
      - name: demo-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        env:
        - name: CONFIG
          valueFrom:
            configMapKeyRef:
              name: configmaptest
              key: code
        args: ["$(CONFIG)"]

  

 4)volume挂载

......
        - containerPort: 80

        volumeMounts:
          - mountPath: /usr/local/nginx/conf/vhost/
            name: http

          - mountPath: /usr/local/nginx/html/foo
            subPath: foo
            name: nginx-html

      volumes:
      - name: http
        configMap:
          name: nginx-conf

      - name: nginx-html
        configMap:
          name: configmaptest
          items: 
          - key: foo
            path: foo
   ......

如果有特定需求,需要挂载某个特定文件,而不允许覆盖原有文件,可以挂载到指定文件,通过 subPath 配合指定文件。
但是单个文件挂载这种方式不能实现热更新,即宿主机 ConfigMap 文件发生变化,容器内部不会自动重载

至于 items 使用就比较简单了,如果一个 ConfigMap 中包含多个配置文件,但是只想暴露出来其中一部分
那么可以通过 items 方式进行指定。当然你也可以对文件设置读写权限

像下面的LAMP,可以将同一个volume下的 mysql 和 html目录,挂载到不同的挂载点上,这样就不需要为 mysql 和 html 单独创建volume了

apiVersion: v1
kind: Pod
metadata:
  name: my-lamp-site
spec:
    containers:
    - name: mysql
      image: mysql
      env:
      - name: MYSQL_ROOT_PASSWORD
        value: "rootpasswd" 

      volumeMounts:
      - mountPath: /var/lib/mysql
        name: site-data
        subPath: mysql

    - name: php
      image: php:7.0-apache
      volumeMounts:
      - mountPath: /var/www/html
        name: site-data
        subPath: html

    volumes:
    - name: site-data
      persistentVolumeClaim:
        claimName: my-lamp-site-data

 

 

apiVersion: v1kind: Pmetadata:

  name: pod-volume-test
spec:
  containers:
    - name: apache
      image: httpd
      ports:
        - containerPort: 80
      volumeMounts:
        - name: volume-test
          mountPath: /var/www/html
  volumes:
    - name: volume-test
      configMap:
        name: cm-apache
        items:
          - key: html
            path: main.html   #文件名
          - key: path
            path: path.txt   #文件名


验证:
root@pod-volume-test:/# cd /var/www/html/ 
root@pod-volume-test:/var/www/html# ls 
main.html path.txt
root@pod-volume-test:/var/www/html#cat main.html 

hello world 
root@pod-volume-test:/var/www/html# cat path.txt 
/var/www/html

  

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: busybox
    args: [ "/bin/sh", "-c", "sleep 3000" ]
    volumeMounts:
    - name: mysql
      mountPath: "/tmp"

  volumes:
  - name: mysql
    configMap:
      name: mysql-cm
      items:
      - key: my.cnf
        path: mysql/my.cnf  

验证

[root@master ~]# kubectl exec -it mypod sh
/ # cat /tmp/mysql/my.cnf 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
!includedir /etc/my.cnf.d
/ # exit

  

热更新机制

当 ConfigMap 作为 Volume 进行挂载时,它的内容是会更新的。分析 ConfigMap volume 的更新机制:

更新操作由 kubelet 的 Pod 同步循环触发,每次进行 Pod 同步时(默认每 10 秒一次),kubelet 都会将 Pod 的所有 ConfigMap Volume 标记为“需要重新挂载
(RequireRemount)”,而 kubelet 中的 Volume 控制循环会发现这些需要重新挂载的 Volume,去执行一次挂载操作,在 ConfigMap 的重新挂载过程中,kubelet
会先比较远端的 ConfigMap 与 Volume 中的 ConfigMap 是否一致,再做更新。要注意,“拿远端的 ConfigMap” 这个操作可能是有缓存的,因此拿到的并不一定是最新版本。
延迟时间:Pod 同步间隔(默认10秒)+ ConfigMap 本地缓存的 TTL。

  

部分文件挂载

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: busybox
    role: master
  name: busybox
spec:
  containers:
  - name: busybox
    image: myhub.fdccloud.com/library/busybox
    command:
    - sleep
    - "3600"

    volumeMounts:
    - name: configmap-volume
      mountPath: /etc/passwd
      subPath: path/to/passwd
    - name: configmap-volume-1
      mountPath: /etc/group
      subPath: path/to/group

  nodeSelector:
    app: busybox

  volumes:
  - name: configmap-volume
    configMap:
      name: cmtest
      items:
        - key: passwd
          path: path/to/passwd

  - name: configmap-volume-1
    configMap:
      name: cmtest
      items:
        - key: group
          path: path/to/group

  

 

  

 

 

 

 

posted @ 2020-08-12 21:59  个人成长之路  阅读(475)  评论(0编辑  收藏  举报