【Kubernetes专项】K8s 配置管理中心 ConfigMap 实现微服务配置管理

十六、K8s 配置管理中心 ConfigMap 实现微服务配置管理

16.1 ConfigMap 相关概念及cm字段

16.1.1 ConfigMap 概述

​ Configmap 是 k8s 中的资源对象,用于保存非机密性的配置的,数据可以用 key/value键值对 的形式保存,也可通过 文件 的形式保存。

  1. Configmap 是 k8s 中的资源, 相当于配置文件,可以有一个或者多个 Configmap;
  2. Configmap 可以做成 Volume,k8s pod 启动之后,通过 volume 形式映射到容器内部指定目录上;
  3. 容器中应用程序按照原有方式读取容器特定目录上的配置文件;
  4. 在容器看来,配置文件就像是打包在容器内部特定目录,整个过程对应用没有任何侵入。

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字段
bash 复制代码
]# kubectl explain cm
  apiVersion    <string>
  kind  <string>
  metadata      <ObjectMeta>
  
  data  <map[string]string>  
  # 以键值对的形式存储非二进制配置数据(适用于普通文本配置)
  
  binaryData    <map[string]string>
  #	以Base64编码的形式存储二进制数据(适用于图片、证书等非文本文件) 

  immutable		<boolean>
  # 将 ConfigMap 标记为不可变,默认为 true,反之为 false
  
# `data` `binaryData`两者不可包含相同的键名,否则创建时会报错

16.2 ConfigMap 创建方式

16.2.1 方式1:命令行直接创建
bash 复制代码
[root@k8s-master1 ~]# kubectl create configmap tomcat-cm --from-literal=tomcat_port=8080 --from-literal=server_name=tomcat

[root@k8s-master1 ~]# kubectl get cm
tomcat-cm          2      6s

[root@k8s-master1 ~]# kubectl describe cm tomcat-cm
server_name:
----
tomcat

tomcat_port:
----
8080
16.2.2 方式2:命令行指定文件创建
bash 复制代码
[root@k8s-master1 ~]# kubectl create cm nginx-vhosts-conf --from-file=nginx=./nginx_vhosts.conf

[root@k8s-master1 ~]# kubectl get cm
nginx-vhosts-conf   1      14s

[root@k8s-master1 ~]# kubectl describe cm nginx-vhosts-conf
nginx:
----
server {
  listen       80;
  server_name  www.kaser.com;
  root         /usr/local/nginx/conf/conf.d/
}
16.2.3 方式3:命令行指定目录创建
bash 复制代码
[root@k8s-master1 ~]# mkdir cm_test
[root@k8s-master1 ~]# cd cm_test/
[root@k8s-master1 cm_test]# echo "server-id=1" > sql_master.cnf
[root@k8s-master1 cm_test]# echo "server-id=2" > sql_slave.cnf
[root@k8s-master1 cm_test]# ls
sql_master.cnf  sql_slave.cnf


[root@k8s-master1 cm_test]# kubectl create cm sql-config-dir --from-file=/root/cm_test

[root@k8s-master1 cm_test]# kubectl get cm
sql-config-dir      2      26s

[root@k8s-master1 cm_test]# kubectl describe cm sql-config-dir
sql_master.cnf:
----
server-id=1


sql_slave.cnf:
----
server-id=2
16.2.4 方式4:编写 yaml 文件创建
bash 复制代码
[root@k8s-master1 ~]# vim mysql-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  test_sql_master.cnf: |		# 写文件,后面必须要有 |
    [mysqld]
    log-bin
    log_bin_trust_function_creators=1
    lower_case_table_names=1
  test_sql_slave.cnf: |
    [mysqld]
    super-read-only
    log_bin_trust_function_creators=1
    
[root@k8s-master1 ~]# kubectl apply -f mysql-cm.yaml
[root@k8s-master1 ~]# kubectl get cm
mysql               2      6s

[root@k8s-master1 ~]# kubectl describe cm mysql
test_sql_master.cnf:
----
[mysqld]
log-bin
log_bin_trust_function_creators=1
lower_case_table_names=1


test_sql_slave.cnf:
----
[mysqld]
super-read-only
log_bin_trust_function_creators=1

16.3 ConfigMap 使用方式

16.3.1 方式1:环境变量configMapKeyRef注入

优先使用 env + valueFrom

  • 显式声明依赖的配置项,提高可读性和可维护性
  • 避免因 ConfigMap 新增无关键导致意外行为
bash 复制代码
]# kubectl explain pod.spec.containers.env
  name  <string> -required-
  value <string>
  valueFrom     <EnvVarSource>
# value 和 valueFrom 不能同时使用,二者互斥。

[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom
  configMapKeyRef       <ConfigMapKeySelector>
  fieldRef      <ObjectFieldSelector>
  resourceFieldRef      <ResourceFieldSelector>
  secretKeyRef  <SecretKeySelector>
  
[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom.configMapKeyRef
  key   <string> -required-
  name  <string>
  optional      <boolean>
  # 是否可选:
  # • false(默认):ConfigMap 或键不存在时,Pod 创建失败
  # • true:ConfigMap/键不存在时忽略该环境变量,Pod 仍可创建
bash 复制代码
[root@k8s-master1 ~]# vim cmkr-sql-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: cmkr-sql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"

[root@k8s-master1 ~]# kubectl apply -f cmkr-sql-cm.yaml
[root@k8s-master1 ~]# kubectl get cm
cmkr-sql            2      27s

[root@k8s-master1 ~]# kubectl describe cm cmkr-sql
log:
----
1

lower:
----
1

[root@k8s-master1 ~]# vim mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
spec:
  containers:
    - name: mysql
      image: docker.io/library/busybox:1.28
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","sleep 3600"]
      env:
        - name: log_bin
          valueFrom:
            configMapKeyRef:
              name: cmkr-sql
              key: log
        - name: lower_bin
          valueFrom:
            configMapKeyRef:
              name: cmkr-sql
              key: lower

[root@k8s-master1 ~]# kubectl apply -f mysql-pod.yaml
[root@k8s-master1 ~]# kubectl get pods | grep mysql
mysql-pod                          1/1     Running

[root@k8s-master1 ~]# kubectl exec  mysql-pod -it -c mysql -- /bin/sh
/ # printenv | grep log
log_bin=1
/ # printenv | grep lower
lower_bin=1
16.3.2 方式2:环境变量envfrom注入

谨慎使用 envFrom:

  • 仅当确认 ConfigMap 所有键均需导入且命名合法时使用
  • 建议配合 prefix 避免命名冲突:
bash 复制代码
]# kubectl explain pod.spec.containers.env
  name  <string> -required-
  value <string>
  valueFrom     <EnvVarSource>
# value 和 valueFrom 不能同时使用,二者互斥。

[root@k8s-master1 ~]# kubectl explain pod.spec.containers.env.valueFrom
  configMapKeyRef       <ConfigMapKeySelector>
  fieldRef      <ObjectFieldSelector>
  resourceFieldRef      <ResourceFieldSelector>
  secretKeyRef  <SecretKeySelector>
  
[root@k8s-master1 ~]# kubectl explain pod.spec.containers.envFrom
  configMapRef  <ConfigMapEnvSource>
  prefix        <string>
  secretRef     <SecretEnvSource>
bash 复制代码
[root@k8s-master1 ~]# vim cmkr-sql-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: cmkr-sql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"

[root@k8s-master1 ~]# kubectl apply -f cmkr-sql-cm.yaml
[root@k8s-master1 ~]# kubectl get cm
cmkr-sql            2      27s

[root@k8s-master1 ~]# vim envfrom-mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
spec:
  containers:
    - name: mysql
      image: docker.io/library/busybox:1.28
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","sleep 3600"]
      envFrom:
        - configMapRef:
            name: cmkr-sql

[root@k8s-master1 ~]# kubectl apply -f envfrom-mysql-pod.yaml
[root@k8s-master1 ~]# kubectl get pods
mysql-pod                          1/1     Running   0          23s

[root@k8s-master1 ~]# kubectl exec -it mysql-pod -c mysql -- /bin/sh
/ # printenv | grep log
log=1
/ # printenv | grep lower
lower=1
16.3.3 方式3:volume卷挂载注入
bash 复制代码
[root@k8s-master1 ~]# vim volume-sql-cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: volume-sql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"
  my.cnf: |
    [HelloWord]
    xixixixixi

[root@k8s-master1 ~]# kubectl apply -f volme-sql-cm.yaml
[root@k8s-master1 ~]# kubectl get cm
volume-sql         3      3s

[root@k8s-master1 ~]# kubectl describe cm volume-sql
log:
----
1

lower:
----
1

my.cnf:
----
[HelloWord]
xixixixixi

[root@k8s-master1 ~]# vim volume-cm-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: volume-cm-pod
spec:
  containers:
    - name: buxybox
      image: docker.io/library/busybox:1.28
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","sleep 3600"]
      volumeMounts:
        - name: vol-cm
          mountPath: /tmp/config
  volumes:
    - name: vol-cm
      configMap:
        name: volume-sql

[root@k8s-master1 ~]# kubectl apply -f volume-cm-pod.yaml
[root@k8s-master1 ~]# kubectl get pods
volume-cm-pod                      1/1     Running   0          4s

[root@k8s-master1 ~]# kubectl exec -it volume-cm-pod -c buxybox -- /bin/sh
/ # ls -l /tmp/config/
total 0
lrwxrwxrwx    1 root     root            10 Jan 29 01:26 log -> ..data/log
lrwxrwxrwx    1 root     root            12 Jan 29 01:26 lower -> ..data/lower
lrwxrwxrwx    1 root     root            13 Jan 29 01:26 my.cnf -> ..data/my.cnf

/ # cat /tmp/config/log
1/ #
/ # cat /tmp/config/lower
1/ #
/ # cat /tmp/config/my.cnf
[HelloWord]
xixixixixi
/ #

16.4 ConfigMap 热更新

volume卷挂载注入的方式才可

bash 复制代码
[root@k8s-master1 ~]# kubectl edit cm volume-sql
......
apiVersion: v1
data:
  log: "6"			# 1 --> 6
  lower: "123123"	# 2 --> 123123
......
:wq	# 保存退出

[root@k8s-master1 ~]# kubectl get pods
volume-cm-pod                      1/1     Running   0          7m32s

# 进入容器查看是否改变
[root@k8s-master1 ~]# kubectl exec -it volume-cm-pod -- /bin/sh
/ # cat /tmp/config/log
6/ #
/ # cat /tmp/config/lower
123123/ #
/ #

注意:

  • 更新 ConfigMap 后:
    • 使用该 ConfigMap 挂载的 Env 不会同步更新
    • 使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新
相关推荐
only_Klein2 小时前
kubernetes集群下的分布式存储方案-ceph
ceph·kubernetes·分布式存储
小浣熊喜欢揍臭臭2 小时前
qiankun微服务搭建之【react+nextJs】
微服务·react
牛奶咖啡132 小时前
Prometheus+Grafana构建云原生分布式监控系统(十六) _基于Alertmanager的告警机制(一)
云原生·prometheus·prometheus告警整合·prometheus告警配置·prometheus告警规则·prometheus触发告警·告警规则配置实践
为什么不问问神奇的海螺呢丶2 小时前
n9e categraf k8s监控配置 -kube-state-metrics
java·容器·kubernetes
EverydayJoy^v^10 小时前
RH134学习进程——十二.运行容器(1)
linux·运维·容器
java_logo11 小时前
OpenProject Docker 容器化部署指南:从快速启动到生产环境配置
docker·容器·openproject·openproject部署·openproject部署手册·openproject部署方案·openproject部署教程
cg_ssh14 小时前
Docker 下启动 Nacos 3.1.1 单机模式
运维·docker·容器
修己xj14 小时前
使用 Docker 部署 SQL Server 并导入 .mdb 文件的完整指南
运维·docker·容器
爱内卷的学霸一枚18 小时前
现代微服务架构实践:从设计到部署的深度解析
windows·微服务·架构