【云原生 | Kubernetes 实战】16、K8s 配置管理中心 ConfigMap 实现微服务配置管理

导读:本篇文章讲解 【云原生 | Kubernetes 实战】16、K8s 配置管理中心 ConfigMap 实现微服务配置管理,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

目录

一、ConfigMap 概述

1.1  什么是 ConfigMap?

1.2  ConfigMap 能解决哪些问题?

1.3 ConfigMap 应用场景

1.4 局限性

二、ConfigMap 创建方法

2.1 根据字面值创建 ConfigMap

2.2 基于文件创建 ConfigMap 

2.3 基于目录创建 ConfigMap

2.4 编写 configmap 资源清单 YAML 文件 

三、使用 ConfigMap

3.1 通过环境变量引入:使用 configMapKeyRef 

3.2 通过环境变量引入:使用 envfrom

3.3 把 configmap 做成 volume 挂载到 pod 

四、ConfigMap 热更新 


一、ConfigMap 概述

1.1  什么是 ConfigMap?

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

1.2  ConfigMap 能解决哪些问题?

        我们在部署服务的时候,每个服务都有自己的配置文件,如果一台服务器上部署多个服务:nginx、tomcat、apache 等,那么这些配置都存在这个节点上,假如一台服务器不能满足线上高并发的要求,需要对服务器扩容,扩容之后的服务器还是需要部署多个服务:nginx、tomcat、apache,新增加的服务器上还是要管理这些服务的配置,如果有一个服务出现问题,需要修改配置文件,每台物理节点上的配置都需要修改,这种方式肯定满足不了线上大批量的配置变更要求。 所以,k8s 中引入了 ConfigMap 资源对象,可以当成 volume 挂载到 pod 中,实现统一的配置管理。

【云原生 | Kubernetes 实战】16、K8s 配置管理中心 ConfigMap 实现微服务配置管理

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

1.3 ConfigMap 应用场景

        使用 k8s 部署应用,当你将应用配置写进代码中,更新配置时也需要打包镜像,ConfigMap 可以将配置信息和 docker 镜像解耦,以便实现镜像的可移植性和可复用性,因为一个 ConfigMap 其实就是一系列配置信息的集合,可直接注入到 Pod 中给容器使用。ConfigMap 注入方式有两种,一种将 ConfigMap 做为存储卷,一种是将 ConfigMap 通过 env 中 configMapKeyRef 注入到容器中。

        使用微服务架构的话,存在多个服务共用配置的情况,如果每个服务中单独一份配置的话,那么更新配置就很麻烦,使用 ConfigMap 可以友好的进行配置共享。

1.4 局限性

        ConfigMap 在设计上不是用来保存大量数据的。在 ConfigMap 中保存的数据不可超过1 MiB。如果你需要保存超出此尺寸限制的数据,可以考虑挂载存储卷或者使用独立的数据库或者文件服务。

ConfigMap 概念官方参考文档:ConfigMap | Kubernetes

二、ConfigMap 创建方法

        你可以使用 kubectl create configmap 或者在 kustomization.yaml 中的 ConfigMap 生成器来创建 ConfigMap。注意,kubectl 从 1.14 版本开始支持 kustomization.yaml

使用 kubectl create configmap 创建 ConfigMap:

你可以使用 kubectl create configmap 命令基于目录、 文件或者字面值来创建 ConfigMap:

kubectl create configmap <映射名称> <数据源>

        其中,<映射名称> 是为 ConfigMap 指定的名称,<数据源> 是要从中提取数据的目录、 文件或者字面值。ConfigMap 对象的名称必须是合法的 DNS 子域名.

        在你基于文件来创建 ConfigMap 时,<数据源> 中的键名默认取自文件的基本名, 而对应的值则默认为文件的内容。

你可以使用 kubectl describe 或者 kubectl get 获取有关 ConfigMap 的信息。

2.1 根据字面值创建 ConfigMap

        你可以将 kubectl create configmap 与 --from-literal 参数一起使用, 通过命令行定义文字值:

# 查看帮助命令
[root@k8s-master01 ~]# kubectl create configmap --help
······
Usage:
  kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run=server|client|none]
[options]

# 创建 configmap
[root@k8s-master01 ~]# kubectl create configmap tomcat-config --from-literal=tomcat_port=8080 --from-literal=server_name=myapp.tomcat.com

[root@k8s-master01 ~]# kubectl get cm
NAME               DATA   AGE
kube-root-ca.crt   1      59d
tomcat-config      2      39s

# 显示 ConfigMap 的详细信息:命令行中提供的每对键值在 ConfigMap 的 data 部分中均表示为单独的条目。
[root@k8s-master01 ~]# kubectl describe configmaps tomcat-config 
Name:         tomcat-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
server_name:
----
myapp.tomcat.com
tomcat_port:
----
8080

BinaryData
====

Events:  <none>

2.2 基于文件创建 ConfigMap 

你可以使用 kubectl create configmap 基于单个文件或多个文件创建 ConfigMap。

[root@k8s-master01 ~]# mkdir configmap
[root@k8s-master01 ~]# cd configmap/
[root@k8s-master01 configmap]# vim nginx.yaml
server {
  listen 80;
  server_name www.nginx.com;
  root /home/nginx/www/
}

# 定义一个 key 是 www,值是 nginx.yaml 中的内容
[root@k8s-master01 configmap]# kubectl create configmap www-nginx --from-file=www=./nginx.yaml 
configmap/www-nginx created

[root@k8s-master01 configmap]# kubectl describe configmaps www-nginx 
Name:         www-nginx
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
www:
----
server {
  listen 80;
  server_name www.nginx.com;
  root /home/nginx/www/
}



BinaryData
====

Events:  <none>

[root@k8s-master01 configmap]# kubectl get configmaps www-nginx 
NAME        DATA   AGE
www-nginx   1      34s

2.3 基于目录创建 ConfigMap

        你可以使用 kubectl create configmap 基于同一目录中的多个文件创建 ConfigMap。 当你基于目录来创建 ConfigMap 时,kubectl 识别目录下基本名可以作为合法键名的文件, 并将这些文件打包到新的 ConfigMap 中。普通文件之外的所有目录项都会被忽略 (例如:子目录、符号链接、设备、管道等等)。

例如:

# 创建本地目录
[root@k8s-master01 ~]# mkdir -pv configure-pod-container/configmap/

# 创建示例文件到 `configure-pod-container/configmap/` 目录
[root@k8s-master01 ~]# cd configure-pod-container/configmap/
[root@k8s-master01 configmap]# echo "server-id=1" > my-server.conf
[root@k8s-master01 configmap]# echo "server-id=2" > my-slave.conf

# 创建 configmap
[root@k8s-master01 configmap]# kubectl create configmap mysql-config --from-file=/root/configure-pod-container/configmap/

        以上命令将 configure-pod-container/configmap 目录下的所有文件,也就是 my-server.conf 和 my-slave.conf 打包到 mysql-config ConfigMap 中。你可以使用下面的命令显示 ConfigMap 的详细信息:

[root@k8s-master01 configmap]# kubectl describe configmaps mysql-config 
Name:         mysql-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
my-server.conf:
----
server-id=1

my-slave.conf:
----
server-id=2


BinaryData
====

Events:  <none>

configure-pod-container/configmap/ 目录中的 server.conf 和 my-slave.conf 文件出现在 ConfigMap 的 data 部分。

创建 ConfigMap 官方参考文档: 配置 Pod 使用 ConfigMap | Kubernetes

2.4 编写 configmap 资源清单 YAML 文件 

# 查看帮助命令
[root@k8s-master01 ~]# kubectl explain configmap

# 创建 configmap 资源文件
[root@k8s-master01 configmap]# vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  master.cnf: |         # master.cnf 是文件名称,“ | ” 符号代表文件内容有多行
    [mysqld]
    log-bin
    log_bin_trust_function_creators=1
    lower_case_table_names=1
  slave.cnf: |
    [mysqld]
    super-read-only
    log_bin_trust_function_creators=1

# 创建资源
[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 
configmap/mysql created

# 查看是否成功创建
[root@k8s-master01 configmap]# kubectl get configmaps mysql
NAME    DATA   AGE
mysql   2      14s

编写 configmap 资源清单官方参考文档:ConfigMap | Kubernetes 

三、使用 ConfigMap

你可以使用四种方式来使用 ConfigMap 配置 Pod 中的容器:

  1. 在容器命令和参数内
  2. 容器的环境变量(常用)
  3. 在只读卷里面添加一个文件,让应用来读取(常用)
  4. 编写代码在 Pod 中运行,使用 Kubernetes API 来读取 ConfigMap

        这些不同的方法适用于不同的数据使用方式。 对前三个方法,kubelet 使用 ConfigMap 中的数据在 Pod 中启动容器。

        第四种方法意味着你必须编写代码才能读取 ConfigMap 和它的数据。然而, 由于你是直接使用 Kubernetes API,因此只要 ConfigMap 发生更改, 你的应用就能够通过订阅来获取更新,并且在这样的情况发生的时候做出反应。 通过直接进入 Kubernetes API,这个技术也可以让你能够获取到不同的名字空间里的 ConfigMap。

3.1 通过环境变量引入:使用 configMapKeyRef 

# 创建一个存储 mysql 配置的 configmap
[root@k8s-master01 configmap]# vim mysql-configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"

[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 

# 创建 pod,引用 configmap 中的内容
[root@k8s-master01 configmap]# vim mysql-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    env:
    - name: log_bin           # 定义环境变量 log_bin
      valueFrom: 
        configMapKeyRef:      # ConfigMap 包含你要赋给 log_bin 的值
          name: mysql         # 指定 configmap 的名字
          key: log            # 指定 configmap 中的 key,即把 log=1 的值赋给 log_bin 变量
    - name: lower             # 定义环境变量 lower
      valueFrom:    
        configMapKeyRef:
          name: mysql
          key: lower
  restartPolicy: Never

[root@k8s-master01 configmap]# kubectl apply -f mysql-pod.yaml 
pod/mysql-pod created
[root@k8s-master01 configmap]# kubectl get pods
NAME                               READY   STATUS    RESTARTS        AGE
mysql-pod                          1/1     Running   0               20s

# 进入容器内部,Pod 的输出包含环境变量 log_bin=1,lower=1。
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod -- sh
/ # printenv 
log_bin=1
lower=1

使用单个 ConfigMap 中的数据定义容器环境变量:配置 Pod 使用 ConfigMap | Kubernetes 

3.2 通过环境变量引入:使用 envfrom

        使用 envFrom 将所有 ConfigMap 的数据定义为容器环境变量,ConfigMap 中的键成为 Pod 中的环境变量名称。

[root@k8s-master01 configmap]# vim mysql-pod-envfrom.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-envfrom
spec:
  containers:
  - name: mysql
    image: busybox
    imagePullPolicy: IfNotPresent
    command: [ "/bin/sh", "-c", "sleep 3600" ]
    envFrom: 
    - configMapRef:
       name: mysql     #指定configmap的名字
  restartPolicy: Never

[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-envfrom.yaml 
pod/mysql-pod-envfrom created
[root@k8s-master01 configmap]# kubectl get pods 
NAME                               READY   STATUS    RESTARTS        AGE
mysql-pod                          1/1     Running   0               15m
mysql-pod-envfrom                  1/1     Running   0               4s

# 进入容器内部查看环境变量
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-envfrom -- sh
/ # printenv 
lower=1
log=1

 将 ConfigMap 中的所有键值对配置为容器环境变量:配置 Pod 使用 ConfigMap | Kubernetes

3.3 把 configmap 做成 volume 挂载到 pod 

        在 Pod 规约的 volumes 部分下添加 ConfigMap 名称。 这会将 ConfigMap 数据添加到 volumeMounts.mountPath 所指定的目录 (在本例中为 /tmp/config)。 

# 创建 configmap
[root@k8s-master01 configmap]# vim mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mysql
  labels:
    app: mysql
data:
  log: "1"
  lower: "1"
  my.cnf: |
    [mysqld]
    hello sky

[root@k8s-master01 configmap]# kubectl apply -f mysql-configmap.yaml 

# 创建 pod,使用存储在 ConfigMap 中的数据填充卷
[root@k8s-master01 configmap]# vim mysql-pod-volume.yaml
apiVersion: v1
kind: Pod
metadata:
  name: mysql-pod-volume
spec:
  containers:
  - name: mysql
    image: busybox
    command: [ "/bin/sh","-c","ls /tmp/config" ]
    volumeMounts:
    - name: mysql-config          # 与 volumes.name 一致
      mountPath: /tmp/config      # 容器内挂载的目录
  volumes:
  - name: mysql-config            # 卷的名称
    configMap:
      name: mysql                 # configmap 的名称
  restartPolicy: Never

[root@k8s-master01 configmap]# kubectl apply -f mysql-pod-volume.yaml 
pod/mysql-pod-volume created

[root@k8s-master01 configmap]# kubectl get pods 
NAME                               READY   STATUS    RESTARTS       AGE
mysql-pod                          1/1     Running   0              55m
mysql-pod-envfrom                  1/1     Running   0              40m
mysql-pod-volume                   1/1     Running   0              5s

# 进入容器内部查看挂载卷下的数据,把 configmap 的内容变为文件存储了
[root@k8s-master01 configmap]# kubectl exec -it mysql-pod-volume -- sh
/ # cd /tmp/config/
/tmp/config # ls
log     lower   my.cnf
/tmp/config # cat log
1/tmp/config # cat lower
/tmp/config # cat my.cnf 
[mysqld]
hello sky

        在这里,ConfigMap 中键 log 的内容将挂载在 config-volume 卷中 /tmp/config/log 文件中。

使用存储在 ConfigMap 中的数据填充卷:配置 Pod 使用 ConfigMap | Kubernetes

四、ConfigMap 热更新 

        当某个已被挂载的 ConfigMap 被更新,所投射的内容最终也会被更新。 对于 Pod 已经启动之后所引用的、可选的 ConfigMap 才出现的情形, 这一动态更新现象也是适用的。

        kubelet 在每次周期性同步时都会检查已挂载的 ConfigMap 是否是最新的。 但是,它使用其本地的基于 TTL 的缓存来获取 ConfigMap 的当前值。 因此,从更新 ConfigMap 到将新键映射到 Pod 的总延迟可能等于 kubelet 同步周期 (默认 1 分钟) + ConfigMap 在 kubelet 中缓存的 TTL(默认 1 分钟)。

# 修改 configmap
[root@k8s-master01 ~]# kubectl edit configmaps mysql
apiVersion: v1
data:
  log: "2"        # 把 1 改为 2
  lower: "1"
······

# 进入挂载卷创建的 pod 容器内部查看 log 内容是否有变化
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-volume -- sh
/ # cd /tmp/config/
/tmp/config # ls
log     lower   my.cnf
/tmp/config # cat log
2/tmp/config # 

# 发现 log 值变成了 2,更新生效了

# 进入 env 创建的 pod 查看环境变量是否有变化
[root@k8s-master01 ~]# kubectl exec -it mysql-pod-envfrom -- sh
/ # printenv 
lower=1
log=1

# 没有变化

注意:更新 ConfigMap 后,使用该 ConfigMap 挂载的 Env 不会同步更新;使用该 ConfigMap 挂载的 Volume 中的数据需要一段时间(实测大概10秒)才能同步更新。

挂载的 ConfigMap 将被自动更新:https://kubernetes.io/zh-cn/docs/tasks/configure-pod-container/configure-pod-configmap/#mounted-configmaps-are-updated-automatically

上一篇文章:【云原生 | Kubernetes 实战】15、K8s 控制器 Daemonset 入门到企业实战应用

下一篇文章:【云原生 | Kubernetes 实战】17、K8s 配置管理中心 Secret 实现加密数据配置管理_Stars.Sky的博客-CSDN博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/74539.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!