作者 | 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/sealer_ 。
Docker 解決了單個容器的鏡像化問題,而 sealer 通過把整個集群打包,實現了分佈式軟件的 Build Share Run!!!
試想我們要去交付一個 SaaS 應用,它依賴了 MySQL/ES/Redis 這些數據庫和中間件,所有東西都在 Kubernetes 上進行編排,如果沒有集群鏡像時,要做如下操作:
- 找個工具去安裝 K8s 集群
- helm install mysql es redis... 如果是離線環境可能還需要導入容器鏡像
- 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 具體能幫我們做哪些事呢?下面列舉幾個主要場景:
1. 安裝 Kubernetes 與集群生命週期管理(升級/備份/恢復/伸縮)
這是個最簡單的場景,不管你是需要在單機上安裝個開發測試環境,還是在生產環境中安裝一個高可用集群;不管是裸機還是對接公有云,或者各種體系結構操作系統,都可以使用 sealer 進行安裝,這裡只安裝 Kubernetes 的話就選擇個基礎鏡像即可。
與其它的安裝工具對比,sealer 優勢在於:
- 簡單到令人髮指:sealer run 一條命令結束。
- 速度快到令人窒息:3min 裝完 6 節點,可能你使用別的工具時還沒下載完 sealer 就已經裝完了,不僅如此,後續我們還有黑科技優化到 2min 甚至 1min 以內。
- 兼容性與穩定性:兼容各種操作系統,支持 x86 arm 等體系結構。
- 一致性設計:會讓集群保持 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 該層。
2. 雲原生生態軟件的打包/安裝等,如 prometheus mysql 集群
sealer run prometheus:latest 就可以創建一個帶有 prometheus 的集群,或者在一個已有的集群中安裝 prometheus。
那麼問題來了:它和 helm 啥區別?
- sealer 不關心編排,更注重打包,上面例子 prometheus 可以用 helm 編排,sealer 會把 chart 和 chart 裡需要的所有容器鏡像打包起來,這是在 build 的過程中通過黑科技做到的,因為 build 過程會像 docker build 一樣起臨時的 Kubernetes 集群,然後我們就知道集群依賴了哪些容器鏡像,最後把這些容器鏡像打包。
- 和 Kubernetes 一起打包,拿了一個 chart 它未必能安裝成功,比如使用了廢棄的 api 版本,但是做成鏡像把 Kubnernetes 也包在一起了,只要 build 沒問題,run 就沒問題,這點和 docker 把操作系統 rootfs 打包在一起有異曲同工之妙。
- 集成性,集群鏡像更關注整個分佈式應用集群整體打包,如把 prometheus ELK mysql 集群做成一個鏡像服務與業務。
所以 sealer 與helm是協作關係,分工明確。
後續可以在 sealer 的官方鏡像倉庫中找到這些通用的集群鏡像,直接使用即可。
3. SaaS 軟件整體打包/交付 專有云離線交付
從分佈式應用的視角看,通常從上往下,少則幾個多則上百的組件,現有整體交付方式大多都是面向過程的,中間需要很多進行干預的事,sealer 就可以把這些東西統統打包在一起進行一鍵交付。
可能你會問:我們做個 tar.gz 再加個 ansible 腳本不也能一鍵化嗎?答案是肯定的。就和 docker 鏡像出現之前,大家也通過 tar.gz 交付一樣,你會發現標準和技術的出現解決了人與人之間的協作問題, 有了集群鏡像就可以直接複用別人的成果,也能製作好東西供別人使用。
專有云場景就非常適合使用 sealer,很多客戶機房都是離線的,而集群鏡像會把所有依賴打到鏡像中,只要鏡像製作得好,那麼所有局點都能以相同的方式進行一鍵交付,獲得極佳的一致性體驗。
4. 在公有云上實踐上述場景
sealer 自帶對接公有云屬性,很多情況下對接公有云會有更好的使用體驗,比如安裝集群時,只需要指定服務器數量和規格而不用關心 IP,伸縮直接修改 Clusterfile 中定義的數字即可。
技術原理簡介
1. 寫時複製
集群鏡像的存儲也是通過寫時複製的方式實現的。這樣做有兩個好處:我們可以把同一集群中不同的分佈式軟件打在不同層,以實現複用;還可以實現直接把集群鏡像 push 到 docker 鏡像倉庫中。
2. 容器鏡像緩存
build 的過程中 sealer 是如何知道待構建的集群鏡像裡有哪些容器鏡像,以及怎麼把容器鏡像存儲下來呢?其中有一些難點問題:
- 如何知道分佈式軟件中有哪些容器鏡像?因為我們需要把這些鏡像緩存下來,不管是掃描用戶的 yaml 文件還是用 helm template 之後掃描都是不完美的。首先不能確定用戶的編排方式是什麼,其次有些軟件不把鏡像地址寫在編排文件中,而是通過自己的程序去拉起,無法保證 build 成功運行就一定沒問題。
- 容器鏡像是需要被存儲到私有倉庫中打包在集群鏡像裡,那容器鏡像倉庫地址勢必和編排文件中寫的不一樣,特別是怎麼保證用戶 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 為例,用戶只需要:
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 中。
5. 基礎設施
現在很多用戶都希望在雲端運行自己的集群鏡像,sealer 自帶對接公有云能力,sealer 自己實現的基礎設施管理器,得益於我們更精細的退避重試機制,30s 即可完成基礎設施構建(阿里雲 6 節點)性能是同類工具中的佼佼者,且 API 調用次數大大降低,配置兼容 Clusterfile。
總結
sealer 未來的一些願景與價值提現:
- sealer 可以以極其簡單的方式讓用戶自定義集群,解決分佈式軟件製作者與使用者的協作問題。
- 極其簡單友好的 User Interface,能屏蔽和兼容各種底層技術細節,到處運行。
- 生態建設,官方倉庫裡將會涵蓋常用的分佈式軟件。
最後我們總結下:
- 如果你要整體交付你的分佈式 SaaS,請用 sealer。
- 如果你要集成多個分佈式服務在一起,如數據庫消息隊列或者微服務運行時,請用 sealer。
- 如果你要安裝一個分佈式應用如 mysql 主備集群,請用 sealer。
- 如果你需要安裝/管理一個 Kubernetes 高可用集群,請用 sealer。
- 如果你要初始化多個數據中心,保持多個數據中心狀態強一致,請用 sealer。
- 如果你需要在公有云上實現上述場景,請用 sealer。
sealer 將會在近期宣佈開源,有興趣的可以關注:https://github.com/alibaba/sealer。
如果你有什麼問題,歡迎釘釘搜索群號:34619594 加入釘釘交流群。
2021 阿里雲開發者大會重磅開啟!
數字時代,如何更好地利用雲的能力?什麼是新型、便捷的開發模式?如何讓開發者更高效地構建應用?科技賦能社會,技術推動變革,拓展開發者的能量邊界,一切,因雲而不同。點擊立即報名活動,2021 阿里雲開發者大會將給你答案。