深入玩转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
- 一行代码调用实现带字段选取+条件判断+排序+分页功能的增强ORM框架
- PDF.NET数据开发框架实体类操作实例
- 利用Burp Suite对OWASP Juice Shop进行渗透测试
- Java同步问题面试知识学习
- Android UI控件系列:LinearLayout(线性布局)
- 使用操作符重载,生成ORM实体类的SQL条件语句
- Dance In Heap(四):一些堆利用的方法(下)
- Mac系统的Proton恶意软件:卷!土!重!来!
- Erlang语言学习入门
- Android使用Ant进行apk多渠道打包
- Dance In Heap(三):一些堆利用的方法(中)
- Android性能优化篇:使用软引用和弱引用
- 使用泛型委托,构筑最快的通用属性访问器
- 记录容易忘记的方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- TensorFlow基础:常量
- 如何在Python中优雅地使用进度条?
- 绝了!这款工具让SpringBoot不再需要Controller、Service、DAO、Mapper!
- 「数据仓库架构」数据仓库的三种模式建模技术
- 设计模式实战-空对象模式,你肯定不知道,但是项目中会常用到到
- Go 开发十种常犯错误
- SpringBoot缓存应用实践
- 为什么应该使用 Go module proxy
- 谁能想到,我给技术总监“上了一课”
- 设计模式速览
- 序列模型——吴恩达深度学习课程笔记(五)
- 30分钟学会pyecharts数据可视化
- 用Keras从零开始6步骤训练神经网络
- Keras结构化数据预处理范例——Titanic生存预测
- 从原理上搞懂如何设置线程池参数大小?