作者 | fanux.中弈, sealos作者,pouch maintainer, sealer創(chuàng)始人
項(xiàng)目地址:https://github.com/alibaba/sealer
什么是集群鏡像
顧名思義和操作系統(tǒng).iso鏡像或者Docker鏡像類似,集群鏡像是用一定的技術(shù)手段把整個(gè)集群的所有文件以一定格式打成的一個(gè)資源包。

對(duì)比單機(jī)和集群會(huì)發(fā)現(xiàn)一些有趣現(xiàn)象:
- 單機(jī)有計(jì)算存儲(chǔ)網(wǎng)絡(luò)這些驅(qū)動(dòng),集群有CNI/CSI/CRI的實(shí)現(xiàn)像是集群的驅(qū)動(dòng)
- 操作系統(tǒng)單機(jī)有ubuntu centos這些,我們可以把kubernetes看成云操作系統(tǒng)
- 單機(jī)上可以運(yùn)行docker容器 或者是虛擬機(jī),相當(dāng)于一個(gè)運(yùn)行的實(shí)例,集群也有運(yùn)行著k8s的實(shí)例
- 單機(jī)上的虛擬機(jī)鏡像,docker鏡像,所以隨著云計(jì)算技術(shù)的發(fā)展,在集群這個(gè)緯度也會(huì)抽象出類似的鏡像技術(shù)。
以基于kubernetes的集群鏡像為例,里面包含了除操作系統(tǒng)以外的所有文件:
- docker的依賴的二進(jìn)制與systemd配置,dockerd的配置,以及一個(gè)私有的容器鏡像倉庫
- kubernetes核心組件二進(jìn)制,容器鏡像,kubelet system配置等
- 應(yīng)用需要用到的yaml配置或者h(yuǎn)elm chart,以及應(yīng)用的容器鏡像
- 其它腳本,配置與二進(jìn)制工具等應(yīng)用運(yùn)行需要的所有依賴
同樣集群鏡像運(yùn)行時(shí)肯定不是起一個(gè)容器或者裝在一臺(tái)機(jī)器上,而是這個(gè)鏡像可以直接安裝到多臺(tái)服務(wù)器上或者直接對(duì)接到公有云的基礎(chǔ)設(shè)施上。
sealer介紹
sealer是阿里巴巴開源的集群鏡像的一個(gè)實(shí)現(xiàn)方式,項(xiàng)目地址: https://github.com/alibaba/sealer 要實(shí)現(xiàn)集群。
Docker解決了單個(gè)容器的鏡像化問題,而sealer通過把整個(gè)集群打包,實(shí)現(xiàn)了分布式軟件的Build Share Run!!!
試想我們要去交付一個(gè)SaaS應(yīng)用,它依賴了mysql es redis這些數(shù)據(jù)庫和中間件,所有東西都在kubernetes上進(jìn)行編排,那如果沒有集群鏡像那要做如下操作:
- 找個(gè)工具去安裝k8s集群
- helm install mysql es redis... 如果是離線環(huán)境可能還需要導(dǎo)入容器鏡像
- kubectl apply yoursaas
看似好像也沒那么復(fù)雜,但是其實(shí)從整個(gè)項(xiàng)目交付的角度來說是面向過程極易出錯(cuò)的
那現(xiàn)在如果現(xiàn)在提供另外一個(gè)方式只要一條命令解決上面的問題你會(huì)不會(huì)用?
sealer run your-saas-application-with-mysql-redis-es:latest
可以看到只需要run一個(gè)集群鏡像整個(gè)集群就被整體交付了,細(xì)節(jié)復(fù)雜的操作都被屏蔽掉了,而且任何應(yīng)用都可以使用相同的方式運(yùn)行。那這個(gè)集群鏡像是怎么來的呢:

我們只需要定義一個(gè)類似Dockerfile的文件我們稱之為Kubefile, 然后執(zhí)行一下build命令即可:
sealer build -t your-saas-application-with-mysql-redis-es:latest .在單機(jī)和集群兩個(gè)緯度進(jìn)行一個(gè)對(duì)比就可以一目了然:

docker可以通過Dockerfile構(gòu)建一個(gè)docker鏡像,使用compose就可以運(yùn)行容器。
sealer通過Kubefile構(gòu)建一個(gè)CloudImage,使用Clusterfile啟動(dòng)整個(gè)集群。
快速體驗(yàn)
制作和運(yùn)行一個(gè)kubernetes dashboard的集群鏡像來體驗(yàn)一個(gè)完整的流程。
編寫Kubefile
# 基礎(chǔ)鏡像,已經(jīng)被制作好了里面包含所有的kubernetes啟動(dòng)相關(guān)的依賴
FROM registry.cn-qingdao.aliyuncs.com/sealer-io/cloudrootfs:v1.16.9-alpha.7
# 下載官方的dashboard yaml編排文件,已經(jīng)下載了可以使用COPY指令
RUN wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml
# 指定運(yùn)行方式,可以使用kubectl helm kustomiz等
CMD kubectl apply -f recommended.yaml
build dashboard集群鏡像
sealer build -t kubernetes-with-dashobard:latest .
運(yùn)行集群鏡像
# 下面命令會(huì)在服務(wù)器上安裝k8s集群并apply dashboard, passwd指定服務(wù)器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
這樣就可以把制作好的鏡像交付出去或者提供給別人復(fù)用。
使用場景
sealer具體能幫我們做哪些事呢,下面列舉幾個(gè)主要場景:
| 安裝kubernetes與集群生命周期管理(升級(jí)/備份/恢復(fù)/伸縮)
這是個(gè)最簡單的場景,不管你是需要在單機(jī)上安裝個(gè)開發(fā)測試環(huán)境還是在生產(chǎn)環(huán)境中安裝一個(gè)高可用集群,不管是裸機(jī)還是對(duì)接公有云,或者各種體系結(jié)構(gòu)操作系統(tǒng),都可以使用sealer進(jìn)行安裝,這里只安裝kubernetes的話就選擇個(gè)基礎(chǔ)鏡像即可。
與其它的安裝工具對(duì)比,sealer優(yōu)勢(shì)在于:
- 簡單到令人發(fā)指 sealer run 一條命令結(jié)束
- 速度快到令人窒息,3min裝完6節(jié)點(diǎn),可能你在使用別的工具還沒下載完sealer就已經(jīng)裝完了,然而我們后續(xù)還有黑科技優(yōu)化到2min甚至1min以內(nèi)
- 兼容性與穩(wěn)定性 兼容各種操作系統(tǒng),支持x86 arm等體系結(jié)構(gòu)
- 一致性設(shè)計(jì),會(huì)讓集群保持Clusterfile中的定義狀態(tài),以升級(jí)為例,只需要改一下Clusterfile中的版本號(hào)即可實(shí)現(xiàn)升級(jí)。
速度快是因?yàn)槭紫仁莋olang實(shí)現(xiàn),意味著我們可以很多很細(xì)致的地方做并發(fā)的處理,這相比ansible就有更多的優(yōu)勢(shì)了,而且還可以做更細(xì)致的錯(cuò)誤處理,然后在鏡像分發(fā)上拋棄了以前l(fā)oad的方式,后續(xù)在文件分發(fā)上也會(huì)做優(yōu)化達(dá)到安裝性能上的極致。
兼容性上,docker kubelet這里都采用了二進(jìn)制+systemd安裝核心組件全容器化,這樣不用再去依賴yum apt這類感知操作系統(tǒng)的安裝工具。 ARM和x86采用不同的鏡像支持與sealer本身解耦開。 對(duì)公有云的適配也抽離單獨(dú)模塊進(jìn)行實(shí)現(xiàn),這里我們沒去對(duì)接terraform原因還是為了性能,在我們的場景下terraform啟動(dòng)基礎(chǔ)設(shè)施將近3min,而我們通過退避重試把基礎(chǔ)設(shè)施啟動(dòng)優(yōu)化到了30s以內(nèi),還有就是在集群鏡像這個(gè)場景下是不需要這么復(fù)雜的基礎(chǔ)設(shè)施管理能力的,我們不想讓sealer變重也不想去依賴一個(gè)命令行工具。
一致性的設(shè)計(jì)理念是sealer中值得一提的,集群鏡像與Clusterfile決定了集群是什么樣子的,相同的鏡像與Clusterfile就能run出個(gè)一樣的集群出來。 變更要么變更Clusterfile如增加節(jié)點(diǎn),改變節(jié)點(diǎn)規(guī)格,要么換鏡像,換鏡像的時(shí)候因?yàn)榧虹R像也是分層結(jié)構(gòu),hash值不變的layer不會(huì)發(fā)生變更,而hash發(fā)生變化會(huì)幫助重新apply該層。
| 云原生生態(tài)軟件的打包/安裝等如prometheus mysql集群等
sealer run prometheus:latest 就可以創(chuàng)建一個(gè)帶有prometheus的集群,或者在一個(gè)已有的集群中安裝prometheus。
那么問題來了:和helm啥區(qū)別?
- sealer 不關(guān)心編排,更注重打包,上面例子prometheus可以用helm編排的,sealer會(huì)把chart和chart里面需要的所有容器鏡像打包起來,這是在build的過程中通過黑科技做到的,因?yàn)閎uild過程會(huì)像docker build一樣起臨時(shí)的kubernetes集群,然后我們就知道了集群依賴了哪些容器鏡像,最后把這些容器鏡像打包。
- 和kubernetes一起打包,拿了一個(gè)chart它未必能安裝成功,比如使用了廢棄的api版本,但是做成鏡像把kubnernetes也包在一起了,只要build沒問題,run就沒問題,這點(diǎn)和docker把操作系統(tǒng)rootfs打包在一起異曲同工。
- 集成性,集群鏡像更關(guān)注整個(gè)分布式應(yīng)用集群整體打包,如把prometheus ELK mysql集群這些做成一個(gè)鏡像服務(wù)與業(yè)務(wù)。
所以sealer與helm是協(xié)作關(guān)系,分工明確。
后續(xù)就可以在sealer的官方鏡像倉庫中找到這些通用的集群鏡像然后直接使用。
| SaaS軟件整體打包/交付 專有云離線交付
從分布式應(yīng)用的視角看,通常從上往下,少則幾個(gè)多則上百的組件,現(xiàn)有整體交付方式大多都是面向過程的,中間需要很多認(rèn)為干預(yù)的事,sealer就可以把這些東西統(tǒng)統(tǒng)打包在一起進(jìn)行一鍵交付。
可能你會(huì)問,我做個(gè)tar.gz再加個(gè)ansible腳本不也是能一樣一鍵化嘛,那是肯定,就和docker鏡像出現(xiàn)之前大家也通過tar.gz交付一樣,你會(huì)發(fā)現(xiàn)標(biāo)準(zhǔn)和技術(shù)的出現(xiàn)解決和人與人之間的協(xié)作問題, 有了集群鏡像你可以直接復(fù)用別人的成果,也能制作好東西做別人使用。
專有云場景就非常適合使用sealer,很多客戶機(jī)房都是離線的,而集群鏡像會(huì)把所有依賴打到鏡像中。 只要鏡像制作的好那所有局點(diǎn)都可以以相同的方式進(jìn)行一鍵交付,獲得極佳的一致性體驗(yàn)。
| 在公有云上實(shí)踐上述場景
sealer自帶對(duì)接公有云屬性,很多情況下對(duì)接公有云會(huì)有更好的使用體驗(yàn),比如安裝集群時(shí)只需要指定服務(wù)器數(shù)量和規(guī)格而不用關(guān)心IP,伸縮直接修改Clusterfile中定義的數(shù)字即可。
技術(shù)原理簡介
| 寫時(shí)復(fù)制
集群鏡像的存儲(chǔ)也是通過寫時(shí)復(fù)制的方式,這樣做有兩個(gè)好處,我們可以把一個(gè)集群中不同的分布式式軟件打在不同的層,以實(shí)現(xiàn)復(fù)用,還可以實(shí)現(xiàn)直接把集群鏡像push到docker鏡像倉庫中。
| 容器鏡像緩存
build的過程中sealer是如何知道待構(gòu)建的集群鏡像里有哪些容器鏡像,以及怎么把容器鏡像存儲(chǔ)下來,這其中有一些難點(diǎn)問題:
- 如何知道分布式軟件中有哪些容器鏡像,因?yàn)槲覀冃枰堰@些鏡像緩存下來,不管是掃描用戶的yaml文件還是用helm template之后掃描都是不完美的,首先不能確定用戶的編排方式是什么,其次有些軟件甚至不把鏡像地址寫在編排文件中,而是通過自己的程序去拉起。無法保證build成功運(yùn)行就一定沒問題。
- 容器鏡像是需要被存儲(chǔ)到私有倉庫中打包在集群鏡像里,那容器鏡像倉庫地址勢(shì)必和編排文件中寫的不一樣,特別是怎么保證用戶alwayPull的時(shí)候還是能夠在私有倉庫中下載到鏡像。
對(duì)待第一個(gè)問題,sealer解決方式是 sealer build的過程中和Docker build一樣會(huì)起一個(gè)臨時(shí)的kubernetes集群,并執(zhí)行用戶在Kubefile中定義的apply指令。

這樣就可以保證用戶依賴的所有鏡像都被打包進(jìn)去,無論用戶使用什么樣的編排方式。
第二個(gè)問題,我們打包容器鏡像到私有鏡像倉庫中,怎樣使用這個(gè)私有鏡像也是個(gè)問題,因?yàn)榧僭O(shè)私有鏡像倉庫名為localhost:5000 那肯定會(huì)和編排文件中寫的不一樣,我們有兩種方式解決,第一種是hack和docker,做了一個(gè)只要私有鏡像倉庫中有就直接從私有鏡像中拉取,沒有才去公網(wǎng)拉取鏡像的能力。

還有種方案是無侵入docker的proxy,把docker請(qǐng)求全部打給代理,讓代理去決定如果私有倉庫有就從私有倉庫拉取。同時(shí)我們還增強(qiáng)了registry的能力讓registry可以cache多個(gè)遠(yuǎn)程倉庫的能力。
sealer的這種方案完美的解決了離線場景鏡像打包的問題。
| 負(fù)載均衡
sealer的集群高可用使用了輕量級(jí)的負(fù)載均衡lvscare,首先相比其它負(fù)載均衡lvscare非常小幾百行代碼,而且lvscare只做ipvs規(guī)則的守護(hù),本身不做負(fù)載非常穩(wěn)定,直接在node上監(jiān)聽apiserver,如果跪了就移除對(duì)應(yīng)的規(guī)則,重新起來之后會(huì)自動(dòng)加回,相當(dāng)于是一個(gè)專用的負(fù)載均衡器,在sealos項(xiàng)目中也用了兩年多,有廣泛的實(shí)踐。

| 運(yùn)行時(shí)
運(yùn)行時(shí)就是支撐應(yīng)用運(yùn)行的環(huán)境,像base on kuberentes的運(yùn)行時(shí)sealer就可以透明的支持非常簡單,以istio為例,用戶只需要:
FROM kubernetes:v1.18.3
RUN curl -L https://istio.io/downloadIstio | sh -
就可以build出來一個(gè)istio的運(yùn)行時(shí)供自己應(yīng)用使用。
對(duì)于不是base on kuberentes的運(yùn)行時(shí),如k0s k3s,可以擴(kuò)展sealer.Runtime中的接口,這樣以后就可以:
FROM k3s:v1.18.3
RUN curl -L https://istio.io/downloadIstio | sh -
更牛的擴(kuò)展比如擴(kuò)展ACK的runtime
FROM aliyum.com/ACK:v1.16.9
RUN curl -L https://istio.io/downloadIstio | sh -
這種鏡像會(huì)直接幫助用戶應(yīng)用運(yùn)行到ACK上。 以上有些能力在roadmap中
| 基礎(chǔ)設(shè)施
現(xiàn)在很多用戶都希望在云端運(yùn)行自己的集群鏡像,sealer自帶對(duì)接公有云能力,sealer自己實(shí)現(xiàn)的基礎(chǔ)設(shè)施管理器,得益于我們更精細(xì)的退避重試機(jī)制,30s即可完成基礎(chǔ)設(shè)施構(gòu)建(阿里云6節(jié)點(diǎn))性能是同類工具中的佼佼者,且API調(diào)用次數(shù)大大降低,配置兼容Clusterfile。
總結(jié)
sealer未來的一些愿景與價(jià)值提現(xiàn):
- sealer可以以極其簡單的方式讓用戶自定義集群,解決分布式軟件制作者與使用者的協(xié)作問題。
- 極其簡單友好的User Interface, 能屏蔽和兼容各種底層技術(shù)細(xì)節(jié),到處運(yùn)行
- 生態(tài)建設(shè),官方倉庫里將會(huì)涵蓋常用的分布式軟件
最后我們總結(jié)下:
- 如果你要整體交付你的分布式SaaS,請(qǐng)用sealer
- 如果你要集成多個(gè)分布式服務(wù)在一起,如數(shù)據(jù)庫消息隊(duì)列或者微服務(wù)運(yùn)行時(shí),請(qǐng)用sealer
- 如果你要安裝一個(gè)分布式應(yīng)用如mysql主備集群,請(qǐng)用sealer
- 如果你需要安裝/管理一個(gè)kubernetes高可用集群,請(qǐng)用sealer
- 如果你要初始化多個(gè)數(shù)據(jù)中心,保持多個(gè)數(shù)據(jù)中心狀態(tài)強(qiáng)一致,請(qǐng)用sealer
- 如果你需要在公有云上實(shí)現(xiàn)上述場景,請(qǐng)用sealer
kubernetes一鍵安裝