云原生下的灰度體系建設(shè)
一周前,我們介紹了《面對(duì)大規(guī)模 K8s 集群,如何先于用戶(hù)發(fā)現(xiàn)問(wèn)題》。
本篇文章,我們將繼續(xù)為大家介紹 ASI SRE(ASI,Alibaba Serverless infrastructure,阿里巴巴針對(duì)云原生應(yīng)用設(shè)計(jì)的統(tǒng)一基礎(chǔ)設(shè)施) 是如何探索在 Kubernetes 體系下,建設(shè) ASI 自身基礎(chǔ)設(shè)施在大規(guī)模集群場(chǎng)景下的變更灰度能力的。
我們面臨著什么
ASI 誕生于阿里巴巴集團(tuán)全面上云之際,承載著集團(tuán)大量基礎(chǔ)設(shè)施全面云原生化的同時(shí),自身的架構(gòu)、形態(tài)也在不斷地演進(jìn)。
ASI 整體上主要采用 Kube-on-Kube 的架構(gòu),底層維護(hù)了一個(gè)核心的 Kubernetes 元集群,并在該集群部署各個(gè)租戶(hù)集群的 master 管控組件:apiserver、controller-manager、scheduler,以及 etcd。而在每個(gè)業(yè)務(wù)集群中,則部署著各類(lèi) controller、webhook 等 addon 組件,共同支撐 ASI 的各項(xiàng)能力。而在數(shù)據(jù)面組件層面,部分 ASI 組件以 DaemonSet 的形式部署在節(jié)點(diǎn)上,也有另一部分采用 RPM 包的部署形式。
同時(shí),ASI 承載了集團(tuán)、售賣(mài)區(qū)場(chǎng)景下數(shù)百個(gè)集群,幾十萬(wàn)的節(jié)點(diǎn)。即便在 ASI 建設(shè)初期,其管轄的節(jié)點(diǎn)也達(dá)到了數(shù)萬(wàn)的級(jí)別。在 ASI 自身架構(gòu)快速發(fā)展的過(guò)程中,組件及線上變更相當(dāng)頻繁,早期時(shí)單日 ASI 的組件變更可以達(dá)到數(shù)百次。而 ASI 的核心基礎(chǔ)組件諸如 CNI 插件、CSI 插件、etcd、Pouch 等,無(wú)論任意之一的錯(cuò)誤變更都可能會(huì)引起整個(gè)集群級(jí)別的故障,造成上層業(yè)務(wù)不可挽回的損失。
簡(jiǎn)而言之,集群規(guī)模大、組件數(shù)量多,變更頻繁以及業(yè)務(wù)形態(tài)復(fù)雜是在 ASI,或其他 Kubernetes 基礎(chǔ)設(shè)施層建設(shè)灰度能力和變更系統(tǒng)的幾大嚴(yán)峻挑戰(zhàn)。當(dāng)時(shí)在阿里巴巴內(nèi)部,ASI/Sigma 已有數(shù)套現(xiàn)有的變更系統(tǒng),但都存在一定的局限性。
天基:具備通用的節(jié)點(diǎn)發(fā)布的能力,但不包括集群、節(jié)點(diǎn)集等 ASI 的元數(shù)據(jù)信息。UCP:早期 sigma 2.0 的發(fā)布平臺(tái),年久失修。sigma-deploy:sigma 3.x 的發(fā)布平臺(tái),以鏡像 patch 的形式更新 deployment/daemonset。asi-deploy:早期 ASI 的發(fā)布平臺(tái),管理了 ASI 自身的組件,僅支持鏡像 patch,只針對(duì) Aone 的 CI/CD 流水線做適配,以及支持在多個(gè)不同環(huán)境間灰度,但灰度粒度較粗。
由此,我們希望借鑒前面幾代 sigma/ASI 的發(fā)布平臺(tái)歷史,從變更時(shí)入手,以系統(tǒng)能力為主,再輔以流程規(guī)范,逐步構(gòu)建 ASI 體系下的灰度體系,建設(shè) Kubernetes 技術(shù)棧下的運(yùn)維變更平臺(tái),保障數(shù)以千計(jì)的大規(guī)模集群的穩(wěn)定性。
預(yù)設(shè)和思路
ASI 自身架構(gòu)和形態(tài)的發(fā)展會(huì)極大地影響其自身的灰度體系建設(shè)方式,因此在 ASI 發(fā)展的早期,我們對(duì) ASI 未來(lái)的形態(tài)做了如下大膽的預(yù)設(shè):
以 ACK 為底座:ACK(阿里云容器服務(wù))提供了云的各種能力,ASI 將基于復(fù)用這些云的能力,同時(shí)將阿里巴巴集團(tuán)內(nèi)積累的先進(jìn)經(jīng)驗(yàn)反哺云。集群規(guī)模大:為提高集群資源利用率,ASI 將會(huì)以大集群的方式存在,單個(gè)集群提供公共資源池來(lái)承載多個(gè)二方租戶(hù)。集群數(shù)量多:ASI 不僅按 Region 維度進(jìn)行集群劃分,還會(huì)按照業(yè)務(wù)方等維度劃分獨(dú)立的集群。Addon 數(shù)量多:Kubernetes 體系是一個(gè)開(kāi)放架構(gòu),會(huì)衍生出非常多 operator,而這些 operator 會(huì)和 ASI 核心組件一起共同對(duì)外提供各種能力。變更場(chǎng)景復(fù)雜:ASI 的組件變更場(chǎng)景將不止鏡像發(fā)布形式,Kubernetes 聲明式的對(duì)象生命周期管理注定了變更場(chǎng)景的復(fù)雜性。
基于以上幾個(gè)假設(shè),我們能夠總結(jié)在 ASI 建設(shè)初期,亟待解決的幾個(gè)問(wèn)題:
如何在單個(gè)大規(guī)模集群中建設(shè)變更的灰度能力?如何在多個(gè)集群間建立規(guī)?;淖兏叶饶芰Γ吭诮M件數(shù)量、種類(lèi)眾多的情況下,如何保證進(jìn)行組件管理并保證組件每次的發(fā)布不會(huì)影響線上環(huán)境?
我們轉(zhuǎn)換一下視角,脫離集群的維度,嘗試從組件的角度來(lái)解決變更的復(fù)雜性。對(duì)于每個(gè)組件,它的生命周期可以大體劃分為需求和設(shè)計(jì)階段,研發(fā)階段和發(fā)布階段。對(duì)于每個(gè)階段我們都希望進(jìn)行規(guī)范化,并解決 Kubernetes 本身的特點(diǎn),將固定的規(guī)范落到系統(tǒng)中,以系統(tǒng)能力去保證灰度過(guò)程。
結(jié)合 ASI 的形態(tài)和變更場(chǎng)景的特殊性,我們從以下幾點(diǎn)思路出發(fā)去系統(tǒng)化建設(shè) ASI 的灰度體系:
需求和設(shè)計(jì)階段方案 TechReview組件上線變更會(huì)審組件研發(fā)階段標(biāo)準(zhǔn)化組件研發(fā)流程組件發(fā)布變更階段提供組件工作臺(tái)能力進(jìn)行組件的規(guī)?;芾斫ㄔO(shè) ASI 元數(shù)據(jù),細(xì)化灰度單元建設(shè) ASI 單集群、跨集群的灰度能力
灰度體系建設(shè)
1. 研發(fā)流程標(biāo)準(zhǔn)化
ASI 核心組件的研發(fā)流程可以總結(jié)為以下幾個(gè)流程:
針對(duì) ASI 自身的核心組件,我們與質(zhì)量技術(shù)團(tuán)隊(duì)的同學(xué)共同建設(shè)了 ASI 組件的 e2e 測(cè)試流程。除了組件自身的單元測(cè)試、集成測(cè)試外,我們單獨(dú)搭建了單獨(dú)的 e2e 集群,用作常態(tài)化進(jìn)行的 ASI 整體的功能性驗(yàn)證和 e2e 測(cè)試。
從單個(gè)組件視角入手,每個(gè)組件的新功能經(jīng)過(guò)研發(fā)后,進(jìn)行 Code Review 通過(guò)并合入 develop 分支,則立即觸發(fā)進(jìn)行 e2e 流程,通過(guò) chorus(云原生測(cè)試平臺(tái)) 系統(tǒng)構(gòu)建鏡像后,由 ASIOps(ASI 運(yùn)維管控平臺(tái)) 部署到對(duì)應(yīng)的 e2e 集群,執(zhí)行標(biāo)準(zhǔn)的 Kubernetes Conformance 套件測(cè)試任務(wù),驗(yàn)證 Kubernetes 范圍內(nèi)的功能是否正常。僅當(dāng)所有測(cè)試 case 通過(guò),該組件的版本才可標(biāo)記為可推平版本,否則后續(xù)的發(fā)布將會(huì)受到管控限制。
然而正如上文提到,Kubernetes 開(kāi)放的架構(gòu)意味著它不僅僅包含管控、調(diào)度等核心組件,集群的功能還很大程度依賴(lài)于上層的 operator 來(lái)共同實(shí)現(xiàn)。因此 Kubernetes 范圍內(nèi)的白盒測(cè)試并不能覆蓋所有的 ASI 的適用場(chǎng)景。底層組件功能的改變很有大程度會(huì)影響到上層 operator 的使用,因此我們?cè)诎缀?Conformance 的基礎(chǔ)上增加了黑盒測(cè)試用例,它包含對(duì)各類(lèi) operator 自身的功能驗(yàn)證,例如從上層 paas 發(fā)起的擴(kuò)縮容,校驗(yàn)發(fā)布鏈路的 quota 驗(yàn)證等能力,常態(tài)化運(yùn)行在集群中。
2. 組件規(guī)?;芾?/strong>
針對(duì) ASI 組件多、集群多的特點(diǎn),我們?cè)谠?asi-deploy 功能之上進(jìn)行拓展,以組件為切入點(diǎn),增強(qiáng)組件在多集群間的管理能力,從鏡像管理演進(jìn)成了YAML 管理。
基于 Helm Template 的能力,我們將一個(gè)組件的 YAML 抽離成模板、鏡像和配置三部分,分別表示以下幾部分信息:
模板:YAML 中在所有環(huán)境固定不變的信息,例如 apiVersion,kind 等;鏡像:YAML 中與組件鏡像相關(guān)的信息,期望在單一環(huán)境或者所有集群中保持一致的信息;配置:YAML 中與單環(huán)境、單集群綁定的信息,允許存在多樣化的內(nèi)容,不同集群中的配置可能不同;
因此,一個(gè)完整的 YAML 則由模板、鏡像和配置共同渲染而成。而 ASIOps 則再會(huì)對(duì)鏡像信息和配置信息這部分 YAML 分別進(jìn)行集群維度和時(shí)間維度(多版本)進(jìn)行管理,計(jì)算組件當(dāng)前版本信息在眾多集群眾多分布狀況以及組件在單集群中版本的一致性狀況。
針對(duì)鏡像版本,我們從系統(tǒng)上促使其版本統(tǒng)一,以保證不會(huì)因版本過(guò)低而導(dǎo)致線上問(wèn)題;而針對(duì)配置版本,我們則從管理上簡(jiǎn)化它的復(fù)雜性,防止配置錯(cuò)誤發(fā)入集群。
有了組件的基礎(chǔ)原型后,我們希望發(fā)布不僅僅是“替換 workload 里的 image 字段”這樣簡(jiǎn)單的一件事。我們當(dāng)前維護(hù)了整個(gè) YAML 信息,包含了除了鏡像之外的其他配置內(nèi)容,需要支持除了鏡像變動(dòng)外的變更內(nèi)容。因此我們嘗試以盡可能接近 kubectl apply 的方式去進(jìn)行 YAML 下發(fā)。
我們會(huì)記錄三部分的 YAML Specification 信息:
Cluster Spec:當(dāng)前集群中指定資源的狀況;Target Spec:現(xiàn)在要發(fā)布進(jìn)集群的 YAML 信息;DB Spec:上一次部署成功的 YAML 信息,與 kubectl apply 保存在 annotation 中的 last-applied-configuration 功能相同。
對(duì)于一個(gè)由鏡像、配置和模板共同構(gòu)建的 YAML,我們會(huì)采集上述三種 Spec 信息,并進(jìn)行一次 diff,從而獲得到資源 diff patch,再進(jìn)行一次 filter out,篩去不允許變更的危險(xiǎn)的字段,最后將整體的 patch 以 strategic merge patch 或者 merge patch 的形式發(fā)送給 APIServer,觸發(fā)使得 workload 重新進(jìn)入 reconcile 過(guò)程,以改變集群中該 workload 的實(shí)際狀況。
除此之外,由于 ASI 組件之間具有較強(qiáng)的相關(guān)性,存在許多場(chǎng)景需要同時(shí)一次性發(fā)布多個(gè)組件。例如當(dāng)我們初始化一個(gè)集群,或者對(duì)集群做一次整體的 release 時(shí)。因此我們?cè)趩蝹€(gè)組件部署的基礎(chǔ)上增加了 Addon Release 的概念,以組件的集合來(lái)表明整個(gè) ASI 的 release 版本,并且根據(jù)每個(gè)組件的依賴(lài)關(guān)系自動(dòng)生成部署流,保證整體發(fā)布的過(guò)程中不會(huì)出現(xiàn)循環(huán)依賴(lài)。
3. 單集群灰度能力建設(shè)
在云原生的環(huán)境下,我們以終態(tài)的形式去描述應(yīng)用的部署形態(tài),而 Kubernetes 提供了維護(hù)各類(lèi) Workload 終態(tài)的能力,Operator 對(duì)比 workload 當(dāng)前狀態(tài)與終態(tài)的差距并進(jìn)行狀態(tài)協(xié)調(diào)。這個(gè)協(xié)調(diào)的過(guò)程,換言之 workload 發(fā)布或者回滾的過(guò)程,可以由 Operator 定義的發(fā)布策略來(lái)處理這個(gè)“面向終態(tài)場(chǎng)景內(nèi)的面向過(guò)程的流程”。
相比 Kubernetes 上層的應(yīng)用負(fù)載,底層的基礎(chǔ)設(shè)施組件在發(fā)布的過(guò)程中更關(guān)心組件自身的灰度發(fā)布策略和灰度暫停能力,_即不論任何類(lèi)型的組件,都需要能在發(fā)布過(guò)程中具備及時(shí)停止發(fā)布的能力,以提供更多的時(shí)間進(jìn)行功能檢測(cè)、決策以及回滾_。具體而言,這些能力可以歸納為如下幾類(lèi):
updateStrategy:流式升級(jí)/滾動(dòng)升級(jí)pause/resume:暫停/恢復(fù)能力maxUnavailable:不可用副本數(shù)到達(dá)一定時(shí)能夠快速停止升級(jí)partition:升級(jí)暫停能力,單次僅升級(jí)固定數(shù)量副本數(shù),保留一定數(shù)量的老版本副本
ASI 中針對(duì) Kubernetes 原生 workload 能力、節(jié)點(diǎn)能力都進(jìn)行了增強(qiáng)。依托于集群中 Kruise 和 KubeNode 這類(lèi) operator 的能力以及上層管控平臺(tái) ASIOps 的共同協(xié)作,我們對(duì) Kubernetes 基礎(chǔ)設(shè)施組件實(shí)現(xiàn)了上述灰度能力的支持。對(duì)于 Deployment / StatefulSet / DaemonSet / Dataplane 類(lèi)型的組件,在單集群中發(fā)布時(shí)支持的能力如下:
后文將簡(jiǎn)要介紹我們針對(duì)不同 Workload 類(lèi)型的組件進(jìn)行灰度的實(shí)現(xiàn),詳細(xì)的實(shí)現(xiàn)細(xì)節(jié)可以關(guān)注我們開(kāi)源的項(xiàng)目 OpenKruise 以及后續(xù)準(zhǔn)備開(kāi)源的 KubeNode。
1)Operator Platform
大多數(shù) Kubernetes 的 operator 以 Deployment 或者 StatefulSet 的方式部署,在 Operator 發(fā)布的過(guò)程中,一旦鏡像字段變動(dòng),所有 Operator 副本均會(huì)被升級(jí)。這個(gè)過(guò)程一旦新版本存在問(wèn)題,則會(huì)造成不可挽回的問(wèn)題。
針對(duì)此類(lèi) operator,我們將 controller-runtime 從 operator 中剝離出來(lái),構(gòu)建一個(gè)中心化的組件 operator-manager(OpenKruise 開(kāi)源實(shí)現(xiàn)中為 controller-mesh)。同時(shí)每個(gè) operator pod 中會(huì)增加一個(gè) operator-runtime 的 sidecar 容器,通過(guò) gRPC 接口為組件的主容器提供 operator 的核心能力。
operator 向 APIServer 建立 Watch 連接后,監(jiān)聽(tīng)到事件并被轉(zhuǎn)化為待 operator 協(xié)調(diào)處理的任務(wù)流(即 operator 的流量),operator-manager 負(fù)責(zé)中心化管控所有 operator 的流量,并根據(jù)規(guī)則進(jìn)行流量分片,分發(fā)到不同的 operator-runtime,runtime 中的 workerqueue 再觸發(fā)實(shí)際 operator 的協(xié)調(diào)任務(wù)。
在灰度過(guò)程中,operator-manager 支持按照 namespace 級(jí)別,哈希分片方式,將 operator 的流量分?jǐn)偨o新舊版本的兩個(gè)副本,從而可以從兩個(gè)副本處理的負(fù)載 workload 來(lái)驗(yàn)證這次灰度發(fā)布是否存在問(wèn)題。
2)Advanced DaemonSet
社區(qū)原生的 DaemonSet 支持了 RollingUpdate,但是其滾動(dòng)升級(jí)的能力上僅支持 maxUnavailable 一種,這對(duì)于單集群數(shù)千上萬(wàn)節(jié)點(diǎn)的 ASI 而言是無(wú)法接受的,一旦更新鏡像后所有 DaemonSet Pod 將會(huì)被升級(jí),并且無(wú)法暫停,僅能通過(guò) maxUnavailable 策略進(jìn)行保護(hù)。一旦 DaemonSet 發(fā)布了一個(gè) Bug 版本,并且進(jìn)程能夠正常啟動(dòng),那么 maxUnavailable 也無(wú)法生效。
此外社區(qū)提供 onDelete 方式,可以在手動(dòng)刪除 Pod 創(chuàng)建新 Pod,由發(fā)布平臺(tái)中心端控制發(fā)布順序和灰度,這種模式無(wú)法做到單集群中的自閉環(huán),所有的壓力都上升到發(fā)布平臺(tái)上。讓上層發(fā)布平臺(tái)來(lái)進(jìn)行Pod驅(qū)逐,風(fēng)險(xiǎn)比較大。最好的方式就是 Workload 能自閉環(huán)提供組件更新的能力。因此我們?cè)?Kruise 中加強(qiáng)了 DaemonSet 的能力使其支持上述幾種重要的灰度能力。
如下是一個(gè)基本的 Kruise Advanced DaemonSet 的例子:
apiVersion: apps.kruise.io/v1alpha1kind: DaemonSetspec: # ... updateStrategy: type: RollingUpdate rollingUpdate: maxUnavailable: 5 partition: 100 paused: false
其中 partition 意為保留老版本鏡像的 Pod 副本數(shù),滾升級(jí)過(guò)程中一旦指定副本數(shù) Pod 升級(jí)完成,將不再對(duì)新的 Pod 進(jìn)行鏡像升級(jí)。我們?cè)谏蠈?ASIOps 中控制 partition 的數(shù)值來(lái)滾動(dòng)升級(jí) DaemonSet,并配合其他 UpdateStrategy 參數(shù)來(lái)保證灰度進(jìn)度,同時(shí)在新創(chuàng)建的 Pod 上進(jìn)行一些定向驗(yàn)證。
3)MachineComponentSet
MachineComponentSet 是 KubeNode 體系內(nèi)的 Workload,ASI 中在 Kubernetes 之外的節(jié)點(diǎn)組件(無(wú)法用 Kubernetes 自身的 Workload 發(fā)布的組件),例如 Pouch,Containerd,Kubelet 等均是通過(guò)該 Workload 進(jìn)行發(fā)布。
節(jié)點(diǎn)組件以 Kubernetes 內(nèi)部的自定義資源 MachineComponent 進(jìn)行表示,包含一個(gè)指定版本的節(jié)點(diǎn)組件(例如 pouch-1.0.0.81)的安裝腳本,安裝環(huán)境變量等信息;而 MachineComponentSet 則是節(jié)點(diǎn)組件與節(jié)點(diǎn)集合的映射,表明該批機(jī)器需要安裝該版本的節(jié)點(diǎn)組件。而中心端的 Machine-Operator 則會(huì)去協(xié)調(diào)這個(gè)映射關(guān)系,以終態(tài)的形式,比對(duì)節(jié)點(diǎn)上的組件版本以及目標(biāo)版本的差異,并嘗試去安裝指定版本的節(jié)點(diǎn)組件。
在灰度發(fā)布這一部分,MachineComponentSet 的設(shè)計(jì)與 Advanced DaemonSet 類(lèi)似,提供了包括 partition,maxUnavailable 的 RollingUpdate 特性,例如以下是一個(gè) MachineComponentSet 的示例:
apiVersion: kubenode.alibabacloud.com/v1kind: MachineComponentSetmetadata: labels: alibabacloud.com/akubelet-component-version: 1.18.6.238-20201116190105-cluster-202011241059-d380368.conf component: akubelet name: akubelet-machine-component-setspec: componentName: akubelet selector: {} updateStrategy: maxUnavailable: 20% partition: 55 pause: false
同樣上層 ASIOps 在控制灰度升級(jí)節(jié)點(diǎn)組件時(shí),與集群側(cè)的 Machine-Operator 進(jìn)行交互,修改指定 MachineComponentSet 的 partition 等字段進(jìn)行滾動(dòng)升級(jí)。
相比于傳統(tǒng)的節(jié)點(diǎn)組件發(fā)布模式,KubeNode 體系將節(jié)點(diǎn)組件的生命周期也閉環(huán)至 Kubernetes 集群內(nèi),并將灰度發(fā)布的控制下沉到集群側(cè),減少中心側(cè)對(duì)節(jié)點(diǎn)元數(shù)據(jù)管理的壓力。
4. 跨集群灰度能力建設(shè)
阿里巴巴內(nèi)部針對(duì)云產(chǎn)品、基礎(chǔ)產(chǎn)品制定了變更紅線 3.0,對(duì)管控面組件、數(shù)據(jù)面組件的變更操作的分批灰度、控制間隔、可觀測(cè)、可暫停、可回滾進(jìn)行了要求。但變更對(duì)象以 region 的單元進(jìn)行灰度不滿(mǎn)足 ASI 的復(fù)雜場(chǎng)景,因此我們嘗試去細(xì)化 ASI 上管控面、數(shù)據(jù)面的變更所屬的變更單元的類(lèi)型。
我們圍繞集群這一基礎(chǔ)單元向上,向下分別進(jìn)行抽象,得到以下幾個(gè)基本單元:
集群組:具有共同業(yè)務(wù)方(ASI 承接的二方用戶(hù))、網(wǎng)絡(luò)域(售賣(mài)區(qū)/OXS/集團(tuán))、環(huán)境(e2e/測(cè)試/預(yù)發(fā)/金絲雀/小流量/生產(chǎn))信息,因此在監(jiān)控、告警、巡檢、發(fā)布等方面的配置具有共同性。集群:ASI 集群概念,對(duì)應(yīng)一個(gè) Kubernetes 集群預(yù)案。節(jié)點(diǎn)集:一組具有共同特征的節(jié)點(diǎn)集合,包括資源池、子業(yè)務(wù)池等信息。Namespace:?jiǎn)蝹€(gè)集群中的單個(gè) Namespace,通常 ASI 中一個(gè)上層業(yè)務(wù)對(duì)應(yīng)一個(gè) Namespace。節(jié)點(diǎn):?jiǎn)闻_(tái)宿主機(jī)節(jié)點(diǎn),對(duì)應(yīng)一個(gè) Kubernetes Node。
針對(duì)每種發(fā)布模式(管控組件、節(jié)點(diǎn)組件),我們以最小爆炸半徑為原則,將他們所對(duì)應(yīng)的灰度單元編排串聯(lián)在一起,以使得灰度流程能夠固化到系統(tǒng)中,組件開(kāi)發(fā)在發(fā)布中必須遵守流程,逐個(gè)單元進(jìn)行部署。編排過(guò)程中,我們主要考慮以下幾個(gè)因素:
業(yè)務(wù)屬性環(huán)境(測(cè)試、預(yù)發(fā)、小流量、生產(chǎn))網(wǎng)絡(luò)域(集團(tuán) V、售賣(mài)區(qū)、OXS)集群規(guī)模(Pod/Node 數(shù))用戶(hù)屬性(承載用戶(hù)的 GC 等級(jí))單元/中心組件特性
同時(shí)我們對(duì)每個(gè)單元進(jìn)行權(quán)重打分,并對(duì)單元間的依賴(lài)關(guān)系進(jìn)行編排。例如以下是一條 ASI 監(jiān)控組件的發(fā)布流水線,由于該監(jiān)控組件在所有 ASI 場(chǎng)景都會(huì)使用同一套方案,它將推平至所有 ASI 集群。并且在推平過(guò)程中,它首先會(huì)經(jīng)過(guò)泛電商交易集群的驗(yàn)證,再進(jìn)行集團(tuán) VPC 內(nèi)二方的發(fā)布,最后進(jìn)行售賣(mài)區(qū)集群的發(fā)布。而在每個(gè)集群中,該組件則會(huì)按照上一節(jié)中我們討論的單集群內(nèi)的灰度方式進(jìn)行 1/5/10 批次的分批,逐批進(jìn)行發(fā)布。
進(jìn)行了灰度單元編排之后,我們則可以獲得到一次組件推平流水線的基礎(chǔ)骨架。而對(duì)于骨架上的每個(gè)灰度單元,我們嘗試去豐富它的前置檢查和后置校驗(yàn),從而能夠在每次發(fā)布后確認(rèn)灰度的成功性,并進(jìn)行有效的變更阻斷。同時(shí)對(duì)于單個(gè)批次我們?cè)O(shè)置一定的靜默期去使得后置校驗(yàn)?zāi)軌蛴凶銐虻臅r(shí)間運(yùn)行完,并且提供給組件開(kāi)發(fā)足夠的時(shí)間進(jìn)行驗(yàn)證。目前單批次前置后置校驗(yàn)內(nèi)容包括:
全局風(fēng)險(xiǎn)規(guī)則(封網(wǎng)、熔斷等)發(fā)布時(shí)間窗口(ASI 試行周末禁止發(fā)布的規(guī)則)KubeProbe 集群黑盒探測(cè)金絲雀任務(wù)(由諾曼底發(fā)起的 ASI 全鏈路的擴(kuò)縮容任務(wù))核心監(jiān)控指標(biāo)大盤(pán)組件日志(組件 panic 告警等)主動(dòng)診斷任務(wù)(主動(dòng)查詢(xún)對(duì)應(yīng)的監(jiān)控信息是否在發(fā)布過(guò)程中有大幅變化)
將整個(gè)多集群發(fā)布的流程串聯(lián)在一起,我們可以得到一個(gè)組件從研發(fā),測(cè)試至上線發(fā)布,整個(gè)流程經(jīng)歷的事件如下圖:
在流水線編排的實(shí)現(xiàn)方面,我們對(duì)社區(qū)已有的 tekton 和 argo 進(jìn)行了選型調(diào)研,但考慮到我們?cè)诎l(fā)布流程中較多的邏輯不適合單獨(dú)放在容器中執(zhí)行,同時(shí)我們?cè)诎l(fā)布過(guò)程中的需求不僅僅是 CI/CD,以及在設(shè)計(jì)初期這兩個(gè)項(xiàng)目在社區(qū)中并不穩(wěn)定。因而我們參考了 tekton 的基礎(chǔ)設(shè)計(jì)(task / taskrun / pipeline / pipelinerun)進(jìn)行了實(shí)現(xiàn),并且保持著和社區(qū)共同的設(shè)計(jì)方向,在未來(lái)會(huì)調(diào)整與社區(qū)更接近,更云原生的方式。
成果
經(jīng)過(guò)近一年半的建設(shè),ASIOps 目前承載了近百個(gè)管控集群,近千個(gè)業(yè)務(wù)集群(包括 ASI 集群、Virtual Cluster 多租虛擬集群,Sigma 2.0 虛擬集群等),400 多個(gè)組件(包括 ASI 核心組件、二方組件等)。同時(shí) ASIOps 上包含了近 30 余條推平流水線,適用于 ASI 自身以及 ASI 承載的業(yè)務(wù)方的不同發(fā)布場(chǎng)景。
同時(shí)每天有近 400 次的組件變更(包括鏡像變更和配置變更),通過(guò)流水線推平的此時(shí)達(dá) 7900+。同時(shí)為了提高發(fā)布效率,我們?cè)谇昂笾脵z查完善的條件下開(kāi)啟了單集群內(nèi)自動(dòng)灰度的能力,目前該能力被大多數(shù) ASI 數(shù)據(jù)面的組件所使用。
如下是一個(gè)組件通過(guò) ASIOps 進(jìn)行版本推平的示例:
同時(shí)我們?cè)?ASIOps 上的分批灰度以及后置檢查變更阻斷,也幫助我們攔住了一定由于組件變更引起的故障。例如 Pouch 組件在進(jìn)行灰度時(shí),由于版本不兼容導(dǎo)致了集群不可用,通過(guò)發(fā)布后觸發(fā)的后置巡檢發(fā)現(xiàn)了這一現(xiàn)象,并阻斷了灰度進(jìn)程。
ASIOps 上的組件大多數(shù)都是 ASI/Kubernetes 底層的基礎(chǔ)設(shè)施組件,近一年半以來(lái)沒(méi)有因?yàn)橛山M件變更所引起的故障。我們努力將指定的規(guī)范通過(guò)系統(tǒng)能力固化下來(lái),以減少和杜絕違反變更紅線的變更,從而將故障的發(fā)生逐步右移,從變更引發(fā)的低級(jí)故障逐步轉(zhuǎn)變至代碼 Bug 自身引起的復(fù)雜故障。
展望
隨著 ASI 的覆蓋的場(chǎng)景逐步擴(kuò)大,ASIOps 作為其中的管控平臺(tái)需要迎接更復(fù)雜的場(chǎng)景,規(guī)模更大的集群數(shù)、組件數(shù)的挑戰(zhàn)。
首先我們亟待解決穩(wěn)定性和效率這一權(quán)衡問(wèn)題,當(dāng) ASIOps 納管的集群數(shù)量到達(dá)一定量級(jí)后,進(jìn)行一次組件推平的耗時(shí)將相當(dāng)大。我們希望在建設(shè)了足夠的前后置校驗(yàn)?zāi)芰?,提供變更全托管的能力,由平臺(tái)自動(dòng)進(jìn)行發(fā)布范圍內(nèi)的組件推平,并執(zhí)行有效的變更阻斷,在 Kubernetes 基礎(chǔ)設(shè)施這一層真正做到 CI/CD 自動(dòng)化。
同時(shí)目前我們需要手動(dòng)對(duì)灰度單元進(jìn)行編排,確定灰度順序,在未來(lái)我們希望建設(shè)完全整個(gè) ASI 的元數(shù)據(jù),并自動(dòng)對(duì)每次發(fā)布范圍內(nèi)的所有單元進(jìn)行過(guò)濾、打分和編排。
最后,目前 ASIOps 暫時(shí)只做到針對(duì)組件相關(guān)的變更進(jìn)行灰度的能力,而 ASI 范圍內(nèi)的變更遠(yuǎn)不止組件這一點(diǎn)?;叶润w系應(yīng)該是一個(gè)通用的范疇,灰度流水線需要被賦能到注入資源運(yùn)維、預(yù)案執(zhí)行的其他的場(chǎng)景中。此外,整個(gè)管控平臺(tái)的灰度能力沒(méi)有與阿里巴巴有任何緊耦合,完全基于 Kruise / KubeNode 等 Workload 進(jìn)行打造,未來(lái)我們會(huì)探索開(kāi)源整套能力輸出到社區(qū)中。