阿里巴巴基於 Kubernetes 的實踐經驗

本文整理自孫健波在 ArchSummit 大會 2019 北京站演講稿記錄。首先介紹了阿里巴巴基於 Kubernetes 項目進行大規模應用實踐過程當中遇到的問題;隨後會逐一介紹解決這些問題的現有實踐及其自己存在的侷限性;最後會介紹阿里巴巴目前正在進行的嘗試和社區在這一領域的發展方向。前端

現在,阿里巴巴內部維護了數十個大規模的 K8s 集羣,其中最大的集羣約 1 萬個節點,每一個集羣會服務上萬個應用;在阿里雲的 Kubernetes 服務 ACK 上,咱們還維護了上萬個用戶的 K8s 集羣。咱們在必定程度上解決了規模和穩定性問題以後,發現其實在 K8s 上管理應用還有很大的挑戰等着咱們。git

應用管理的兩大難題

今天咱們主要討論這兩個方面的挑戰:github

對應用研發而言,K8s API 針對簡單應用過於複雜,針對複雜應用難以上手;
對應用運維而言,K8s 的擴展能力難以管理;K8s 原生的 API 沒有對雲資源所有涵蓋。web

整體而言,咱們面臨的挑戰就是:如何基於 K8s 提供真正意義上的應用管理平臺,讓研發和運維只需關注到應用自己。數據庫

研發對應用管理的訴求

1. K8s all in one 的 YAML 文件

讓咱們來看一下這樣一個 K8s 的 yaml 文件,這個 yaml 文件已是被簡化過的,可是咱們能夠看到它仍然仍是比較長。緩存

面對這樣一個廣受「複雜」詬病的 YAML 文件,我相信你們都會忍不住想該怎麼簡化。網絡

自上而下,咱們大體把它們分爲三塊:併發

  • 一塊是擴縮容、滾動升級相關的參數,這一塊應該是應用運維的同窗比較關心的;
  • 中間一塊是鏡像、端口、啓動參數相關的,這一塊應該是開發的同窗比較關心的;
  • 最後一塊你們可能根本看不懂,一般狀況下也不太須要明白,能夠把它們理解爲 K8s 平臺層的同窗須要關心的。

看到這樣一個 yaml 文件,咱們很容易想到,只要把裏面的字段封裝一下,把該暴露的暴露出來就行了。確實,咱們內部就有 PaaS 平臺這麼作。負載均衡

2. 只透出部分字段:簡單卻能力不足

內部的某個 PaaS 平臺精心挑選了部分字段,並作了一個漂亮的前端界面給用戶,只透出給用戶 5 個左右的字段,大大下降了用戶理解 K8s 的心智負擔。而後底層實現用相似模板的方式把用戶這五個字段渲染出來一個完整的 yaml 文件。運維

突出的字段大概以下圖所示:

不得不說這種方式是很是有效的,針對簡單無狀態的應用,精簡 API 能夠大大下降 K8s 的門檻,快速而且高效的對接用戶,PaaS 平臺也順利讓你們使用了起來。同時,我也從一些技術分享中瞭解到許多其餘公司也是用這種相似的方式簡化的 K8s API。

可是當用戶的業務開始大規模對接之後,咱們就會天然而然遇到有狀態的複雜應用,用戶就會開始抱怨 PaaS 平臺能力不夠了。好比咱們的 Zookeeper 多實例選主、主從切換這些邏輯,在這五個字段裏就很難展開了。

歸根結底就是屏蔽大量字段的方式會限制基礎設施自己的能力演進,可是 K8s 的能力是很是強大而靈活的。咱們不可能爲了簡化而放棄掉 K8s 強大的能力。

就好比當前這個例子,咱們很容易想到,針對複雜有狀態的應用,應該經過 K8s 裏面的 CRD 和 Operator 來解決。

3. CRD+Operator: K8s 擴展能力強大卻難以上手

確實,咱們內部對接複雜應用雲原生化的時候,也推薦他們編寫 Operator,可是常常出現這樣一段對話。

中間件的工程師跟咱們說,我這有個 Zookeeper 該用哪一種 K8s 的 Workload 接入啊?咱們想了想,K8s 設計如此精妙,天然沒有解決不了的問題,因而咱們推薦他們使用 Operator。他們就懵了,說大家搞雲原生的這幾年造新詞的能力絕對一流,以前都沒據說過。

想一想也是,業務方理解這些新概念不難,可是真的要本身去上手實現,仍是很是困難的。咱們天然也以爲業務方更應該專一於他們的業務自己,因而咱們不得不幫他們一塊兒寫。

能夠看到,咱們亟需一個統一的模型去解決研發對應用管理的訴求。

運維對應用管理的訴求

除了研發側的問題以外,咱們在運維側也遇到了很大的挑戰。

1. 運維能力衆多卻難以管理

K8s 的 CRD Operator 機制很是靈活而強大,不光是複雜應用能夠經過編寫 CRD Operator 實現,咱們的運維能力也大量經過 Operator 來擴展,好比灰度發佈、流量管理、彈性擴縮容等等。

咱們經常讚歎於 K8s 的靈活性,它讓咱們基礎平臺團隊對外提供能力很是方便,可是對應用運維來講,他們要使用咱們提供的這些運維能力,卻變得有些困難。

好比咱們上線了一個 CronHPA,能夠定時設置在每一個階段會根據 CPU 調整實例數的範圍。應用運維並不知道跟原生不帶定時功能的 HPA 會產生衝突,而咱們也沒有一個統一的渠道幫助管理這麼多種複雜的擴展能力,結果天然是引發了故障。這血的教訓提醒咱們要作事前檢查,熟悉 K8s 的機制很容易讓咱們想到爲每一個 Operator 加上 admission webhook。

這個 admission webhook 須要拿到這個應用綁定的全部運維能力以及應用自己的運行模式,而後作統一的校驗。若是這些運維能力都是一方提供的還好,若是存在兩方,甚至三方提供的擴展能力,咱們就沒有一個統一的方式去獲知了。

事實上若是咱們想的更遠一些就會發現,咱們須要一個統一的模型來協商並管理這些複雜的擴展能力。

2. 雲資源難以描述和統一交付

當咱們把應用的 Operator 以及對應的運維能力都寫好之後,咱們很容易想到要打包交付這個應用,這樣不管是公有云仍是專有云均可以經過一個統一的方式去交互。社區的主流方式目前就是使用 Helm 來打包應用,而咱們也採用了這樣的方式給咱們的用戶交付,可是卻發現咱們的用戶需求遠不止於此。

雲原生應用有一個很大的特色,那就是它每每會依賴雲上的資源,包括數據庫、網絡、負載均衡、緩存等一系列資源。

當咱們使用 Helm 打包時,咱們只能針對 K8s 原生 API,而若是咱們還想啓動 RDS 數據庫,就比較困難了。若是不想去數據庫的交互頁面,想經過 K8s 的 API 來管理,那就又不得不去寫一個 CRD 來定義了,而後經過 Operator 去調用實際雲資源的 API。

這一整套交付物實際上就是一個應用的完整描述,即咱們所說的「應用定義」。但事實上,咱們發現「應用定義」這個東西,在整個雲原生社區裏實際上是缺失的。這也是爲何阿里巴巴內部有不少團隊開始嘗試設計了本身的「應用定義」。

這種定義方式最終全部的配置仍是會所有堆疊到一個文件裏,這跟 K8s API all-in-one 的問題實際上是同樣的,甚至還更嚴重了。並且,這些應用定義最終也都成爲了黑盒,除了對應項目自己可使用,其餘系統基本沒法複用,天然就更沒法使得多方協做複用了。

3. 每一個公司和團隊都在本身定義應用

不光是阿里巴巴內部的團隊須要應用定義,事實上幾乎每一個基於 K8s 管理應用的公司和團隊都在本身定義應用。以下所示,我就搜到了兩家公司的應用定義:

應用定義其實是應用交付/分發不可或缺的部分。可是在具體的實踐中,咱們感覺到這些內部的應用定義都面臨着以下的問題:

  • 定義是否足夠開放,是否能夠複用?
  • 如何與開源生態協做?
  • 如何迭代與演進?

這三個問題帶來的挑戰都是巨大的,我在上文已經提到,一個應用定義須要容易上手,但又不失靈活性,更不能是一個黑盒。應用定義一樣須要跟開源生態緊密結合,沒有生態的應用定義註定是沒有將來的,天然也很難持續的迭代和演進。

區分使用者的分層模型與模塊化的封裝

讓咱們回過頭來從新審視咱們面臨的挑戰,歸根結底在於 K8s 的 All in One API 是爲平臺提供者設計的,咱們不能像下圖左側顯示的同樣,讓應用的研發、運維跟 K8s 團隊同樣面對這一團 API。

一個合理的應用模型應該具備區分使用者角色的分層結構,同時將運維能力模塊化的封裝。讓不一樣的角色使用不一樣的 API,正如上圖右側部分。

OAM:以應用爲中心的 K8s API 分層模型

OAM(Open Application Model) 正是這樣一個以應用爲中心的 K8s API 分層模型:

  • 從研發的角度,他操做和關注的 API 對象叫 Component;
  • 從運維的角度,模塊化的運維能力封裝就是 Trait,而運維能夠經過 App Config 將 Component 和 Trait 自由組合,最終實例化成一個運行的應用;
  • K8s 團隊自己則仍然基於 K8s 的原生 API 迭代這一層能力。

針對研發時常抱怨的 K8s API 太複雜,咱們經過關注點分離,區分使用者面對的 API 來解決,同時提供了幾種核心的 Workload,讓研發只須要填寫少數幾個字段就能夠完成組件的定義;針對複雜應用定義,咱們經過擴展的 Workload,容許研發對接 CRD Operator 的方式對接自定義 Workload。

針對運維須要的模塊化封裝運維能力和全局管理的需求,OAM 模型經過 Trait 來提供。

Trait 是運維能力的體現,不一樣的 Trait 也對應了不一樣類型的運維能力,如日誌收集 Trait、負載均衡 Trait、水平擴縮容 Trait 等等;同時 OAM 自己就提供了一個全局管理的標準,OAM 模型的實現層能夠輕鬆針對 OAM 定義裏的種種 Trait 描述進行管理和檢查。

針對雲資源,OAM 向上也提供了統一的 API,也是經過關注點分爲三類:

一類是研發關注的雲資源,如數據庫 RDS、對象存儲 OSS 等,經過擴展 Workload 接入;

另外一類是運維關注的雲資源,如負載均衡 SLB 等,經過 Trait 接入;

最後一類也是運維關注的雲資源,可是可能包含多個應用之間的聯動關係,如虛擬專有網絡 VPC 等,經過應用的 Scope 接入。Scope 則是 OAM 中管理多應用聯動關係的概念。

能夠看到,OAM 經過統一的一套標準,解決了咱們今天提到的全部難題。讓咱們繼續深刻到 OAM 中看看不一樣的概念具體是什麼。

1. OAM Component:研發關注的 API

Component 就是 OAM 模型提供給研發的 API 對象,以下所示:

能夠看到 Component 自己就是一個 K8s 的CRD,spec 字段裏面的部分就是 Component 具體的定義。其中第一個重要的字段就是 workloadType,這個決定了應用的運行模式。

針對簡單應用,OAM 提供了 6 種核心 Workload,以下表所示:

主要經過是否可訪問、是否可複製、是否長久運行來區分。如 Server,就表明了你們最經常使用的 K8s 裏面 Deployment+Service 的組合。

填寫了核心 workloadType 的 Component,只須要定義 Container 裏的注入鏡像、啓動參數等字段,就如咱們最開始所說的屏蔽掉大量字段的 PaaS 同樣,爲用戶大大下降了門檻。

而針對複雜的有狀態應用,OAM 則容許經過擴展 Workload 來實現,以下圖所示,咱們能夠定義一個新的叫 openfaas 的 WorkloadType,它的定義實際上徹底等價於一個 CRD 定義。

OAM 模型中,使用自定義的 Workload 也是經過 Component,只是 WorkloadType 改成你自定義的 WorkloadType 名稱。

2. OAM Trait:可發現、可管理的運維能力

Trait 就是模塊化的運維能力,咱們能經過命令行工具發現一個系統裏支持哪些 Traits(運維能力)。

這時候,運維要查看具體的運維能力該怎麼使用,是很是簡單的:

能夠看到,他能夠在 Trait 定義裏清晰的看到這個運維能力能夠做用於哪一種類型的 Workload,包括能填哪些參數、哪些必填/選填、參數的做用描述是什麼。你也能夠發現,OAM 體系裏面,Component 和 Trait 這些 API 都是 Schema,因此它們是整個對象的字段全集,也是瞭解這個對象描述的能力「到底能幹嘛?」的最佳途徑。

事實上,你們可能已經發現,Trait 的定義和 CRD 是對等的,而你徹底也能夠經過 Operator 實現 Trait。

因此 OAM 事實上將本來散亂的 Operator 經過不一樣的角色有機的管理起來了。

3. OAM Application Config:組裝 Component 和 Trait,應用實例化運行

Component 和 Trait 最終經過 Application Configuration 結合,並真實運行起來。

更重要的是,這個 OAM 應用描述文件是徹底自包含的,也就是說經過 OAM YAML,做爲軟件分發商,咱們就能夠完整地跟蹤到一個軟件運行須要的全部資源和依賴。這就使得如今對於一個應用,你們只須要一份 OAM 的配置文件,就能夠快速、在不一樣運行環境上把應用隨時運行起來,把這種自包含的應用描述文件完整地交付到任何一個運行環境中。

而咱們圖中的 Rudr 項目就是 OAM 的一個實現,也能夠理解爲 OAM 的一個解釋器,將 OAM 的統一描述轉換爲背後衆多的 Operator。

同時 Rudr 也是一個統一管理的媒介,若是 Application Configuration 中出現了一個 Component 綁定 2 個 Trait 而且互相沖突的狀況,就能夠快速被檢驗並發現問題,以下圖所示:

一樣,包括複雜應用的編排、雲資源的拉起、Workload 與 Trait 交互等等,均可以在這個 OAM 解釋器中實現。

你們能夠經過 Rudr 項目中的教程文檔體驗 OAM 的這些交互過程。

OAM 加持下的 Kubernetes PaaS

事實上,OAM 加持下的 PaaS 基於 Kubernetes,將衆多 Operator 分層的管理了起來。

對於研發,一般他關心的應用多是一個由 web 和數據庫組合而成的應用,數據庫組件的背後多是一個 RDS Operator 實現。web 應用背後,則能夠是咱們開源的 K8s 原生 StatefulSet的加強項目 OpenKruise,OpenKruise 中提供的包括原地升級等加強能力則經過 Trait 的方式去配置。而額外的一些監控報警、日誌等能力,則由一個個獨立的 Operator 去實現,由運維在第二層去關注和管理。

最終 K8s 團隊聯合各類基礎軟件的提供商,圍繞 K8s 原生 API,以 Operator 的形式不斷提供擴展能力,經過 OAM 這樣統一的規範和標準向外標準化輸出。

更重要的是,OAM 的統一描述大大提升了 Operator 的複用能力,使得 Operator 的編寫主須要關注業務邏輯自己。好比原先你寫一個 Zookeeper Operator,你須要寫實例的服務發現、須要寫升級時主備切換的編排邏輯、須要寫實例備份的邏輯,而這一切在 OAM 的標準化下,你將能夠輕鬆在社區找到相似組成部分。

OAM 加持下的 Kubernetes PaaS,使得不一樣的 Operator 能夠像樂高積木同樣靈活組裝,使得應用定義成爲了社區共同建設的項目,使得應用管理變得統一,功能卻更增強大!

最後

最後,給你們分享一下 OAM 項目近期的計劃,OAM 是一個徹底屬於社區的應用定義模型,咱們很是但願你們都能參與進來。

經過 Gitter 直接參與討論,詳情點擊這裏

咱們會集成 OpenFaaS、Terraform、Knative,支持不一樣的 Workload,讓 OAM 能夠對接不一樣的實現;咱們會針對 K8s Operator 提供一鍵接入的轉換方式,讓如今的 Operator 快速融入OAM。

咱們也會開源一個 oam-framework 項目,這個項目能夠快速構建一個 OAM 的實現,相似 kubebuilder、Operator-sdk 快速構建 Operator 同樣,oam-framework 會幫助你快速構建 OAM 實現。

咱們還會構建一個 CRD (traits/workloads) Registry 項目,可讓你們註冊本身的 OAM 實現、自定義 Workload、Trait 等等資源,以便最大程度的實現社區中你們的協做與複用。

OAM 規範地址,點擊這裏

OAM 開源實現地址,點擊這裏


本文做者:中間件小哥

原文連接

本文爲阿里雲內容,未經容許不得轉載。

相關文章
相關標籤/搜索