爲何咱們須要多集羣?
近年來,多集羣架構已經成爲「老生常談」。咱們喜歡高可用,喜歡異地多可用區,而多集羣架構天生就具有了這樣的能力。另外一方面咱們也但願經過多集羣混合雲來下降成本,利用到不一樣集羣各自的優點和特性,以便使用不一樣集羣的最新技術(如 AI、GPU 集羣等)。git
就是由於這種種緣由,多集羣幾乎成爲了雲計算的新潮流,而被談及最多而且落地的多集羣場景主要有這三類:github
一類用於應對「雲突發」。以下圖 1 所示,正常狀況下用戶使用本身的 IDC 集羣提供服務,當應對突發大流量時,迅速將應用擴容到雲上集羣共同提供服務,將多集羣做爲備用資源池。該模式通常針對無狀態的服務,能夠快速彈性擴展,主要針對使用 CPU、內存較爲密集的服務,如搜索、查詢、計算等類型的服務。
web
圖 1:多集羣「雲突發」場景設計模式
第二類用於「雲容災」。以下圖 2 所示,一般主要服務的集羣爲一個,另外一個集羣週期性備份。或者一個集羣主要負責讀寫,其餘備份集羣只讀。在主集羣所在的雲出現問題時能夠快速切換到備份集羣。該模式可用於數據量較大的存儲服務。
api
圖 2:多集羣「雲容災」場景安全
第三類則用於「異地多活」。如圖 3 所示,與「雲容災」的主要區別是數據是實時同步的,多集羣均可以同時讀寫。這種模式一般針對極其重要的數據,如全局統一的用戶帳號信息等。
websocket
圖 3:多集羣,異地多活場景網絡
可是多集羣同時也帶來了巨大的複雜性,一方面如何讓應用能夠面向多集羣部署分發,另外一方面是但願應用真正能作到多集羣之間靈活切換,想到傳統應用遷移的難度可能就已經讓咱們望而卻步了。面向多集羣,咱們依然缺少足夠成熟的應用交付和管理的能力。session
多集羣的最後一千米
早在 2013 年,很多老牌雲計算廠商就已經在聊「爲何要多集羣」,並開始倡導多集羣是「Next Big Thing」。架構
然而殘酷的現實倒是,每個不一樣的雲、每個數據中心都是一套本身的 API 與設計方式,所謂「多集羣」多數狀況下只是廠商 A 主動集成不一樣類型集羣的一套接入層。
這種背景下的多集羣一直以來都以架構複雜著稱,具體表現就是各個廠商發佈會上使人眼花繚亂的多集羣 / 混合雲解決方案架構圖,以下 圖 4 就是一個傳統的多集羣企業級解決方案架構圖,不得不說,咱們很難徹底理解圖中的全部細節。
圖 4:傳統的多集羣企業級解決方案架構圖
這種背景下的多集羣技術,其實更像是廠商對一個封閉產品的代名詞。不一樣廠商的雲有不一樣的 API、不一樣的能力特性,廠商們在這之上架構的多集羣、混合雲解決方案,大量的精力都是在適配和整合不一樣集羣平臺上的各種能力。
而對於用戶,最終的結果又會是另外一種形式的綁定。這樣的多集羣沒法造成生態,也許這就是咱們遲遲沒法面向這種多集羣構建統一的應用交付、構建真正多集羣能力的緣由。
Kubernetes:全世界數據中心的統一 API
不過,伴隨着雲原生理念的迅速普及,「步履蹣跚」的多集羣理念卻迎來了一個很是關鍵的契機。
從 2015 年 CNCF 成立到如今,短短四年多的時間,其組織下就孵化了數十個項目,吸引了近四百位企業級會員的加入,項目貢獻人數達到六萬三千多人,而每一年參與 CNCF 官方活動的人數也早已超過了十萬人, CNCF Lanscape 下符合雲原生標準的項目已經達到了上千個。
這種 Kubernetes 以及雲原生技術體系迅速崛起的直接結果,就是在全部公有云之上, Kubernetes 服務都已經成爲了毋庸置疑的一等公民;而全世界幾乎全部的科技公司和大量的企業終端用戶,也都已經在本身的數據中內心使用 K8s 來進行容器化應用的編排與管理。
不難看到,Kubernetes 正在迅速成爲全世界數據中心的統一 API。
圖 5:雲原生的曙光
這層統一而標準的 API 之下,多集羣和混合雲的能力纔開始真正體現價值。
Kubernetes 和它所推崇的聲明式容器編排與管理體系,讓軟件交付自己變得愈來愈標準化和統一化,而且實現了與底層基礎設施的徹底解耦;而另外一方面,雲原生技術體系在全部公有云和大量數據中內心的落地,使得軟件面向一個統一的 API 實現「一次定義,處處部署」成爲了可能。
Kubernetes API 在全世界數據中內心的普及,終於讓多集羣和混合雲理念有了一個堅實的事實基礎。而伴隨着軟件產業對提高效率、下降成本的巨大渴望,雲原生加持下的雲計算飛輪終於啓動,並將越飛越快。
多集羣時代的 「 The Platform for Platform」
你們可能據說過,Kubernetes 項目的本質實際上是 Platform for Platform,也就是一個用來構建「平臺」的「平臺」。
相比於 Mesos 和 Swarm 等容器管理平臺,Kubernetes 項目最大的優點和關注點,在於它始終專一於如何幫助用戶基於 Kubernetes 的聲明式 API ,快速、便捷的構建健壯的分佈式應用,而且按照統一的模型(容器設計模式和控制器機制)來驅動應用的實際狀態向指望狀態逼近和收斂。
而當 The Platform for Platform 的特質和多集羣鏈接在一塊兒, Kubernetes 的用戶實際上直接擁有了面向多集羣統一構建平臺級服務的寶貴能力。
好比, kubeCDN 項目就是這樣的一個典型案例,它的核心思想,就是直接基於全世界公有云上的 K8s 集羣來自建 CDN。藉助雲原生技術,巧妙的解決了使用傳統 CDN 廠商服務的不少痛點(包括安全性沒有保障、服務質量依賴外部廠商、CDN 廠商看重利潤忽視部分用戶需求、商業機密可能被泄露洞察等等)。在實現上,kubeCDN 在不一樣的區域構建 K8s 集羣,並經過 Route53 來根據延遲智能路由用戶的請求到最優的集羣。而做爲搭建 CDN 的基礎,Kubernetes 則幫助用戶整合了基礎設施,其自己統一的 API 又使得用戶能夠快速分發內容部署應用。
圖 6:CDN 場景的 K8s 多集羣
不難看到,基於 Kubernetes 的多集羣給了 kubeCDN 災備和統一多集羣資源的能力;而統一標準的 Kubernetes API 層,則把構建一個全球級別 CDN 的代價減小到了幾百行代碼的工做量。基於 K8s 的多集羣混合雲,正在爲不一樣的產業帶來了新的活力和更多的想象空間。
雲的將來,是面向多集羣的應用交付
若是說多集羣是雲計算的將來,那麼多集羣的將來又是什麼呢?
雲原生技術的發展路徑是持續輸出「事實標準的軟件」,而這些事實標準中,應用的彈性(resiliency)、易用性(usability)和可移植性(portability)是其所解決的三大本質問題。
應用的彈性對於雲產品的客戶來講等價於業務可靠性和業務探索與創新的敏捷性,體現的是雲計算所創造的客戶價值,應用彈性的另外一個關注點在於快速部署、交付、以及在雲上的擴縮容能力。這就須要完善的應用交付鏈路以及應用的雲原生開發框架支撐;
其次,良好易用性才能更好地發揮應用的彈性。在微服務軟件架構成爲主流的情形下,易用性須要考慮經過技術手段實現對應用總體作全局性的治理,實現全局最優。這凸顯了 Service Mesh 的服務能力;
最後,當應用具有良好的可移植性,實現多集羣和混合雲的戰略將成爲必然趨勢。
就像 K8s 是雲時代的操做系統,而在這操做系統之上構建的應用還須要一系列的開發、交付、管理工具。雲計算的價值,最終會迴歸到應用自己的價值。而如何服務好這些應用,將成爲雲廠商們新一輪能力的體現。
在這條路徑上,統一的雲原生應用標準定義和規範,通用的應用託管和分發中心,基於 Service Mesh 的、跨雲的應用治理能力,以及 K8s 原生的、面向多集羣的應用交付和管理體系,將會持續不斷的產生巨大的價值。
Kubernetes 項目在「多集羣」上的探索
當前 K8s 圍繞多集羣也已經開始了許多項目,如 Federation V2,Cluster Registry,Kubemci 等。在這以前更早開始的項目是 Federation v1,可是現在已經逐漸被社區所廢棄。這其中的主要緣由,在於 v1 的設計試圖在 K8s 之上又構建一層 Federation API,直接屏蔽掉了已經取得普遍共識的 K8s API ,這與雲原生社區的發展理念是相悖的。
而 RedHat 後來牽頭髮起的 Federation V2 項目, 則以插件的形式融入到 K8s API 中(即咱們熟悉的 CRD)。它提供了一個能夠將任何 K8s API type 轉換成有多集羣概念的 federated type 的方法,以及一個對應的控制器以便推送這些 federated 對象 (Object)。而它並不像 V1 同樣關心複雜的推送策略(V1 的 Federation Scheduler),只負責把這些 Object 分發到用戶事先定義的集羣去。
須要注意的是,這裏被推送到這些集羣上的對象,都來自於一個相同的模板,只有一些元數據會有差異。另外,被推送的 type 都須要製做 Fedrated type,這在 type 類型比較有限的時候才比較方便。
這也就意味着 Federation v2 的主要設計目標,實際上是向多集羣推送 RBAC,policy 等集羣配置信息:這些可推送資源類型是固定的,而每一個集羣的配置策略格式也是基本相似的。
因此說,Federation v2 的定位暫時只是一個多集羣配置推送項目。
然而,面向多集羣交付應用背後每每是有着複雜的決策邏輯的。好比:集羣 A 當前負載低,就應該多推一些應用上去。再好比,用戶可能有成百上千個來自二方、三方的軟件( 都是 CRD + Operator)要面向多集羣交付,在目前 Fed v2 的體系下,用戶要去維護這些 CRD 的 Fedreted type,代價是很是大的。
面向應用的 Kubernetes 多集羣架構初探
那麼一個以應用爲中心、圍繞應用交付的多集羣多集羣管理該具有何種能力呢?這裏面有三個技術點值得深刻思考:
用戶 Kubernetes 集羣多是沒有公網 IP、甚至在私有網絡當中的:而不管用戶的 Kubernetes 集羣部署在任何位置,多集羣服務都應該可以將它們接入進來,而且暴露完整的、沒有通過任何修改的 Kubernetes API。這是用戶進行應用交付的重要基礎。
以 GitOps 驅動的多集羣配置管理中心:用戶接入集羣的配置管理,須要經過一箇中心化的配置管理中心來推送和同步。但更重要的是,這些配置信息應該經過 GitOps、 以對用戶徹底公開、透明、可審計的方式進行託管,經過 Git 協議做爲多集羣控制中心與用戶協做的標準界面。
「託管式」而非「接管式」的統一鑑權機制:不管用戶是在使用的是公有云上的 Kubernetes 服務,仍是自建 IDC 集羣,這些集羣接入使用的鑑權證書是由統一機構頒發的。雲提供商,不該該存儲用戶集羣的任何祕鑰 (Credentials) 信息,而且應該提供統一的受權權限管理能力,容許用戶對接入的任何集羣作子用戶受權。
多集羣架構的基石:Kubernetes API 隧道
要將 Kubernetes 集羣以原生 API 的託管方式接入到多集羣管理體系當中,這背後主要的技術難點是「集羣隧道」。
集羣隧道會在用戶的 Kubernetes 集羣裏安裝一個 agent,使得用戶的集羣無需公網 IP,就能夠被用戶像使用公有云上的 Kubernetes 服務同樣在公網訪問,隨時隨地愉快的使用、管理、監控本身的集羣,擁有統一的鑑權、權限、日誌、審計、控制檯等等一系列的功能。
集羣隧道的架構也應該是簡潔的。以下圖 7 所示,其核心分爲兩層,下層是被託管的集羣,在其中會有一個 Agent,Agent 一方面在被託管的集羣中運行,能夠輕易的在內網訪問被託管的集羣,另外一方面它經過公網與公有云接入層中的節點 (Stub) 構建一個隧道 (tunnel)。在上層,用戶經過公有云統一的方式接入審計、鑑權、權限相關功能,經過訪問 Stub,再經過隧道由 Agent 向用戶本身的 Kubernetes 集羣轉發命令。
圖 7:多集羣 K8s 隧道架構
經過這樣的層層轉發,用戶可使用公有云統一的鑑權方式透明的使用被託管的集羣,而且公有云自己不該該觸碰和存儲用戶的鑑權信息。要實現這樣的集羣隧道,多集羣架構必需要能克服兩大難題:
在用戶訪問時,API 接入公有云統一的證書管理,包括鑑權、權限、子用戶受權等等。
在 API 轉發到用戶 Agent 時,再將請求變爲 K8s 集羣原有的受權訪問,被託管集羣的鑑權永遠只存在集羣自己。
這兩大難題,是現有的開源 Tunnel 庫、以及原生的四層轉發與七層轉發都不能徹底解決的,這裏一一列舉以下:
ngrok:一個曾經頗有名,可是目前已經被廢棄的項目,github 的 Readme 中明確的寫着,「不要在生產環境使用」;
go-http-tunnel:很簡潔的項目,可是一方面源碼的協議是 AGPL-3.0,意味着代碼沒法商用,另外一方面,在 kubectl 執行 exec 等命令時須要 hijack 鏈接,基於 http2 的 tunnel 在協議原理上就自然不知足這個功能;
chisel: 一樣很簡潔的項目,底層基於 TCP 構建鏈接,而後巧妙的利用了 ssh 實現 tcp 鏈接的 session 管理和多路複用。可是依然沒法解決在 tunnel 的一端 (Stub) 對接解析公有云的證書,驗證後又在另外一端 (Agent) 使用 K8s 的 token 發起新的請求;
rancher/remotedialer:rancher 的這個項目功能與 chisel 類似,基於 websocket,agent 直接把集羣的 token 傳遞到了 Server 端,須要存儲用戶本身的集羣鑑權信息,與咱們的目標不符;
frp: 一個大而全的項目,有不少如 UI、Dashboard 等功能,可是依然沒有直接知足咱們在 stub 端證書解析、agent 端 token 訪問需求;
apiserver-network-proxy:與 chisel 的功能很像,基於 grpc,剛開始沒多久的項目,一樣不能直接知足需求。
阿里雲 Kubernetes 服務多集羣架構
目前,在阿里雲 Kubernetes 服務中( ACK )提供的多集羣能力,遵循的正是上述「以應用爲中心」的多集羣架構。這個功能,以「接入已有集羣」做爲入口,以下圖所示:
圖 8:在阿里雲容器服務 Kubernetes 版上使用「接入已有集羣」能力
集羣隧道
圖 9:阿里雲的集羣隧道架構
這個多集羣架構如圖 9 所示,跟上一節所述是基本一致的。具體來講,阿里雲的 ACK 服務(容器服務 Kubernetes 版)會在用戶集羣上安裝一個 Agent,安裝完畢後 Agent 只須要可以公網訪問,用戶就能夠在 ACK 上使用本身的集羣,經過 ACK 統一的鑑權方式體驗原生的 K8s API。
長鏈接與長響應
在 Kubernetes 控制操做中,存在諸如 kubectl exec , kubectl port-forward 基於非 HTTP 協議的長鏈接以及 kubectl logs -f 這種反饋持續時間較長的長響應。它們對於通訊鏈路的獨佔使得 HTTP/2 的多路複用沒法運做,Go 語言官方庫中的 HTTP/1.1 自己也不支持協議升級,故而沒法採用原生七層 HTTP 轉發。
爲了解決這兩大難題,ACK 的隧道技術上採用了一系列策略進行應對:
使用原生七層轉發,對轉發數據進行證書識別,將 Kubernetes 權限注入,解決鑑權問題;
對於協議升級請求,劫持七層鏈路,使用四層鏈路,進而使用原生四層無感知轉發,解決長鏈接問題;
只在發送請求方向上覆用鏈路,每次反饋創建新鏈路,防止阻塞,解決長響應問題。
隧道高可用
除此以外,在 ACK 的隧道設計中,因爲中間的鏈路(Agent 與 Stub)對於用戶而言是透明的,在客戶端以及目標集羣的 API Server 正常運轉的狀況下,不能由於中間鏈路的故障致使沒法鏈接,所以 ACK 隧道還提供了 Agent 與 Stub 的高可用能力,提升容錯力,下降故障恢復時間。
Agent 高可用
容許多個 Agent 同時鏈接 Stub,多個 Agent 的存在不只能夠高可用,還能夠做爲負載均衡來使用。
多 Agent 負載均衡 :一方面,每一個 Agent 會定時向 Stub 發送當前的可用狀態,另外一方面,Stub 進行數據包轉發時,採用隨機輪詢的方式,選擇一個可用的 Agent 轉發;
多集羣防干擾、集羣切換:在多 Agent 的存在下,可能會涉及到 Agent 來自不一樣的 Kubernetes 集羣形成干擾,因此一樣須要加入 Agent 的集羣惟一 ID。當原先集羣的全部鏈接都斷開時,會進行集羣切換。
Stub 高可用
在 Stub 端,因爲客戶端只會向同一個 IP 發送,多個 Stub 的存在須要使用 Kubernetes 的 Service 進行協調,例如可使用 LoadBalancer。可是,若是使用 LoadBalancer 對請求進行分流,一個重要問題是,因爲長鏈接的存在,從客戶端發出的信息多是上下文相關的而非互相獨立的。TCP 四層分流會破壞上下文,因此 Stub 在同一時刻應當只能有一個在起做用。
在只有一個 Stub 運行的狀況下,依然要保證其高可用,這裏 ACK 隧道採用了 Kubernetes 的 Lease API 等高可用能力。所以 Stub 端的高可用雖然不能像 Agent 端同樣起到分流分壓做用,可是它提供滾動升級等能力。
結語
雲的邊界正在被技術和開源迅速的抹平。愈來愈多的軟件和框架從設計上就再也不會跟某雲產生直接綁定。畢竟,你沒辦法撫平用戶對商業競爭擔心和焦慮,也不可能阻止愈來愈多的用戶把 Kubernetes 部署在全世界的全部雲上和數據中內心。
在將來雲的世界裏,K8s 會成爲連通「雲」與「應用」的高速公路,以標準、高效的方式將「應用」快速交付到世界上任何一個位置。而這裏的交付目的地,既能夠是最終用戶,也能夠是 PaaS/Serverless ,甚至會催生出更加多樣化的應用託管生態。「雲」的價值,必定會迴歸到應用自己。
多集羣與混合雲的時代已經來臨,以應用爲中心的多集羣多集羣架構,纔是雲計算生態發展的必然趨勢,你的雲能夠運行在任何地方,而咱們幫你管理。讓咱們一塊兒迎接面嚮應用的雲原生多集羣時代,一塊兒擁抱雲原生,一塊兒關注應用自己的價值!
做者介紹:孫健波,阿里雲容器平臺技術專家,Kubernetes 項目社區成員,負責 ACK 容器服務相關開發工做。殷達,清華大學與卡內基梅隆大學計算機專業在讀研究生,於阿里雲容器平臺部實習,主要參與 ACK 容器服務多雲技術及雲原生應用開發。