深入玩转K8S之如何实现外挂配置管理—ConfigMap

时间:2022-06-19
本文章向大家介绍深入玩转K8S之如何实现外挂配置管理—ConfigMap,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

还是老规矩先来了解下什么是ConfigMap,那么在了解ConifigMap的同时也得了解下另一个概念就是Secret。可能会有人说,你这不是在讲ConfigMap么,怎么还要扯Secret,别着急等我慢慢道来,那为什么要有这两个东西呢?因为在实际应用的过程中,我们经常会需要传一些配置给我们的应用,比如配置文件变更啊、用户名密码啊等等之类的。可能这个时候就会有童鞋说了我们有好多种方案可以实现啊,比如:

1.我们可以直接在打包镜像的时候写在应用配置文件里面。

2.我们可以在配置文件里面通过env环境变量传入。

3.我们可以在应用启动的时候去数据库或者某个特定的地方拿。

确实可以实现,但每个方案的弊端也显而易见,比如:

1.这种方式的坏处显而易见而且非常明显,几乎是绑死了配置,不便于后续操作。

2.这样的话我们要修改env就必须去修改yaml文件,而且需要重启所有的Container才行。

3.第三个方案实现起来麻烦,另外如果配置的地方变了怎么办?这个跟第一种方式有点类似,太过于锁死。

当然还有别的方案,但是各种方案都有各自的问题,而且还有一个问题就是,如果说我的一个配置,是要多个应用一起使用的,以上除了第三种方案,都没办法进行配置的共享,就是说我如果要改配置的话,那得一个一个手动改。假如我们有100个应用,就得改100份配置,以此类推……

Kubernetes对这个问题提供了一个很好的解决方案,就是用ConfigMap和Secret。前面说了那么多那么究竟这俩是什么概念,相信聪明的童鞋已经知道是干什么的了。

根据字面意思就可以理解到,ConfigMap是存储通用的配置变量的,类似于配置文件,使用户可以将分布式系统中用于不同模块的环境变量统一到一个对象中管理;而它与配置文件的区别在于它是存在集群的“环境”中的,并且支持K8S集群中所有通用的操作调用方式。而Secret呢就是存储一些比较敏感的信息,比如:密码、密钥之类的信息。

从数据角度来看,ConfigMap的类型只是键值组,用于存储被Pod或者其他资源对象(如RC)访问的信息。这与secret的设计理念有异曲同工之妙,主要区别在于ConfigMap通常不用于存储敏感信息,而只存储简单的文本信息。

本文呢我们拿Myql举例来看看如何实现ConfigMap也就是说配置文件与Container解耦的,创建ConfigMap的方式有两种,一种是通过yaml文件来创建,另一种是通过kubectl直接在命令行下创建。

由于是测试我这里随便找了一个my.cnf,比较简洁。

[root@k8smaster configmap]# cat mysqld.cnf 
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysql]
no-auto-rehash
 
[mysqld]
user = mysql
port = 3306
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
 
[mysqld_safe]
log-error= /var/log/mysql/mysql_oldboy.err
pid-file = /var/run/mysqld/mysqld.pid

注意:

这个名字为什么是mysqld.cnf,是因为容器里读取的配置文件名字就是这个,最少修改的原则,直接取代覆盖,还用原名字。

用这个文件创建ConfigMap

[root@k8smaster configmap]# kubectl create configmap mysql-config --from-file=mysqld.cnf
configmap "mysql-config" created

有两种方式让pod使用,第一种是环境变量或参数,第二种是文件挂载。我们今天以Volume形式挂载进Mysql容器,并读取这个文件启动,挂载到哪里呢?肯定是挂载到默认的存放配置文件处,并取代它。比如Mysql,它的配置文件就在/etc/mysql/mysql.conf.d/。

[root@k8smaster configmap]# cat mysql-svc2.yml 
apiVersion: v1
kind: Service
metadata:
  name: mysql2
spec:
  ports:
  - port: 3306
  selector:
    app: mysql1
 
---
apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: mysql-t1
spec:
  selector:
    matchLabels:
      app: mysql1
  template:
      metadata:
        labels:
          app: mysql1
      spec:
        containers:
        - image: mysql:5.7
          name: mysql-t
          env:
          - name: MYSQL_ROOT_PASSWORD
            valueFrom:
              secretKeyRef:
                name: mysecret
                key: password
          ports:
          - containerPort: 3306
            name: mysql
          volumeMounts:
          - name: mysql-t1
            mountPath: /etc/mysql/mysql.conf.d    ##注意路径
        volumes:
          - name: mysql-t1
            configMap:
              name: mysql-config

注意:

当ConfigMap以数据卷的形式挂载进Pod时,更新ConfigMap(或删掉重建ConfigMap),Pod内挂载的配置信息会热更新,但使用环境变量方式加载到pod,则不会自动更新。

[root@k8smaster configmap]# kubectl apply -f mysql-svc2.yml 
service "mysql2" created
deployment.apps "mysql-t1" created

最后我们来验证下是否把镜像里面默认的配置文件换成了我们刚才修改的配置文件。

[root@k8snode1 ~]# docker ps | grep mysql
23c3846564ec   docker.io/mysql@sha256:e8f85df0b02606e573ad3dfa31ad6dd1d659ad72ea927f8f307b28fa19ab9cc5     "docker-entrypoint..."   4 minutes ago       Up 4 minutes
[root@k8snode1 ~]# docker exec -it 23c3846564ec bash
root@mysql-t1-6fbf57db97-dvh42:/# 
root@mysql-t1-6fbf57db97-dvh42:/#
root@mysql-t1-6fbf57db97-dvh42:/# cd /etc/mysql/mysql.conf.d/
root@mysql-t1-6fbf57db97-dvh42:/etc/mysql/mysql.conf.d# ls
mysqld.cnf
root@mysql-t1-6fbf57db97-dvh42:/etc/mysql/mysql.conf.d# cat mysqld.cnf 
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysql]
no-auto-rehash
 
[mysqld]
user = mysql
port = 3306
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
 
[mysqld_safe]
log-error= /var/log/mysql/mysql_oldboy.err
pid-file = /var/run/mysqld/mysqld.pid

可以看到已经覆盖原文件。好了,本文关于ConfigMap就介绍到这里,关于另外一种方式,可以自己琢磨下,这里就不在赘述了,后续有机会可以在介绍下。

本文参考了:

https://blog.51cto.com/goome/2155871

https://www.kubernetes.org.cn/3400.html