作者 | fanux.中弈

什么是集群镜像

顾名思义和操作系统.iso镜像或者Docker镜像类似,集群镜像是用一定的技术手段把整个集群的所有文件以一定格式打成的一个资源包

对比单机和集群会发现一些有趣现象:

  • 单机有计算存储网络这些驱动,集群有CNI/CSI/CRI的实现像是集群的驱动
  • 操作系统单机有ubuntu centos这些,我们可以把kubernetes看成云操作系统
  • 单机上可以运行docker容器 或者是虚拟机,相当于一个运行的实例,集群也有运行着k8s的实例
  • 单机上的虚拟机镜像,docker镜像,所以随着云计算技术的发展,在集群这个纬度也会抽象出类似的镜像技术。

以基于kubernetes的集群镜像为例,里面包含了除操作系统以外的所有文件:

  • docker的依赖的二进制与systemd配置,dockerd的配置,以及一个私有的容器镜像仓库
  • kubernetes核心组件二进制,容器镜像,kubelet system配置等
  • 应用需要用到的yaml配置或者helm chart,以及应用的容器镜像
  • 其它脚本,配置与二进制工具等应用运行需要的所有依赖

同样集群镜像运行时肯定不是起一个容器或者装在一台机器上,而是这个镜像可以直接安装到多台服务器上或者直接对接到公有云的基础设施上。

sealer介绍

sealer是阿里巴巴开源的集群镜像的一个实现方式,项目地址: https://github.com/alibaba/se...
Docker解决了单个容器的镜像化问题,而sealer通过把整个集群打包,实现了分布式软件的Build Share Run!!!

试想我们要去交付一个SaaS应用,它依赖了mysql es redis这些数据库和中间件,所有东西都在kubernetes上进行编排,那如果没有集群镜像那要做如下操作:

  1. 找个工具去安装k8s集群
  2. helm install mysql es redis... 如果是离线环境可能还需要导入容器镜像
  3. kubectl apply yoursaas

看似好像也没那么复杂,但是其实从整个项目交付的角度来说是面向过程极易出错的

那现在如果现在提供另外一个方式只要一条命令解决上面的问题你会不会用?
sealer run your-saas-application-with-mysql-redis-es:latest
可以看到只需要run一个集群镜像整个集群就被整体交付了,细节复杂的操作都被屏蔽掉了,而且任何应用都可以使用相同的方式运行。那这个集群镜像是怎么来的呢:

我们只需要定义一个类似Dockerfile的文件我们称之为Kubefile, 然后执行一下build命令即可:
sealer build -t your-saas-application-with-mysql-redis-es:latest .
在单机和集群两个纬度进行一个对比就可以一目了然:

docker可以通过Dockerfile构建一个docker镜像,使用compose就可以运行容器。
sealer通过Kubefile构建一个CloudImage,使用Clusterfile启动整个集群。

快速体验

制作和运行一个kubernetes dashboard的集群镜像来体验一个完整的流程。
编写Kubefile

# 基础镜像,已经被制作好了里面包含所有的kubernetes启动相关的依赖
FROM registry.cn-qingdao.aliyuncs.com/sealer-io/cloudrootfs:v1.16.9-alpha.7
# 下载官方的dashboard yaml编排文件,已经下载了可以使用COPY指令
RUN wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
# 指定运行方式,可以使用kubectl helm kustomiz等
CMD kubectl apply -f recommended.yaml

build dashboard集群镜像
sealer build -t kubernetes-with-dashobard:latest .

运行集群镜像

# 下面命令会在服务器上安装k8s集群并apply dashboard, passwd指定服务器ssh密码,也可以使用密钥
sealer run kubernetes-with-dashobard:latest \
    --master 192.168.0.2,192.168.0.3,192.168.0.4 \
  --node 192.168.0.5,192.168.0.6 \
  --passwd xxx
# 检查pod
kubectl get pod -A |grep dashboard

把制作好的镜像推送到镜像仓库,兼容docker registry

sealer tag kubernetes-with-dashobard:latest docker.io/fanux/dashobard:latest
sealer push docker.io/fanux/dashobard:latest

这样就可以把制作好的镜像交付出去或者提供给别人复用。

使用场景

sealer具体能帮我们做哪些事呢,下面列举几个主要场景:

| 安装kubernetes与集群生命周期管理(升级/备份/恢复/伸缩)
这是个最简单的场景,不管你是需要在单机上安装个开发测试环境还是在生产环境中安装一个高可用集群,不管是裸机还是对接公有云,或者各种体系结构操作系统,都可以使用sealer进行安装,这里只安装kubernetes的话就选择个基础镜像即可。
与其它的安装工具对比,sealer优势在于:

  1. 简单到令人发指 sealer run 一条命令结束
  2. 速度快到令人窒息,3min装完6节点,可能你在使用别的工具还没下载完sealer就已经装完了,然而我们后续还有黑科技优化到2min甚至1min以内
  3. 兼容性与稳定性 兼容各种操作系统,支持x86 arm等体系结构
  4. 一致性设计,会让集群保持Clusterfile中的定义状态,以升级为例,只需要改一下Clusterfile中的版本号即可实现升级。

速度快是因为首先是golang实现,意味着我们可以很多很细致的地方做并发的处理,这相比ansible就有更多的优势了,而且还可以做更细致的错误处理,然后在镜像分发上抛弃了以前load的方式,后续在文件分发上也会做优化达到安装性能上的极致。

兼容性上,docker kubelet这里都采用了二进制+systemd安装核心组件全容器化,这样不用再去依赖yum apt这类感知操作系统的安装工具。 ARM和x86采用不同的镜像支持与sealer本身解耦开。 对公有云的适配也抽离单独模块进行实现,这里我们没去对接terraform原因还是为了性能,在我们的场景下terraform启动基础设施将近3min,而我们通过退避重试把基础设施启动优化到了30s以内,还有就是在集群镜像这个场景下是不需要这么复杂的基础设施管理能力的,我们不想让sealer变重也不想去依赖一个命令行工具。

一致性的设计理念是sealer中值得一提的,集群镜像与Clusterfile决定了集群是什么样子的,相同的镜像与Clusterfile就能run出个一样的集群出来。 变更要么变更Clusterfile如增加节点,改变节点规格,要么换镜像,换镜像的时候因为集群镜像也是分层结构,hash值不变的layer不会发生变更,而hash发生变化会帮助重新apply该层。

| 云原生生态软件的打包/安装等如prometheus mysql集群等
sealer run prometheus:latest 就可以创建一个带有prometheus的集群,或者在一个已有的集群中安装prometheus。
那么问题来了:和helm啥区别?

  1. sealer 不关心编排,更注重打包,上面例子prometheus可以用helm编排的,sealer会把chart和chart里面需要的所有容器镜像打包起来,这是在build的过程中通过黑科技做到的,因为build过程会像docker build一样起临时的kubernetes集群,然后我们就知道了集群依赖了哪些容器镜像,最后把这些容器镜像打包。
  2. 和kubernetes一起打包,拿了一个chart它未必能安装成功,比如使用了废弃的api版本,但是做成镜像把kubnernetes也包在一起了,只要build没问题,run就没问题,这点和docker把操作系统rootfs打包在一起异曲同工。
  3. 集成性,集群镜像更关注整个分布式应用集群整体打包,如把prometheus ELK mysql集群这些做成一个镜像服务与业务。

所以sealer与helm是协作关系,分工明确。
后续就可以在sealer的官方镜像仓库中找到这些通用的集群镜像然后直接使用。

| SaaS软件整体打包/交付 专有云离线交付
从分布式应用的视角看,通常从上往下,少则几个多则上百的组件,现有整体交付方式大多都是面向过程的,中间需要很多认为干预的事,sealer就可以把这些东西统统打包在一起进行一键交付。

可能你会问,我做个tar.gz再加个ansible脚本不也是能一样一键化嘛,那是肯定,就和docker镜像出现之前大家也通过tar.gz交付一样,你会发现标准和技术的出现解决和人与人之间的协作问题, 有了集群镜像你可以直接复用别人的成果,也能制作好东西做别人使用。

专有云场景就非常适合使用sealer,很多客户机房都是离线的,而集群镜像会把所有依赖打到镜像中。 只要镜像制作的好那所有局点都可以以相同的方式进行一键交付,获得极佳的一致性体验。

| 在公有云上实践上述场景
sealer自带对接公有云属性,很多情况下对接公有云会有更好的使用体验,比如安装集群时只需要指定服务器数量和规格而不用关心IP,伸缩直接修改Clusterfile中定义的数字即可。

技术原理简介

| 写时复制
集群镜像的存储也是通过写时复制的方式,这样做有两个好处,我们可以把一个集群中不同的分布式式软件打在不同的层,以实现复用,还可以实现直接把集群镜像push到docker镜像仓库中。

| 容器镜像缓存
build的过程中sealer是如何知道待构建的集群镜像里有哪些容器镜像,以及怎么把容器镜像存储下来,这其中有一些难点问题:

  1. 如何知道分布式软件中有哪些容器镜像,因为我们需要把这些镜像缓存下来,不管是扫描用户的yaml文件还是用helm template之后扫描都是不完美的,首先不能确定用户的编排方式是什么,其次有些软件甚至不把镜像地址写在编排文件中,而是通过自己的程序去拉起。无法保证build成功运行就一定没问题。
  2. 容器镜像是需要被存储到私有仓库中打包在集群镜像里,那容器镜像仓库地址势必和编排文件中写的不一样,特别是怎么保证用户alwayPull的时候还是能够在私有仓库中下载到镜像。

对待第一个问题,sealer解决方式是 sealer build的过程中和Docker build一样会起一个临时的kubernetes集群,并执行用户在Kubefile中定义的apply指令。

这样就可以保证用户依赖的所有镜像都被打包进去,无论用户使用什么样的编排方式。
第二个问题,我们打包容器镜像到私有镜像仓库中,怎样使用这个私有镜像也是个问题,因为假设私有镜像仓库名为localhost:5000 那肯定会和编排文件中写的不一样,我们有两种方式解决,第一种是hack和docker,做了一个只要私有镜像仓库中有就直接从私有镜像中拉取,没有才去公网拉取镜像的能力。 

还有种方案是无侵入docker的proxy,把docker请求全部打给代理,让代理去决定如果私有仓库有就从私有仓库拉取。同时我们还增强了registry的能力让registry可以cache多个远程仓库的能力。
sealer的这种方案完美的解决了离线场景镜像打包的问题。

| 负载均衡
sealer的集群高可用使用了轻量级的负载均衡lvscare,首先相比其它负载均衡lvscare非常小几百行代码,而且lvscare只做ipvs规则的守护,本身不做负载非常稳定,直接在node上监听apiserver,如果跪了就移除对应的规则,重新起来之后会自动加回,相当于是一个专用的负载均衡器,在sealos项目中也用了两年多,有广泛的实践。

| 运行时
运行时就是支撑应用运行的环境,像base on kuberentes的运行时sealer就可以透明的支持非常简单,以istio为例,用户只需要:

FROM kubernetes:v1.18.3
RUN curl -L https://istio.io/downloadIstio | sh -

就可以build出来一个istio的运行时供自己应用使用。

对于不是base on kuberentes的运行时,如k0s k3s,可以扩展sealer.Runtime中的接口,这样以后就可以:

FROM k3s:v1.18.3
RUN curl -L https://istio.io/downloadIstio | sh -

更牛的扩展比如扩展ACK的runtime

FROM aliyum.com/ACK:v1.16.9
RUN curl -L https://istio.io/downloadIstio | sh -

这种镜像会直接帮助用户应用运行到ACK上。 以上有些能力在roadmap中

| 基础设施
现在很多用户都希望在云端运行自己的集群镜像,sealer自带对接公有云能力,sealer自己实现的基础设施管理器,得益于我们更精细的退避重试机制,30s即可完成基础设施构建(阿里云6节点)性能是同类工具中的佼佼者,且API调用次数大大降低,配置兼容Clusterfile。

总结

sealer未来的一些愿景与价值提现:

  • sealer可以以极其简单的方式让用户自定义集群,解决分布式软件制作者与使用者的协作问题。
  • 极其简单友好的User Interface, 能屏蔽和兼容各种底层技术细节,到处运行
  • 生态建设,官方仓库里将会涵盖常用的分布式软件

最后我们总结下:

  • 如果你要整体交付你的分布式SaaS,请用sealer
  • 如果你要集成多个分布式服务在一起,如数据库消息队列或者微服务运行时,请用sealer
  • 如果你要安装一个分布式应用如mysql主备集群,请用sealer
  • 如果你需要安装/管理一个kubernetes高可用集群,请用sealer
  • 如果你要初始化多个数据中心,保持多个数据中心状态强一致,请用sealer
  • 如果你需要在公有云上实现上述场景,请用sealer

sealer将会在近期宣布开源,有兴趣的可以关注https://github.com/alibaba/se...
image.png


sealyun
289 声望56 粉丝

技术填坑者,爬起来接着填