第十九章 kubernetes 核心技术-ConfigMap


一、概述

在生产环境中经常会遇到需要修改配置文件的情况,传统的修改方式不仅会影响到服务的正常运行,而且操作步骤也很繁琐。为了解决这个问题,kubernetes项目从1.2版本引入了ConfigMap功能,用于将应用的配置信息与程序的分离。这种方式不仅可以实现应用程序被的复用,而且还可以通过不同的配置实现更灵活的功能。在创建容器时,用户可以将应用程序打包为容器镜像后,通过环境变量或者外接挂载文件的方式进行配置注入。ConfigMap && Secret 是K8S中的针对应用的配置中心,它有效的解决了应用挂载的问题,并且支持加密以及热更新等功能,可以说是一个k8s提供的一件非常好用的功能。

二、ConfigMap作用

ConfigMap 功能在 Kubernetes1.2 版本中引入,许多应用程序会从配置文件、命令行参数或环境变量中读取配 置信息。ConfigMap API给我们提供了向容器中注入配置信息的机制,ConfigMap 可以被用来保存单个属性,也可以用来保存整个配置文件或者 JSON 二进制大对象

作用:存储不加密数据到etcd,让Pod以变量或者volume挂载到容器中

场景:配置文件

三、ConfigMap指定配置文件

1.以Volume挂载到pod容器中

1)创建一个配置文件示例

[root@kubernetes-master-001 ~]# vim redis.properties 
redis.host=127.0.0.1
redis.port=6379
redis.password=123456

2)创建ConfigMap

[root@kubernetes-master-001 ~]# kubectl  create  configmap  redis-config --from-file=redis.properties 
configmap/redis-config created

[root@kubernetes-master-001 ~]# kubectl  get cm
NAME               DATA   AGE
kube-root-ca.crt   1      7d21h
redis-config       1      13s

[root@kubernetes-master-001 ~]# kubectl  describe cm redis-config
Name:         redis-config
Namespace:    default
Labels:       
Annotations:  

Data
====
redis.properties:
----
redis.host=127.0.0.1
redis.port=6379
redis.password=123456


BinaryData
====

Events:  

3)创建Pod

[root@kubernetes-master-001 ~]# vim cm.yaml 
apiVersion: v1 
kind: Pod 
metadata:
  name: mypod
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh", "-c", "cat /etc/config/redis.properties"]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: redis-config
  restartPolicy: Never

4)验证ConfigMap

[root@kubernetes-master-001 ~]# kubectl  apply  -f cm.yaml 
pod/mypod created

[root@kubernetes-master-001 ~]# kubectl get pods
NAME    READY   STATUS      RESTARTS   AGE
mypod   0/1     Completed   0          22s

[root@kubernetes-master-001 ~]# kubectl  logs mypod
redis.host=127.0.0.1
redis.port=6379
redis.password=123456

2.以变量形式挂载

1)创建变量文件

[root@kubernetes-master-001 ~]# vi myconfig.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfig
  namespace: default
data:
  special.level: info
  special.type: hello

2)创建ConfigMap

[root@kubernetes-master-001 ~]# kubectl apply -f myconfig.yaml 
configmap/myconfig created

[root@kubernetes-master-001 ~]# kubectl  get cm
NAME               DATA   AGE
kube-root-ca.crt   1      7d22h
myconfig           2      13s
redis-config       1      31m

3)创建Pod

[root@kubernetes-master-001 ~]# vim config-car.yaml 
apiVersion: v1 
kind: Pod 
metadata:
  name: mypod
spec:
  containers:
    - name: busybox
      image: busybox
      command: [ "/bin/sh", "-c", "echo $(LEVEL) $(TYPE)"]
      env:
        - name: LEVEL
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: special.level
        - name: TYPE
          valueFrom:
            configMapKeyRef:
              name: myconfig
              key: special.type
  restartPolicy: Never

4)验证ConfigMap

[root@kubernetes-master-001 ~]# kubectl  apply  -f config-car.yaml 
pod/mypod created

[root@kubernetes-master-001 ~]# kubectl  get  pods
NAME    READY   STATUS      RESTARTS   AGE
mypod   0/1     Completed   0          23s

[root@kubernetes-master-001 ~]# kubectl  logs mypod 
info hello

四、ConfigMap指定配置目录

1.创建目录及文件

[root@kubernetes-master-001 ~]# mkdir configmap
[root@kubernetes-master-001 ~]# touch configmap/index.html
[root@kubernetes-master-001 ~]# echo "index" > configmap/index.html

2.创建ConfigMap

[root@kubernetes-master-001 ~]# kubectl create configmap catalog --from-file=configmap/
configmap/catalog created
[root@kubernetes-master-001 ~]# kubectl describe configmaps catalog
Name:         catalog
Namespace:    default
Labels:       
Annotations:  

Data
====
index.html:
----
index


BinaryData
====

Events:  

五、ConfigMap指定配置项

[root@kubernetes-master-001 ~]# kubectl create configmap calue --from-literal=key=value --from-literal=key1=value1
configmap/calue created
[root@kubernetes-master-001 ~]# kubectl describe configmaps calue
Name:         calue
Namespace:    default
Labels:       
Annotations:  

Data
====
key:
----
value
key1:
----
value1

BinaryData
====

Events:  

六、ConfigMap指定配置清单

1.编写清单文件

[root@kubernetes-master-001 ~]# vim test.yaml
kind: ConfigMap
apiVersion: v1
metadata:
  name: configmap-yaml
  labels:
    app: configmap
data:
  key: value
  nginx_config: |-
    upstream tomcatserver1 {
      server 192.168.72.49:8081;
    }
    upstream tomcatserver2 {
      server 192.168.72.49:8082;
    }
    server {
      listen 80;
      server_name 8081.max.com;
      location / {
        proxy_pass http://tomcatserver1;
        index index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
      }
    }

2.创建ConfigMap

[root@kubernetes-master-001 ~]#  kubectl apply -f test.yaml
configmap/configmap-yaml created
[root@kubernetes-master-001 ~]# kubectl describe configmaps configmap-yaml
Name:         configmap-yaml
Namespace:    default
Labels:       app=configmap
Annotations:  

Data
====
key:
----
value
nginx_config:
----
upstream tomcatserver1 {
  server 192.168.72.49:8081;
}
upstream tomcatserver2 {
  server 192.168.72.49:8082;
}
server {
  listen 80;
  server_name 8081.max.com;
  location / {
    proxy_pass http://tomcatserver1;
    index index.html index.htm;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}

BinaryData
====

Events:  

七、使用ConfigMap

一般情况下,我们是通过挂载的方式使用configmap。

1.编写yaml文件

[root@kubernetes-master-001 ~]# vim test.yaml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: configmap-yaml
  labels:
    app: configmap
data:
  key: value
  nginx_config: |-
    upstream tomcatserver1 {
      server 192.168.72.49:8081;
    }
    server {
      listen 80;
      server_name 8081.max.com;
      location / {
        proxy_pass http://tomcatserver1;
        index index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
      }
    }

---

kind: Pod
apiVersion: v1
metadata:
  name: configmap-pod
  labels:
    app: configmap-pod
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
      volumeMounts:
        - mountPath: /usr/share/nginx/demo
          name: conf
  volumes:
    - name: conf
      configMap:
        name: configmap-yaml
        items:
          - key: nginx_config
            path: nginx_config
          - key: key
            path: key

2.部署应用

[root@kubernetes-master-001 ~]# kubectl  apply  -f test.yaml 
configmap/configmap-yaml configured
pod/configmap-pod created

[root@kubernetes-master-001 ~]# kubectl get  pod -l app=configmap-pod
NAME            READY   STATUS    RESTARTS   AGE
configmap-pod   1/1     Running   0          56s

3.验证应用

[root@kubernetes-master-001 ~]# kubectl  exec -it configmap-pod -- bash
root@configmap-pod:/# cd /usr/share/nginx/
root@configmap-pod:/usr/share/nginx# ls -l
total 0
drwxrwxrwx 3 root root 90 Nov 16 06:22 demo
drwxr-xr-x 2 root root 40 Nov 10 01:37 html
root@configmap-pod:/usr/share/nginx# cd demo/
root@configmap-pod:/usr/share/nginx/demo# ls
key  nginx_config
root@configmap-pod:/usr/share/nginx/demo# cat nginx_config 
upstream tomcatserver1 {
  server 192.168.72.49:8081;
}
server {
  listen 80;
  server_name 8081.max.com;
  location / {
    proxy_pass http://tomcatserver1;
    index index.html index.htm;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}root@configmap-pod:/usr/share/nginx/demo# cat key 
valueroot@configmap-pod:/usr/share/nginx/demo#

八、subPath

mountPath结合subPath(也可解决多个configmap挂载同一目录,导致覆盖)作用。

1.编写yaml文件

[root@kubernetes-master-001 ~]# vim web2.yaml 
kind: ConfigMap
apiVersion: v1
metadata:
  name: configmap-yaml
  labels:
    app: configmap
data:
  key: value
  nginx_config: |-
    upstream tomcatserver1 {
      server 192.168.72.49:8081;
    }
    upstream tomcatserver2 {
      server 192.168.72.49:8082;
    }
    server {
     listen 80;
     server_name 8081.max.com;
      location / {
        proxy_pass http://tomcatserver1;
        index index.html index.htm;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
      }
    }
---
kind: Pod
apiVersion: v1
metadata:
  name: configmap-pod
  labels:
    app: configmap-pod
spec:
  containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
      ports:
        - containerPort: 80
      volumeMounts:
        - mountPath: /usr/share/nginx/html/nginx.conf
          name: conf
          subPath: nginx_config
  volumes:
    - name: conf
      configMap:
        name: configmap-yaml
        items:
          - key: nginx_config
            path: nginx_config

2.应用部署

[root@kubernetes-master-001 ~]# kubectl apply  -f web2.yaml 
configmap/configmap-yaml created
pod/configmap-pod created

[root@kubernetes-master-001 ~]# kubectl  get pods
NAME            READY   STATUS    RESTARTS   AGE
configmap-pod   1/1     Running   0          19s

3.验证应用部署

[root@kubernetes-master-001 ~]# kubectl  exec -it configmap-pod -- bash
root@configmap-pod:/# cd /usr/share/nginx/html/
root@configmap-pod:/usr/share/nginx/html# ls -l
total 12
-rw-r--r-- 1 root root 497 Nov  2 14:49 50x.html
-rw-r--r-- 1 root root 615 Nov  2 14:49 index.html
-rw-r--r-- 1 root root 339 Nov 16 06:35 nginx.conf
root@configmap-pod:/usr/share/nginx/html# cat nginx.conf
upstream tomcatserver1 {
  server 192.168.72.49:8081;
}
upstream tomcatserver2 {
  server 192.168.72.49:8082;
}
server {
 listen 80;
 server_name 8081.max.com;
  location / {
    proxy_pass http://tomcatserver1;
    index index.html index.htm;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
  }
}root@configmap-pod:/usr/share/nginx/html#

九、ConfigMap热更新

1.编写yaml文件

[root@kubernetes-master-001 ~]# vim web3.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80
        envFrom:
        - configMapRef:
            name: env-config
        volumeMounts:
          - mountPath: /usr/share/nginx/demo/
            name: config
      volumes:
        - name: config
          configMap:
            name: env-config
            items:
              - key: log_level
                path: log_level
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO

2.部署应用

[root@kubernetes-master-001 ~]# kubectl  apply  -f web3.yaml 
deployment.apps/my-nginx created
configmap/env-config created

[root@kubernetes-master-001 ~]# kubectl  get pods
NAME                       READY   STATUS              RESTARTS   AGE
configmap-pod              1/1     Running             0          20m
my-nginx-6947589dc-txz7b   0/1     ContainerCreating   0          7s

[root@kubernetes-master-001 ~]# kubectl  get pods
NAME                       READY   STATUS    RESTARTS   AGE
configmap-pod              1/1     Running   0          22m
my-nginx-6947589dc-txz7b   1/1     Running   0          2m19s

3.验证应用

[root@kubernetes-master-001 ~]# kubectl exec  my-nginx-6947589dc-txz7b -- cat /usr/share/nginx/demo/log_level
INFO

[root@kubernetes-master-001 ~]# kubectl edit configmaps env-config 
configmap/env-config edited

[root@kubernetes-master-001 ~]# kubectl exec  my-nginx-6947589dc-txz7b -- cat /usr/share/nginx/demo/log_level
DEBUG

十、ConfigMap 更新后滚动更新 Pod

更新 ConfigMap 目前并不会触发相关 Pod 的滚动更新,可以通过修改 pod annotations 的方式强制触发滚动更新
[root@kubernetes-master-001 ~]# kubectl  patch deployments.apps  my-nginx --patch '{"spec": {"template": {"metadata":{"annotations": {"version/config": "20190411" }}}}}'
deployment.apps/my-nginx patched

这个例子里我们在.spec.template.metadata.annotations 中添加 version/config ,每次通过修改 version/config 来触发滚动更新

更新 ConfigMap 后:
1)使用该 ConfigMap 挂载的 Env 不会同步更新

2)使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概 10 秒)才能同步更新

相关