基于kubernetes的集群镜像系统如何解决配置问题实现完美交付

469 阅读6分钟

集群镜像介绍

集群镜像是一个巨大的创新,把单机上的虚拟机镜像或者单个容器镜像抽象到了集群维度,未来

大部分软件都是分布式的,所以集群纬度的镜像可以更好的保障分布式应用整体使用的一致性。

阿里巴巴sealer就是一个非常优秀的实现,把k8s看成

操作系统给分布式应用制作镜像,比如docker只能给你制作单个mysql的镜像,而sealer可以帮助

你制作整个mysql高可用集群的镜像。

背景介绍

应用视角的计算机或者是云的发展历程就是一个不断屏蔽底层细节的过程,让用户只需要关心他应该关心的层面,屏蔽到哪一层取决于软件工作在哪一层。 举个例子:我想实现一个文件浏览器,查看系统中文件目录,那我仅需要关心系统调用而不用关心内核怎么实现,因为操作系统帮助我们很好的做了屏蔽。

然而并不在所有领域都像操作系统那样把我们不需要关心的细节都屏蔽的很好,比如应用依赖一个数据库,传统一点的方式,我们需要去在操作系统上安装启动数据库,每种操作系统上方式还不一样,其实应用想要的是数据库而却要关心这样一个不友好的实现过程。 好在有一些优化方案,比如制作虚拟机镜像,这样只要有一个带数据库的虚拟机镜像启动就可以满足应用的需求了,应用不再关心数据库下面的操作系统是什么,同理Docker也实现一样的能力。

但是假如应用依赖一个分布式数据库,对于分布式的软件,现有的方式几乎都显得力不从心(云服务除外)。虚拟机镜像解决不了分布式软件的开箱即用问题,云原生社区的人可能会说用kubernetes+helm,说的不错但是要知道一个现实是数千万开发者有多少是了解这些复杂技术的,更多的可能只是听过名词,应用想要的是一个分布式数据库,显然再关心下面一层的内容就是没有屏蔽好底层的细节。

集群镜像就可以从顶层使用者的视角把整个集群的能力封装到恰到好处

  • 比如你想去使用一SaaS软件,有了集群镜像你只需要run xxxSaaS才不需要关心它依赖了什么数据库用了什么消息队列。
  • 比如你想要一个分布式的mysql,有了集群镜像只需要run mysql-cluster,完全不用关心数据库是不是跑在容器中,kubernetes单词都不会拼写都没关系。
  • 比如你想起一个kubernetes集群,有了集群镜像只需要run kubernetes,也完全不用关心集群是跑在哪种操作系统上

如此做到你想关注哪一层就封装屏蔽到哪一层,集群镜像给你想要的结果而隐藏掉复杂的中间过程。熟悉Docker的同学一定有这样的感觉,我们现在run一个mysql的容器很少关心是from centos还是utuntu了,那未来基于集群镜像的能力我们去run一个分布式应用也不用关心它底层的云操作系统是什么了。

本文聊一下集群镜像里面配置应该如何进行管理。

kubernetes中的配置管理

大家都知道configmap中可以放用户自定义的一些配置文件,如果编排文件比较多的时候,实际生产我们

又只关心少量的参数,我们就可以通过helm这类工具把少量参数抽到values里面,在运行的时候只需要

关注values里面的少量参数就可以。

集群镜像配置管理

难点在于集群镜像是一个黑盒,那不可能说需要改个参数还得重新构建一下集群镜像,所以sealer巧妙利用overwrite的特性解决这一问题。

Clusterfile文件类似compose,是告诉你如何启动整个集群的,里面包含一些重要信息,比如使用的集群

镜像是什么,节点IP列表是什么等等。还有一部分就是用来定义覆盖镜像内部参数的一部分了:

apiVersion: sealer.aliyun.com/v1alpha1
kind: Cluster
metadata:
  name: my-cluster
spec:
  image: registry.cn-qingdao.aliyuncs.com/sealer-app/my-SAAS-all-inone:latest
  provider: BAREMETAL
---
apiVersion: sealer.aliyun.com/v1alpha1
kind: Config
metadata:
  name: mysql-config
spec:
  path: etc/mysql-valus.yaml
  data: |
       mysql-user: root
       mysql-passwd: xxx
...
---
apiVersion: sealer.aliyun.com/v1alpha1
kind: Config
metadata:
  name: redis-config
spec:
  path: etc/redis-valus.yaml
  data: |
       redis-user: root
       redis-passwd: xxx
...

如上,Config对象定义了文件名和文件内容,这样就可以覆盖掉集群镜像里面的默认配置。

sealer只做简单的覆盖,而不关心你的使用什么编排工具编排的,甚至是docker 的deamon.json

配置都可以通过这种方式配置,就非常的解耦和灵活。

构建镜像使用该配置:

FROM kuberentes:v1.19.9
...
CMD helm install mysql -f etc/mysql-config.yaml
CMD helm install mysql -f etc/redis-config.yaml

即可,这样sealer起起来的集群就可以注入应用的配置了。

少量配置

当然如果是少量配置可以通过“集群环境变量”的方式注入。

如我需要配置集群中dashboard的监听端口号,可以这样写你的编排文件:

...
kind: Service
apiVersion: v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
spec:
  ports:
    - port: 443
      targetPort: {{ DashBoardPort }}
  selector:
    k8s-app: kubernetes-dashboard
...

然后构建你的集群镜像,把这个模板文件拷贝到集群镜像中:

FROM kubernetes:1.16.9
COPY dashobard.yaml manifests/
CMD kubectl apply -f manifests/dashobard.yaml

运行时通过环境变量指定具体端口号:

sealer run -e DashBoardPort=8443 mydashboard:latest

也可以通过Clusterfile指定:

apiVersion: sealer.aliyun.com/v1alpha1
kind: Cluster
metadata:
  name: my-cluster
spec:
  image: mydashobard:latest
  provider: BAREMETAL
  env:
    DashBoardPort: 6443 # Specify a custom port here, which will be rendered into the mirrored yaml
  ssh:
    passwd:
    pk: xxx
...

总结

sealer 的配置管理部分的实现非常简单优雅,而且能满足大部分场景的需求,这样我们把不经常变更的东西打到集群镜像里面,把经常变更的东西通过Config对象注入文件。

特别一个saas应用通常有非常多的依赖,我们就可以把这些依赖的k8s docker 中间件 数据库和saas本身都 打到集群镜像里,把启动整个集群需要的少量参数暴露出来,就能帮助我们快速的复制集群。

这样玩专有云交付那都是小时级分钟级交付,大大提升企业的竞争力。

企业在多机房部署时也一样,构建一次,其它地方就可以快速批量复制,保障整个集群的一致性。

哪怕你只是想装一个k8s或者一个高可用mysql,都可以用sealer,因为镜像打包什么内容完全是由 Build的人决定的,我们也会构建好很多通用镜像供用户直接使用。 kubernetes一键安装

sealer集群整体打包!