作者 | 孫健波(阿裡巴巴技術專家)、趙钰瑩
導讀:雲原生時代,Kubernetes 的重要性日益凸顯。然而,大多數網際網路公司在 Kubernetes 上的探索并非想象中順利,Kubernetes 自帶的複雜性足以讓一批開發者望而卻步。本文中,阿裡巴巴技術專家孫健波在接受采訪時基于阿裡巴巴 Kubernetes 應用管理實踐過程提供了一些經驗與建議,以期對開發者有所幫助。
在網際網路時代,開發者更多是通過頂層架構設計,比如多叢集部署和分布式架構的方式來實作出現資源相關問題時的快速切換,做了很多事情來讓彈性變得更加簡單,并通過混部計算任務來提高資源使用率,雲計算的出現則解決了從 CAPEX 到 OPEX 的轉變問題。
雲計算時代讓開發可以聚焦在應用價值本身,相較于以前開發者除了業務子產品還要投入大量精力在存儲、網絡等基礎設施,如今這些基礎設施都已經像水電煤一樣便捷易用。雲計算的基礎設施具有穩定、高可用、彈性伸縮等一系列能力,除此之外還配套解決了一系列應用開發“最佳實踐”的問題,比如監控、審計、日志分析、灰階釋出等。原來,一個工程師需要非常全面才能做好一個高可靠的應用,現在隻要了解足夠多的基礎設施産品,這些最佳實踐就可以信手拈來了。但是,在面對天然複雜的 Kubernetes 時,很多開發者都無能為力。
作為 Jira 和代碼庫 Bitbucket 背後的公司,Atlassian 的 Kubernetes 團隊首席工程師 Nick Young 在采訪中表示:
雖然當初選擇 Kubernetes 的戰略是正确的(至少到現在也沒有發現其他可能的選擇),解決了現階段遇到的許多問題,但部署過程異常艱辛。
那麼,有好的解決辦法嗎?
太過複雜的 Kubernetes
“如果讓我說 Kubernetes 存在的問題,當然是‘太複雜了’”,孫健波在采訪中說道,“不過,這其實是由于 Kubernetes 本身的定位導緻的。”
孫健波補充道,Kubernetes 的定位是“platform for platform”。它的直接使用者,既不是應用開發者,也不是應用運維,而是“platform builder”,也就是基礎設施或者平台級工程師。但是,長期以來,我們對 Kubernetes 項目很多時候都在錯位使用,大量的應用運維人員、甚至應用研發都在直接圍繞 Kubernetes 很底層的 API 進行協作,這是導緻很多人抱怨 “Kubernetes 實在是太複雜了”的根本原因之一。
這就好比一名 Java Web 工程師必須直接使用 Linux Kernel 系統調用來部署和管理業務代碼,自然會覺得 Linux “太反人類了”。是以,目前 Kubernetes 項目實際上欠缺一層更高層次的封裝,來使得這個項目能夠對上層的軟體研發和運維人員更加友好。
如果可以了解上述的定位,那麼 Kubernetes 将 API 對象設計成 all-in-one 是合理的,這就好比 Linux Kernel 的 API,也不需要區分使用者是誰。但是,當開發者真正要基于 K8s 管理應用、并對接研發、運維工程師時,就必然要考慮這個問題,也必然要考慮如何做到像另一層 Linux Kernel API 那樣以标準、統一的方式解決這個問題,這也是
阿裡雲和微軟聯合開放雲原生應用模型 Open Application Model (OAM)的原因。
有狀态應用支援
除了天然的複雜性問題,Kubernetes 對于有狀态應用的支援也一直是衆多開發者花費大量時間研究和解決的問題,并不是不可以支援,隻是沒有相對較優的解決方案。目前,業内主流的針對有狀态應用的解法是 Operator,但是編寫 Operator 其實是很困難的。
在采訪中,孫健波表示,這是因為 Operator 本質上是一個“進階版”的 K8s 用戶端,但是 K8s API Server 的設計,是“重用戶端”的模型,這當然是為了簡化 API Server 本身的複雜度,但也導緻了無論是 K8s client 庫,還是以此為基礎的 Operator,都變的異常複雜和難以了解:它們都夾雜了大量 K8s 本身的實作細節,比如 reflector、cache store、informer 等。這些,并不應該是 Operator 編寫者需要關心的,Operator 編寫者應該是有狀态應用本身的領域專家(比如 TiDB 的工程師),而不應該是 K8s 專家。這是現在 K8s 有狀态應用管理最大的痛點,而這可能需要一個新的 Operator 架構來解決這個問題。
另一方面,複雜應用的支援不止編寫 Operator 這麼簡單,這裡還需要有狀态應用傳遞的技術支撐,這是目前社群上各種持續傳遞項目都有意或者無意間忽略掉的事情。事實上,持續傳遞一個基于 Operator 的有狀态應用,跟傳遞一個無狀态的 K8s Deployment 的技術挑戰完全不是一個量級的。這也是孫健波所在團隊在 CNCF 應用傳遞領域小組(CNCF SIG App Deliver)倡導“應用傳遞分層模型”的重要原因:如下圖所示,四層模型分别為“應用定義”、“應用傳遞”、“應用運維與自動化”、“平台層”,隻有通過這四個層不同能力的合力協作,才能真正做到高品質和高效率的傳遞有狀态應用。

舉個例子,Kubernetes API 對象的設計是“all-in-one”的, 即:應用管理過程中的所有參與者,都必須在同一個 API 對象上進行協作。這就導緻開發者會看到,像 K8s Deployment 這樣的 API 對象描述裡, 既有應用開發關注的字段,也可以看到運維關注的字段,還有一些字段可能還是被多方關注的。
實際上,無論是應用開發、應用運維,還是 HPA 這樣的 K8s 自動化能力,它們都有可能需要控制一個 API 對象裡的同一個字段。最典型的情況就是副本數(replica)這種參數。但是,到底誰 own 這個字段,是一個非常棘手的問題。
綜上,既然 K8s 的定位是雲時代的 Linux Kernel,那麼 Kubernetes 就必須在 Operator 支援、API 層以及各類接口定義的完善上不斷進行突破,使得更多生态參與者可以更好的基于 K8s 建構自己的能力和價值。
阿裡巴巴大規模 Kubernetes 實踐
如今,Kubernetes 在阿裡經濟體的應用場景涵蓋了阿裡方方面面的業務,包括電商、物流、離線上計算等,這也是目前支撐阿裡 618、雙 11 等網際網路級大促的主力軍之一。阿裡集團和螞蟻金服内部運作了數十個超大規模的 K8s 叢集,其中最大的叢集約 1 萬個機器節點,而且這其實還不是能力上限。每個叢集都會服務上萬個應用。在阿裡雲 Kubernetes 服務(ACK)上,我們還維護了上萬個使用者的 K8s 叢集,這個規模和其中的技術挑戰在全世界也是首屈一指的。
孫健波透露,阿裡内部早在 2011 年便開始了應用容器化,當時最開始是基于 LXC 技術建構容器,随後開始用自研的容器技術和編排排程系統。整套系統本身沒有什麼問題,但是作為基礎設施技術團隊,目标一定是希望阿裡的基礎技術棧能夠支撐更廣泛的上層生态,能夠不斷演進和更新,是以,整個團隊又花了一年多時間逐漸補齊了 K8s 的規模和性能短闆。總體來看,更新為 K8s 是一個非常自然的過程,整個實踐過程其實也很簡單:
- 第一:解決應用容器化的問題,這裡需要合理利用 K8s 的容器設計模式;
- 第二:解決應用定義與描述的問題,這裡需要合理的利用 OAM,Helm 等應用定義工具和模型來實作,并且要能夠對接現有的應用管理能力;
- 第三:建構完整的應用傳遞鍊,這裡可以考慮使用和內建各種持續傳遞能力。
如上的三步完成,就具備了對接研發、運維、上層 PaaS 的能力,能夠講清楚自己的平台價值。接下來就可以試點開始,在不影響現有應用管理體系的前提下,一步步換掉下面的基礎設施。
Kubernetes 本身并不提供完整的應用管理體系,這個體系是整個雲原生的生态基于 K8s 建構出來的,可以用下圖表示:
Helm 就是其中最成功的一個例子,它位于整個應用管理體系的最上面,也就是第 1 層,還有 Kustomize 等各種 YAML 管理工具,CNAB 等打包工具,它們都對應在第 1.5 層。然後有 Tekton、Flagger 、Kepton 等應用傳遞項目,對應在第 2 層。Operator ,以及 K8s 的各種工作負載元件,比如 Deployment、StatefulSet,對應在第 3 層。最後才是 K8s 的核心功能,負責對工作負載的容器進行管理,封裝基礎設施能力,對各種不同的工作負載對接底層基礎設施提供 API 等。
初期,整個團隊最大的挑戰來自于規模和性能瓶頸,但這個解法也是最直接的。孫健波表示,随着規模逐漸增大,我們看到規模化鋪開 K8s 最大的挑戰實際上是如何基于 K8s 進行應用管理和對接上層生态。比如,我們需要統一的管控來自數十個團隊、數百個不同目的的 Controller;我們需要以每天近萬次的頻率傳遞來自不同團隊的生産級應用,這些應用的釋出、擴容政策可能完全不同;我們還需要對接數十個更加複雜的上層平台,混合排程和部署不同形态的作業以追求最高的資源使用率,這些訴求才是阿裡巴巴 Kubernetes 實踐要解決的問題,規模和性能隻是其中一個組成部分。
除了 Kubernetes 的原生功能外,在阿裡巴巴内部會開發大量的基礎設施以 K8s 插件的形式對接到這些功能上,随着規模的擴大,用統一的方式發現和管理這些能力成為了一個關鍵問題。
此外,阿裡巴巴内部也有衆多存量 PaaS,這些是為了滿足使用者不同業務場景上雲所建構的,比如有的使用者希望上傳一個 Java 的 War 包就可以運作,有的使用者希望上傳一個鏡像就可以運作。在這些需求背後,阿裡各團隊幫使用者做了許多應用管理的工作,這也是存量 PaaS 出現的原因,而這些存量 PaaS 與 Kubernetes 對接過程可能會産生各種問題。目前,阿裡正在通過 OAM 這個統一标準的應用管理模型,幫助這些 PaaS 向 K8s 底盤進行對接和靠攏,實作标準化和雲原生化。
解耦運維和研發
通過解耦,Kubernetes 項目以及對應的雲服務商就可以為不同的角色暴露不同次元、更符合對應使用者訴求的聲明式 API。比如,應用開發者隻需要在 YAML 檔案中聲明”應用 A 要使用 5G 可讀寫空間“,應用運維人員則隻需要在對應的 YAML 檔案裡聲明”Pod A 要挂載 5G 的可讀寫資料卷“。這種”讓使用者隻關心自己所關心的事情“所帶來的專注力,是降低 Kubernetes 使用者學習門檻和上手難度的關鍵所在。
孫健波表示,現在大多數的解法實際上是“悲觀處理”。比如,阿裡内部的 PaaS 平台,為了減輕研發使用的負擔,長期以來隻開放給研發設定 5 個 Deployment 的字段。這當然是因為 K8s YAML "all-in-one"的設計,使得完整的 YAML 對研發來說太複雜,但這也導緻 K8s 本身的能力,絕大多數情況下對研發來說是完全沒有體感的。而對 PaaS 平台運維來說,他反而覺得 K8s YAML 太簡單,不夠描述平台的運維能力,是以要給 YAML 檔案添加大量 annotation。
此外,這裡的核心問題在于,對運維人員而言,這種“悲觀處理”的結果就是他自己太“獨裁”,包攬了大量細節工作,還費力不讨好。比如擴容政策,目前就是完全由運維一方說了算。可是,研發作為編寫代碼的實際人員,才是對應用怎麼擴容最有發言權的,而且研發人員也非常希望把自己的意見告訴運維,好讓 K8s 更加 靈活,真正滿足擴容需求。但這個訴求在目前的系統裡是無法實作的。
是以,“研發和運維解耦”并不是要把兩者割裂,而是要給研發提供一個标準、高效的,同運維進行溝通的方式,這也是 OAM 應用管理模型要解決的問題。孫健波表示,OAM 的主要作用之一就是提供一套研發從自己的角度表達訴求的标準和規範,然後這套标準“你知,我知,系統知”,那麼上面這些問題也就迎刃而解了。
具體來說,OAM 是一個專注于描述應用的标準規範。有了這個規範,應用描述就可以徹底與基礎設施部署和管理應用的細節分開。這種關注點分離(Seperation of Conerns)的設計好處是非常明顯的。舉個例子,在實際生産環境中,無論是 Ingress、CNI 還是 Service Mesh,這些表面看起來一緻的運維概念,在不同的 Kubernetes 叢集中可謂千差萬别。通過将應用定義與叢集的運維能力分離,我們就可以讓應用開發者更專注應用本身的價值點,而不是”應用部署在哪“這樣的運維細節。
此外,關注點分離讓平台架構師可以輕松地把平台運維能力封裝成可被複用的元件,進而讓應用開發者專注于将這些運維元件與代碼進行內建,進而快速、輕松地建構可信賴的應用。OAM 的目标是讓簡單的應用管理變得更加輕松,讓複雜的應用傳遞變得更加可控。孫健波表示,未來,團隊将專注于将這套體系逐漸向雲端 ISV 和軟體分發商側推進,讓基于 K8s 的應用管理體系真正成為雲時代的主流。
嘉賓介紹:孫健波,阿裡巴巴技術專家。Kubernetes 項目社群成員。目前在阿裡巴巴參與大規模雲原生應用傳遞與管理相關工作,2015 年參與編寫《Docker 容器與容器雲》技術書籍。曾任職七牛,參與過時序資料庫、流式計算、日志平台等項目相關應用上雲過程。
今年 12 月 6-7 日北京 ArchSummit 全球架構師峰會上,孫健波老師會繼續分享《阿裡巴巴 Kubernetes 應用管理實踐中的經驗與教訓》,會介紹阿裡對解耦研發和運維過程中的現有實踐,以及實踐本身存在的問題;以及實施的标準化、統一化解決的思路,以及對社群的進一步思考。
“ 阿裡巴巴雲原生微信公衆号(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術公衆号。”
更多詳細資訊可關注
“阿裡巴巴雲原生”。