十六、K8s 配置管理中心 ConfigMap 实现微服务配置管理
16.1 ConfigMap 相关概念及cm字段
16.1.1 ConfigMap 概述
Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value键值对 的形式保存,也可通过 文件 的形式保存。
- Configmap 是 k8s 中的资源, 相当于配置文件,可以有一个或者多个 Configmap;
- Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
- 容器中应用程序按照原有方式读取容器特定目录上的配置文件;
- 在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。
configmap 注入方式有两种:
- 第一种:将 configMap 做为存储卷;
- 第二种:将 configMap 通过 env字段 中 configMapKeyRef变量 注入到容器中。
16.1.2 ConfigMap 能解决什么问题?
我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s 中引入了 Configmap 资源对象,可以当成 volume 挂载到 pod中,实现统一的配置管理。
16.1.3 ConfigMap 应用场景
16.1.3.1 场景1-部署应用
使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,configmap 可以将配置信息和 docker镜像 解耦,以便实现镜像的可移植性和可复用性,因为一个 configMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。
16.1.3.2 场景2-使用微服务架构
使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用configmap 可以友好的进行配置共享。
16.1.4 ConfigMap 局限性
ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过 1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。
16.1.5 cm字段
1]# kubectl explain cm 2 apiVersion <string> 3 kind <string> 4 metadata <ObjectMeta> 5 6 data <map[string]string> 7 # 以键值对的形式存储非二进制配置数据(适用于普通文本配置) 8 9 binaryData <map[string]string> 10 # 以Base64编码的形式存储二进制数据(适用于图片、证书等非文本文件) 11 12 immutable <boolean> 13 # 将 ConfigMap 标记为不可变,默认为 true,反之为 false 14 15# [`data`](https://xplanc.org/primers/document/zh/03.HTML/EX.HTML%20%E5%85%83%E7%B4%A0/EX.data.md) `binaryData`两者不可包含相同的键名,否则创建时会报错 16
16.2 ConfigMap 创建方式
16.2.1 方式1:命令行直接创建
1[root@k8s-master1 ~]# kubectl create configmap tomcat-cm --from-literal=tomcat_port=8080 --from-literal=server_name=tomcat 2 3[root@k8s-master1 ~]# kubectl get cm 4tomcat-cm 2 6s 5 6[root@k8s-master1 ~]# kubectl describe cm tomcat-cm 7server_name: 8---- 9tomcat 10 11tomcat_port: 12---- 138080 14

16.2.2 方式2:命令行指定文件创建
1[root@k8s-master1 ~]# kubectl create cm nginx-vhosts-conf --from-file=nginx=./nginx_vhosts.conf 2 3[root@k8s-master1 ~]# kubectl get cm 4nginx-vhosts-conf 1 14s 5 6[root@k8s-master1 ~]# kubectl describe cm nginx-vhosts-conf 7nginx: 8---- 9server { 10 listen 80; 11 server_name www.kaser.com; 12 root /usr/local/nginx/conf/conf.d/ 13} 14

16.2.3 方式3:命令行指定目录创建
1[root@k8s-master1 ~]# mkdir cm_test 2[root@k8s-master1 ~]# cd cm_test/ 3[root@k8s-master1 cm_test]# echo "server-id=1" > sql_master.cnf 4[root@k8s-master1 cm_test]# echo "server-id=2" > sql_slave.cnf 5[root@k8s-master1 cm_test]# ls 6sql_master.cnf sql_slave.cnf 7 8 9[root@k8s-master1 cm_test]# kubectl create cm sql-config-dir --from-file=/root/cm_test 10 11[root@k8s-master1 cm_test]# kubectl get cm 12sql-config-dir 2 26s 13 14[root@k8s-master1 cm_test]# kubectl describe cm sql-config-dir 15sql_master.cnf: 16---- 17server-id=1 18 19 20sql_slave.cnf: 21---- 22server-id=2 23

16.2.4 方式4:编写 yaml 文件创建
1[root@k8s-master1 ~]# vim mysql-cm.yaml 2apiVersion: v1 3kind: ConfigMap 4metadata: 5 name: mysql 6 labels: 7 app: mysql 8data: 9 test_sql_master.cnf: | # 写文件,后面必须要有 | 10 [mysqld] 11 log-bin 12 log_bin_trust_function_creators=1 13 lower_case_table_names=1 14 test_sql_slave.cnf: | 15 [mysqld] 16 super-read-only 17 log_bin_trust_function_creators=1 18 19[root@k8s-master1 ~]# kubectl apply -f mysql-cm.yaml 20[root@k8s-master1 ~]# kubectl get cm 21mysql 2 6s 22 23[root@k8s-master1 ~]# kubectl describe cm mysql 24test_sql_master.cnf: 25---- 26[mysqld] 27log-bin 28log_bin_trust_function_creators=1 29lower_case_table_names=1 30 31 32test_sql_slave.cnf: 33---- 34[mysqld] 35super-read-only 36log_bin_trust_function_creators=1 37

16.3 ConfigMap 使用方式
16.3.1 方式1:环境变量configMapKeyRef注入
优先使用
env+valueFrom
- 显式声明依赖的配置项,提高可读性和可维护性
- 避免因 ConfigMap 新增无关键导致意外行为
1]# kubectl explain pod.spec.containers.env 2 name <string> -required- 3 value <string> 4 valueFrom <EnvVarSource> 5# value 和 valueFrom 不能同时使用,二者互斥。 6 7[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom 8 configMapKeyRef <ConfigMapKeySelector> 9 fieldRef <ObjectFieldSelector> 10 resourceFieldRef <ResourceFieldSelector> 11 secretKeyRef <SecretKeySelector> 12 13[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom.configMapKeyRef 14 key <string> -required- 15 name <string> 16 optional <boolean> 17 # 是否可选: 18 # • false(默认):ConfigMap 或键不存在时,Pod 创建失败 19 # • true:ConfigMap/键不存在时忽略该环境变量,Pod 仍可创建 20
1[root@k8s-master1 ~]# vim cmkr-sql-cm.yaml 2apiVersion: v1 3kind: ConfigMap 4metadata: 5 name: cmkr-sql 6 labels: 7 app: mysql 8data: 9 log: "1" 10 lower: "1" 11 12[root@k8s-master1 ~]# kubectl apply -f cmkr-sql-cm.yaml 13[root@k8s-master1 ~]# kubectl get cm 14cmkr-sql 2 27s 15 16[root@k8s-master1 ~]# kubectl describe cm cmkr-sql 17log: 18---- 191 20 21lower: 22---- 231 24 25[root@k8s-master1 ~]# vim mysql-pod.yaml 26apiVersion: v1 27kind: Pod 28metadata: 29 name: mysql-pod 30spec: 31 containers: 32 - name: mysql 33 image: docker.io/library/busybox:1.28 34 imagePullPolicy: IfNotPresent 35 command: ["/bin/sh","-c","sleep 3600"] 36 env: 37 - name: log_bin 38 valueFrom: 39 configMapKeyRef: 40 name: cmkr-sql 41 key: log 42 - name: lower_bin 43 valueFrom: 44 configMapKeyRef: 45 name: cmkr-sql 46 key: lower 47 48[root@k8s-master1 ~]# kubectl apply -f mysql-pod.yaml 49[root@k8s-master1 ~]# kubectl get pods | grep mysql 50mysql-pod 1/1 Running 51 52[root@k8s-master1 ~]# kubectl exec mysql-pod -it -c mysql -- /bin/sh 53/ # printenv | grep log 54log_bin=1 55/ # printenv | grep lower 56lower_bin=1 57
16.3.2 方式2:环境变量envfrom注入
谨慎使用 envFrom:
- 仅当确认 ConfigMap 所有键均需导入且命名合法时使用
- 建议配合 prefix 避免命名冲突:
1]# kubectl explain pod.spec.containers.env 2 name <string> -required- 3 value <string> 4 valueFrom <EnvVarSource> 5# value 和 valueFrom 不能同时使用,二者互斥。 6 7[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom 8 configMapKeyRef <ConfigMapKeySelector> 9 fieldRef <ObjectFieldSelector> 10 resourceFieldRef <ResourceFieldSelector> 11 secretKeyRef <SecretKeySelector> 12 13[root@k8s-master1 ~]# kubectl explain pod.spec.containers.envFrom 14 configMapRef <ConfigMapEnvSource> 15 prefix <string> 16 secretRef <SecretEnvSource> 17
1[root@k8s-master1 ~]# vim cmkr-sql-cm.yaml 2apiVersion: v1 3kind: ConfigMap 4metadata: 5 name: cmkr-sql 6 labels: 7 app: mysql 8data: 9 log: "1" 10 lower: "1" 11 12[root@k8s-master1 ~]# kubectl apply -f cmkr-sql-cm.yaml 13[root@k8s-master1 ~]# kubectl get cm 14cmkr-sql 2 27s 15 16[root@k8s-master1 ~]# vim envfrom-mysql-pod.yaml 17apiVersion: v1 18kind: Pod 19metadata: 20 name: mysql-pod 21spec: 22 containers: 23 - name: mysql 24 image: docker.io/library/busybox:1.28 25 imagePullPolicy: IfNotPresent 26 command: ["/bin/sh","-c","sleep 3600"] 27 envFrom: 28 - configMapRef: 29 name: cmkr-sql 30 31[root@k8s-master1 ~]# kubectl apply -f envfrom-mysql-pod.yaml 32[root@k8s-master1 ~]# kubectl get pods 33mysql-pod 1/1 Running 0 23s 34 35[root@k8s-master1 ~]# kubectl exec -it mysql-pod -c mysql -- /bin/sh 36/ # printenv | grep log 37log=1 38/ # printenv | grep lower 39lower=1 40
16.3.3 方式3:volume卷挂载注入
1[root@k8s-master1 ~]# vim volume-sql-cm.yaml 2apiVersion: v1 3kind: ConfigMap 4metadata: 5 name: volume-sql 6 labels: 7 app: mysql 8data: 9 log: "1" 10 lower: "1" 11 my.cnf: | 12 [HelloWord] 13 xixixixixi 14 15[root@k8s-master1 ~]# kubectl apply -f volme-sql-cm.yaml 16[root@k8s-master1 ~]# kubectl get cm 17volume-sql 3 3s 18 19[root@k8s-master1 ~]# kubectl describe cm volume-sql 20log: 21---- 221 23 24lower: 25---- 261 27 28my.cnf: 29---- 30[HelloWord] 31xixixixixi 32 33[root@k8s-master1 ~]# vim volume-cm-pod.yaml 34apiVersion: v1 35kind: Pod 36metadata: 37 name: volume-cm-pod 38spec: 39 containers: 40 - name: buxybox 41 image: docker.io/library/busybox:1.28 42 imagePullPolicy: IfNotPresent 43 command: ["/bin/sh","-c","sleep 3600"] 44 volumeMounts: 45 - name: vol-cm 46 mountPath: /tmp/config 47 volumes: 48 - name: vol-cm 49 configMap: 50 name: volume-sql 51 52[root@k8s-master1 ~]# kubectl apply -f volume-cm-pod.yaml 53[root@k8s-master1 ~]# kubectl get pods 54volume-cm-pod 1/1 Running 0 4s 55 56[root@k8s-master1 ~]# kubectl exec -it volume-cm-pod -c buxybox -- /bin/sh 57/ # ls -l /tmp/config/ 58total 0 59lrwxrwxrwx 1 root root 10 Jan 29 01:26 log -> ..data/log 60lrwxrwxrwx 1 root root 12 Jan 29 01:26 lower -> ..data/lower 61lrwxrwxrwx 1 root root 13 Jan 29 01:26 my.cnf -> ..data/my.cnf 62 63/ # cat /tmp/config/log 641/ # 65/ # cat /tmp/config/lower 661/ # 67/ # cat /tmp/config/my.cnf 68[HelloWord] 69xixixixixi 70/ # 71
16.4 ConfigMap 热更新
volume卷挂载注入的方式才可
1[root@k8s-master1 ~]# kubectl edit cm volume-sql 2...... 3apiVersion: v1 4data: 5 log: "6" # 1 --> 6 6 lower: "123123" # 2 --> 123123 7...... 8:wq # 保存退出 9 10[root@k8s-master1 ~]# kubectl get pods 11volume-cm-pod 1/1 Running 0 7m32s 12 13# 进入容器查看是否改变 14[root@k8s-master1 ~]# kubectl exec -it volume-cm-pod -- /bin/sh 15/ # cat /tmp/config/log 166/ # 17/ # cat /tmp/config/lower 18123123/ # 19/ # 20
注意:
- 更新 ConfigMap 后:
- 使用该 ConfigMap 挂载的 Env 不会同步更新
- 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
《【Kubernetes专项】K8s 配置管理中心 ConfigMap 实现微服务配置管理》 是转载文章,点击查看原文。