您好,登錄后才能下訂單哦!
點擊下載《不一樣的 雙11 技術:阿里巴巴經濟體云原生實踐》
cdn.com/2d3f2c0a733aa3bc75c82319f10a13c2f82b3771.jpeg">
本文節選自《不一樣的 雙11 技術:阿里巴巴經濟體云原生實踐》一書,點擊上方圖片即可下載!
作者 | 張振(守辰)阿里云云原生應用平臺高級技術專家
導讀:2019 年阿里巴巴核心系統 100% 以云原生方式上云,完美地支撐了 雙11 大促。這次上云的姿勢很不一般,不僅是擁抱了 Kubernetes,而且還以擁抱 Kubernetes 為契機進行了一系列對運維體系的深度改造。
Kubernetes?作為云原生的最佳實踐,已經成為了事實上的容器編排引擎標準,Kubernetes 在阿里巴巴集團落地主要經歷了四個階段:
在這幾年的實踐中,一個問題始終縈繞在各個架構師的頭腦中: 在阿里巴巴這么大體量、這么復雜的業務下, 遺留了大量傳統的運維習慣以及支撐這些習慣的運維體系,落地 Kubernetes?到底要堅持什么?要妥協什么?要改變什么?
本文將分享阿里巴巴這幾年對于這些問題的思考。答案很明顯:擁抱 Kubernetes?本身并不是目的,而是通過擁抱 Kubernetes?撬動業務的云原生改造,通過 Kubernetes?的能力,治理傳統運維體系下的沉疴頑疾,釋放云彈性的能力,為業務的應用交付解綁提速。
在阿里巴巴的 Kubernetes?落地實踐中,關注了下面幾個關鍵的云原生改造:
在阿里巴巴傳統的運維體系下,應用的變更都是 PaaS?通過創建操作工單,發起工作流,繼而對容器平臺發起一個個的變更來完成的。
當應用發布時, PaaS?會從數據庫中查到應用所有相關的容器,并針對每個容器,向容器平臺發起修改容器鏡像的變更。每一個變更實際上也是一個工作流,涉及到鏡像的拉取、舊容器的停止和新容器的創建。工作流中一旦發生錯誤或者超時,都需要 PaaS?進行重試。一般而言,為了保證工單及時的完成,重試僅會執行幾次,幾次重試失敗后,只能依靠人工處理。
當應用縮容時,PaaS?會根據運維人員的輸入,指定容器列表進行刪除,一旦其中有容器因為宿主機異常的情況下刪除失敗或者超時,PaaS?只能反復重試,為了保證工單的結束,在重試一定次數后只能認為容器刪除成功。如果宿主機后續恢復正常,被“刪除”的容器很有可能依然運行著。
傳統的面向過程的容器變更一直存在如下問題無法解決:
例如,一旦容器鏡像變更失敗,PaaS?無法保證容器鏡像的最終一致;一旦刪除容器失敗,
也無法保證容器最后真的被刪除干凈。兩個例子都需要通過巡檢來處理不一致的容器。而巡檢任務因為執行較少,其正確性和及時性都很難保證;
例如應用的發布和應用的擴容過程需要加鎖,否則會出現新擴的容器鏡像未更新的情況。而一旦對變更進行加鎖,變更的效率又會大幅下降。
Kubernetes?的能力提供了解決這個問題的機會。Kubernetes 的 workload?提供了聲明式的 API?來修改應用的實例數和版本,workload?的控制器可以監聽 pod?的實際情況,保證應用 pod?的實例數量和版本符合終態,避免了并發擴容和發布的沖突問題。Kubernetes 的 kubelet 會依據 pod?的 spec,反復嘗試啟動 pod,直到 pod?符合 spec?描述的終態。重試由容器平臺內部實現,不再和應用的工單狀態綁定。
在阿里巴巴傳統的運維體系下,容器平臺僅生產資源,應用的啟動以及服務發現是在容器啟動后由 PaaS?系統來執行的,這種分層的方法給了 PaaS?系統最大的自由,也在容器化后促進了阿里巴巴第一波容器生態的繁榮。但是這種方式有一個嚴重的問題,即:
容器平臺無法獨立地去觸發容器的擴縮容,需要和一個個 PaaS?來做復雜的聯動,上層 PaaS?也需要做很多重復的工作。這妨礙了容器平臺在宿主機發生故障、重啟、容器中進程發生異常、卡住時的高效自愈修復,也讓彈性擴縮容變得非常復雜。
在?Kubernetes?中通過容器的命令以及生命周期鉤子,可以將 PaaS?啟動應用以及檢查應用啟動狀態的流程內置在了 pod?中;另外,通過創建 service?對象,可以將容器和對應的服務發現機制關聯起來,從而實現容器、應用、服務生命周期的統一。容器平臺不再僅僅生產資源,而是交付可以直接為業務使用的服務。這極大地簡化了上云之后故障自愈以及自動彈性擴縮容能力的建設,
真正地發揮了云的彈性能力。
另外,在宿主機發生故障的情況下,PaaS?傳統上需要先對應用進行擴容,然后才刪除宿主機上的容器。然而在大規模的集群下,我們發現往往會卡在應用擴容這步。應用資源額度可能不夠,集群內滿足應用調度限制的空閑資源也可能不夠,無法擴容就無法對宿主機上的容器進行驅逐,進而也無法對異常的宿主機進行送修,久而久之,整個集群很容易就陷入故障機器一大堆,想修修不了、想騰騰不動的困境之中。
在?Kubernetes?中對于故障機的處理要“簡單和粗暴”得多,不再要求對應用先擴容,而是直接把故障機上的容器進行刪除,刪除后才由負載控制器進行擴容。這種方案乍一聽簡直膽大妄為,落地?Kubernetes?的時候很多 PaaS?的同學都非常排斥這種方法,認為這會嚴重影響業務的穩定性。事實上,絕大多數核心的業務應用都維護著一定的冗余容量,以便全局的流量切換或者應對突發的業務流量,臨時刪除一定量的容器根本不會造成業務的容量不足。
我們所面臨的關鍵問題是如何確定業務的可用容量,當然這是個更難的問題,但對于自愈的場景完全不需要準確的容量評估,只需要一個可以推動自愈運轉的悲觀估計就可以。在?Kubernetes?中可以通過 PodDisruptionBudget?來定量地描述對應用的可遷移量,例如可以設置對應用進行驅逐的并發數量或者比例。這個值可以參考發布時的每批數量占比來設置。假如應用發布一般分 10?批,那么可以設置 PodDisruptionBudget?中的 maxUnavailable?為 10%(對于比例,如果應用只有 10?個以內的實例,Kubernetes?還是認為可以驅逐 1?個實例)。萬一應用真的一個實例都不允許驅逐呢?那么對不起,這樣的應用是需要改造之后才能享受上云的收益的。一般應用可以通過改造自身架構,或者通過 operator?來自動化應用的運維操作,從而允許實例的遷移。<
Docker?的出現提供了一種統一的應用交付形式,通過把應用的二進制、配置、依賴統一在構建過程中打到了鏡像中,
通過使用新的鏡像創建容器,并刪除掉舊容器就完成了應用的變更。Docker?在交付應用時和傳統基于軟件包或者腳本的交付方式有一個重大區別,就是強制了容器的不可變,想要變更容器只能通過新創建容器來完成,而每個新容器都是從應用同一個鏡像創建而來,確保了一致性,從而避免了配置漂移,或者雪花服務器的問題。
Kubernetes 進一步強化了不可變基礎設施的理念,在默認的滾動升級過程中不但不會變更容器,而且還不會變更pod。每次發布,都是通過創建新的?pod,并刪除舊的 pod?來完成,這不僅保證了應用的鏡像統一,還保證了數據卷、資源規格以及系統參數配置都是和應用模板的 spec?保持一致。
另外,不少應用都有比較復雜的結構,一個應用實例可能同時包含多個團隊獨立開發的組件。 比如一個應用可能包括了業務相關的應用程序服務器,也包括了基礎設施團隊開發的日志采集進程,甚至還包括了第三方的中間件組件。這些進程、組件如果想要獨立發布就不能放在一個應用鏡像中,為此?Kubernetes?提供了多容器 pod?的能力,可以在一個 pod?中編排多個容器,想要發布單個組件,只需要修改對應容器的鏡像即可。
不過,阿里巴巴傳統的容器形態是富容器,即應用程序服務器,以及日志采集進程等相關的組件都部署在一個大的系統容器中,這造成了日志采集等組件的資源消耗無法單獨限制,也無法方便地進行獨立升級。因此,在阿里巴巴這次上云中,開始把系統容器中除業務應用外的其他組件都拆分到獨立的 sidecar?容器,我們稱之為輕量化容器改造。改造后,一個 pod?內會包括一個運行業務的主容器、一個運行著各種基礎設施 agent?的運維容器,以及服務網格等的sidecar容器。輕量化容器之后, 業務的主容器就能以比較低的開銷運行業務服務,從而更方便進行 serverless?的相關改造。
不過,Kubernetes 默認的滾動升級過程過于僵硬地執行了不可變基礎設施的理念,導致對多容器 pod?的能力支持有嚴重的缺失。雖然可以在一個 pod?中編排多個容器,但如果要發布 pod?中的一個容器,在實際執行發布時,不僅會重建待發布的容器,還會把整個 pod?都刪除,而后重調度、再重建。這意味著假如要升級基礎設施的日志采集組件,會導致其他組件,特別是業務的應用服務器被一起刪除重啟,從而干擾到正常的業務運行。因此,多個組件的變更依然沒有解耦。
對業務而言,假如 pod?中有本地緩存的組件,而每次業務的發布都會重啟緩存進程,這會導致業務發布期間緩存的命中率大幅下降,影響性能甚至用戶的體驗;另外,如果基礎設施、中間件等團隊的組件升級都和業務的組件升級綁定在一起,這會給技術的迭代更新帶來巨大的阻礙。假設負責中間件的團隊推出了新的 service mesh 版本, 而為了升級 mesh 還需要央求一個個業務發布才能更新 mesh 組件,那么中間件的技術升級就會大大減速。
因此,相比 pod?層次的不可變,我們認為堅持容器級別的不可變原則,更能發揮?Kubernetes?多容器 pod?的技術優勢。為此,我們建設了支持應用發布時只原地修改 pod?中部分容器的能力,特別地建設了支持容器原地升級的工作負載控制器,并替換?Kubernetes?默認的 deployment?和 statefulset?控制器作為內部的主要工作負載。
另外,還建設了支持跨應用進行 sidecar?容器升級的 sidecarset, 方便進行基礎設施以及中間件組件的升級。此外,通過支持原地升級還帶來了集群分布確定性、加速鏡像下載等的額外優勢。這部分能力,我們已經通過?OpenKruise 項目開源出來。OpenKruise 中的 Kruise 是 cruise的諧音,'K' for Kubernetes, 寓意 Kubernetes 上應用的自動巡航,滿載著阿里巴巴多年應用部署管理經驗和阿里巴巴經濟體云原生化歷程的最佳實踐。目前,OpenKruise 正在計劃發布更多的 Controller 來覆蓋更多的場景和功能,比如豐富的發布策略、金絲雀發布、藍綠發布、分批發布等等。
今年我們實現了 Kubernetes 的規模化落地,經受了 雙11 大促真實場景的考驗。像阿里巴巴這樣有著大量存量應用的場景,落地 K8s 并沒有捷徑,我們經受住了快速規模化落地的誘惑,沒有選擇兼容和妥協落后的運維習慣,而是選擇深蹲打好基礎、選擇深挖云原生價值。接下來,我們將繼續推動更多應用的云原生改造,特別是有狀態應用的改造,讓有狀態應用的部署和運維更加高效;另外,還將推動整個應用交付鏈路的云原生改造,讓應用交付更加高效和標準化。
本書亮點
“ 阿里巴巴云原生微信公眾號(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的技術公眾號。”
更多相關信息,關注“阿里巴巴云原生”。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。