推荐一款可快速全量交付 Kubernetes 集群分布式应用的神器 Sealer

Posted by Mike on 2021-06-02

什么是集群镜像

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

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

  • 单机有计算、存储、网络等驱动;集群有 CNI/CSI/CRI 实现像是集群的驱动。
  • 单机有 Ubuntu、Centos 操作系统;集群中可以把 Kubernetes 看成云操作系统。
  • 单机上可以运行 Docker 容器或虚拟机;相当于一个运行的实例,集群上也有运行着 K8s 的实例。
  • 单机上有虚拟机镜像,Docker 镜像;随着云计算技术的发展,集群上也会抽象出类似的镜像技术。

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

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

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

什么是 sealer

sealer[ˈsiːlər]是一款分布式应用打包交付运行的解决方案,通过把分布式应用及其数据库中间件等依赖一起打包以解决复杂应用的交付问题。

sealer 构建出来的产物我们称之为集群镜像, 集群镜像里内嵌了一个 kubernetes, 解决了分布式应用的交付一致性问题。集群镜像可以 push 到 registry 中共享给其他用户使用,也可以在官方仓库中找到非常通用的分布式软件直接使用。

Docker 解决了单个容器的镜像化问题,而 sealer 把 kubernetes 看成操作系统,在这个更高的抽象纬度上做出来的镜像就是集群镜像。sealer 通过把整个集群打包,实现了分布式软件的 Build Share Run!!!

特性

  • [x] 极其简单的方式在生产环境中或者离线环境中安装 kubernetes、以及 kubernetes 生态中其它软件
  • [x] 通过 Kubefile 可以非常简单的自定义 kubernetes 集群镜像对集群和应用进行打包,并可以提交到仓库中进行分享
  • [x] 强大的生命周期管理能力,以难以想象的简单的方式去做如集群升级,集群备份恢复,节点阔缩等操作
  • [x] 速度极快 3min 以内完成集群安装
  • [x] 支持 ARM x86, v1.20 以上版本支持 containerd,几乎兼容所有支持 systemd 的 linux 操作系统
  • [x] 不依赖 ansible haproxy keepalived, 高可用通过 ipvs 实现,占用资源少,稳定可靠
  • [x] 官方仓库中有非常多的生态软件镜像可以直接使用,包含所有依赖,一键安装

使用场景

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

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

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

现在如果提供另外一个方式,只需一条命令就可解决上面的问题,你会不会用?

1
$ sealer run your-saas-application-with-mysql-redis-es:latest

可以看到,只需要 run 一个集群镜像,整个集群就被交付了,细节复杂的操作都被屏蔽掉了,而且任何应用都可以使用相同的方式运行。这个集群镜像是怎么来的呢?

如上图所示:我们只需要定义一个类似 Dockerfile 的文件,将其称之为 Kubefile, 然后执行 build 命令即可:

1
$ sealer build -t your-saas-application-with-mysql-redis-es:latest .

从单机和集群两个纬度进行对比,就可以一目了然:

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

技术原理

1. 写时复制

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

2. 容器镜像缓存

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

  1. 如何知道分布式软件中有哪些容器镜像?因为我们需要把这些镜像缓存下来,不管是扫描用户的 yaml 文件还是用 helm template 之后扫描都是不完美的。首先不能确定用户的编排方式是什么,其次有些软件不把镜像地址写在编排文件中,而是通过自己的程序去拉起,无法保证 build 成功运行就一定没问题。

  2. 容器镜像是需要被存储到私有仓库中打包在集群镜像里,那容器镜像仓库地址势必和编排文件中写的不一样,特别是怎么保证用户 alwayPull 的时候还是能够在私有仓库中下载到镜像?

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

如上图所示,这样就可以保证用户依赖的所有镜像都被打包进去,无论用户使用什么样的编排方式。

第二个问题,我们打包容器镜像到私有镜像仓库中,怎样使用这个私有镜像也是个难题,假设私有镜像仓库名为 localhost:5000,肯定会和编排文件中写的不一致,对此我们有两种方式解决:

  • 第一种是 hack 和 docker,做了一个只要私有镜像仓库中有就直接从私有镜像中拉取,没有才去公网拉取镜像的能力。

  • 第二种方案是无侵入 docke r的 proxy,把 docker 请求全部打给代理,让代理去决定如果私有仓库有就从私有仓库拉取。同时我们还增强了 registry 的能力让 registry 可以 cache 多个远程仓库的能力。

sealer 的这种方案完美解决了离线场景镜像打包的问题。

3. 负载均衡

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

4. 运行时

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

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

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

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

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

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

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

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

5. 基础设施

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

快速体验

安装一个 kubernetes 集群

1
$ sealer run kubernetes:v1.19.9 --masters 192.168.0.2 --passwd xxx

如果是在云上安装:

1
2
3
4
5
6
$ export ACCESSKEYID=xxx
$ export ACCESSKEYSECRET=xxx
$ sealer run registry.cn-qingdao.aliyuncs.com/sealer-io/dashboard:latest
# 或者指定节点数量运行集群
$ sealer run registry.cn-qingdao.aliyuncs.com/sealer-io/dashboard:latest \
--masters 3 --nodes 3
1
2
3
4
5
6
7
8
$ kubectl get node
NAME STATUS ROLES AGE VERSION
izm5e42unzb79kod55hehvz Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r7z Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r8z Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r9z Ready <none> 18h v1.16.9
izm5ehdjw3kru84f0kq7raz Ready <none> 18h v1.16.9
izm5ehdjw3kru84f0kq7rbz Ready <none> 18h v1.16.9

查看镜像默认启动配置:

1
$ sealer inspect -c registry.cn-qingdao.aliyuncs.com/sealer-io/dashboard:latest

使用 Clusterfile 拉起一个 K8s 集群

使用已经提供好的官方基础镜像(sealer-io/kubernetes:v1.19.9)就可以快速拉起一个 k8s 集群。

  1. 场景 1:在已存在的服务器上去安装,provider 类型为:BAREMETAL

Clusterfile 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
apiVersion: sealer.aliyun.com/v1alpha1
kind: Cluster
metadata:
name: my-cluster
spec:
image: registry.cn-qingdao.aliyuncs.com/sealer-io/kubernetes:v1.19.9
provider: BAREMETAL
ssh:
passwd:
pk: xxx
pkPasswd: xxx
user: root
network:
interface: eth0
cniName: calico
podCIDR: 100.64.0.0/10
svcCIDR: 10.96.0.0/22
withoutCNI: false
certSANS:
- aliyun-inc.com
- 10.0.0.2

masters:
ipList:
- 172.20.125.234
- 172.20.126.5
- 172.20.126.6
nodes:
ipList:
- 172.20.126.8
- 172.20.126.9
- 172.20.126.10

执行如下所示命令:

1
2
3
4
5
6
7
8
9
$ sealer apply -f Clusterfile
$ kubectl get node
NAME STATUS ROLES AGE VERSION
izm5e42unzb79kod55hehvz Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r7z Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r8z Ready master 18h v1.16.9
izm5ehdjw3kru84f0kq7r9z Ready <none> 18h v1.16.9
izm5ehdjw3kru84f0kq7raz Ready <none> 18h v1.16.9
izm5ehdjw3kru84f0kq7rbz Ready <none> 18h v1.16.9
  1. 场景 2:自动申请阿里云服务器进行安装, provider 类型为:ALI_CLOUD

Clusterfile 内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: sealer.aliyun.com/v1alpha1
kind: Cluster
metadata:
name: my-cluster
spec:
image: registry.cn-qingdao.aliyuncs.com/sealer-io/kubernetes:v1.19.9
provider: ALI_CLOUD
ssh:
passwd:
pk: xxx
pkPasswd: xxx
user: root
network:
interface: eth0
cniName: calico
podCIDR: 100.64.0.0/10
svcCIDR: 10.96.0.0/22
withoutCNI: false
certSANS:
- aliyun-inc.com
- 10.0.0.2

masters:
cpu: 4
memory: 4
count: 3
systemDisk: 100
dataDisks:
- 100
nodes:
cpu: 4
memory: 4
count: 3
systemDisk: 100
dataDisks:
- 100

准备好阿里云的 AK 和 SK,并执行如下所示命令:

1
$ ACCESSKEYID=xxxxxxx ACCESSKEYSECRET=xxxxxxx sealer apply -f Clusterfile

部署完成后,基础设置的一些源信息会被写入到 Clusterfile 中,存储在 /root/.sealer/[cluster-name]/Clusterfile 中。如果你需要释放集群,可以执行下面的命令:

1
$ ./sealer delete -f /root/.sealer/my-cluster/Clusterfile

制作一个自定义的集群镜像, 这里以制作一个 Kubernetes Dashboard 镜像为例

新建一个 dashboard 目录,并创建一个文件 Kubefile 内容为:

1
2
3
FROM registry.cn-qingdao.aliyuncs.com/sealer-io/kubernetes:v1.19.9
RUN wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
CMD kubectl apply -f recommended.yaml
1
2
3
$ export ACCESSKEYID=xxxxxxx
$ export ACCESSKEYSECRET=xxxxxxx
$ sealer build -f Kubefile -t my-kuberentes-cluster-with-dashboard:latest .

创建一个带有 Kubernetes Dashboard 的自定义集群, 操作同上,替换掉 Clusterfile 中的 image 字段即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
apiVersion: sealer.aliyun.com/v1alpha1
kind: Cluster
metadata:
name: my-cluster
spec:
image: my-kuberentes-cluster-with-dashboard:latest
provider: ALI_CLOUD
ssh:
passwd:
pk: xxx
pkPasswd: xxx
user: root
network:
interface: eth0
cniName: calico
podCIDR: 100.64.0.0/10
svcCIDR: 10.96.0.0/22
withoutCNI: false
certSANS:
- aliyun-inc.com
- 10.0.0.2

masters:
cpu: 4
memory: 4
count: 3
systemDisk: 100
dataDisks:
- 100
nodes:
cpu: 4
memory: 4
count: 3
systemDisk: 100
dataDisks:
- 100

和上面的操作类似,先准备好阿里云的 AK 和 SK,并执行如下所示命令:

1
$ ACCESSKEYID=xxxxxxx ACCESSKEYSECRET=xxxxxxx sealer apply -f Clusterfile

到这里,你就部署好一个自带 Kubernetes Dashboard 的集群。

你还可以把制作好的集群镜像推送到镜像仓库,供其它人进行使用。

1
2
$ sealer tag my-kuberentes-cluster-with-dashboard:latest registry.cn-qingdao.aliyuncs.com/sealer-io/my-kuberentes-cluster-with-dashboard:latest
$ sealer push registry.cn-qingdao.aliyuncs.com/sealer-io/my-kuberentes-cluster-with-dashboard:latest

总结

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

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

最后我们总结下:

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

sealer 项目地址:https://github.com/alibaba/sealer

参考文档

  1. https://github.com/alibaba/sealer/blob/main/docs/README_zh.md
  2. https://mp.weixin.qq.com/s/0SBslzaMWtqn9H8Q57urNA
  3. https://mp.weixin.qq.com/s/0jVykl3DAYp9cQpAi13G-A