不!我們不使用 Kubernetes!

一篇關於《爲什麼使用 Kubernetes 擴展規模意味着 “做幾乎相同的事情,卻來得更復雜”》的帖子在網上瘋傳,以至於刊登這篇文章的網站因流量過大而癱瘓。

作者是 Ably 公司的基礎設施主管 Maik Zumstrull。

我們 Ably 運行着一個大規模的生產級基礎設施,爲我們的客戶在全球的實時消息傳遞應用提供技術支持。與大多數科技公司一樣,該基礎設施主要依賴軟件;而且與大多數科技公司一樣,軟件主要在 Docker 容器中部署和運行。

如果您一直關注技術領域,可能會立馬想到這個問題:

“那麼…… 你們使用 Kubernetes 嗎?”

新老客戶、對我們的平臺感興趣的開發人員以及面試 Ably 職位的求職者都提出過這個問題。有意思的是,甚至幾個求職者放棄了工作機會,聲稱理由是我們不使用 Kubernetes!

這也是我們在規劃長期基礎設施路線圖時問自己的一個問題:我們是否應該在某個時候使用 Kubernetes 作爲主要的部署平臺?

爲何是 Kubernetes?

Kubernetes 是最廣爲人知的系統,用於大規模編排容器化軟件。雖然外頭有不同的聲音,但它仍基本上處於炒作週期的頂峯——常常讓人覺得大家都在 Kubernetes 上運行,或至少大家都在談論希望如何將一切轉移到 Kubernetes。Mesos 的人氣急劇下滑,Docker Swarm 成了不受待見的話題;如果你仍在部署到普通的 EC2 實例,你很可能就是老古董。

Kubernetes 優點多多。它是由大規模生產級工作負載方面經驗豐富的工程師開發的,運用了來自谷歌的 Borg 編排系統的實用的可靠技術。它受到無數廠商的支持;這年頭沒有官方的 Docker 鏡像和 Kubernetes 部署指南,都不好意思發佈軟件產品。

有點令人驚訝的是,Kubernetes 從靈感源頭 Borg 繼承而來的初衷所剩無幾,這個初衷就是將數量龐大的裸機系統轉變成私有云環境。今天 Kubernetes 似乎主要部署在虛擬機上,最常見的是在公共雲提供商上。公共雲是當今許多組織部署 Kubernetes 的主要動因所在:它被視爲統一的 API 層,使多雲部署對您的 DevOps 人員而言很透明。

即使在單個雲中,Kubernetes 開發者體驗也備受稱道。開發人員已經很熟悉 Docker, 而 Kubernetes 很容易讓相同的容器在生產環境中運行。藉助命名空間、內置的資源管理以及內置的虛擬網絡功能或服務網格,它還允許部署由不同團隊維護的多個交互服務,而不會相互干擾。

Ably 做了什麼?

Ably 是公共雲客戶。我們的整個生產環境完全放在 AWS 上,目前沒有使用別的雲環境。我們在 EC2 實例上運行。機器總數在一天內隨自動擴展機制而變化,但始終至少有數千臺,橫跨十個 AWS 區域。這些機器確實運行 Docker,我們的的大部分軟件部署在容器中。

Ably 的雲架構示意圖,沒有 Kubernetes

我們不使用任何知名的運行時編排層。每個實例創建時,已經基於它所在的自動擴展組知道運行哪些容器。作爲啓動鏡像一部分的每個實例上的小型自定義啓動服務查看實例配置,提取合適的容器鏡像,然後啓動容器。

在實例的整個生命週期中,容器集是相同的。根本沒有決定將實例從 “核心” 轉換成 “前端” 或之類東西的調度器服務:想改變集羣的配置,創建或銷燬整個實例,不是被告知運行一組不同的容器。每個實例上都有輕量級監控服務:如果實例消亡,會重新生成所需的容器,如果運行的任何軟件版本不再是該集羣的首選版本,它會自行終止該實例。

至於流量處理方面,我們使用 AWS 網絡負載均衡器(NLB)。由於一個自動擴展組對應一個生產級服務,我們可以使用普通的 AWS 方法:將一個 NLB 指向一個自動擴展組作爲目標組,不需要額外的抽象層。

至於內部的服務到服務通信(可以稱之爲 “服務網格”),我們使用…… 網絡。由於服務不是在機器上任意混合,機器自動分配的 IP 地址足以滿足我們的用途。

如果您不打算使用 Kubernetes,爲何使用 Docker?

Docker 仍是部署軟件的一種相當方便的方式,軟件用大量使用依賴項的語言(Node、Python 和 Ruby 等)編寫時尤其如此。在這種情況下,可部署單元是複雜目錄樹中成千上萬個相互依賴的文件,外加需要是源樹快照的完全正確版本的執行運行時環境。

我們過去常將構建的軟件作爲簡單的打包文件(又叫 slug)來分發,每個實例上的管理服務負責下載和拆包它們。功能上,我們做的仍然一樣,因爲 Docker 鏡像就是一堆捆綁了元數據 JSON blob 的打包文件,但是 curl 和 tar 已換成了 docker pull。

(並非工程團隊中的每個人都一致認爲這是改進,那是另一篇博文探討的話題。)

這種架構有多靈活?

資源管理

說到資源管理,我們根據服務的需求決定使用哪種類型的 EC2 實例。沒必要弄清楚如何將較小的服務打包到較大的實例上;在弄清楚如何將小型虛擬機打包到大型物理機上這個方面,亞馬遜至少比我們多十年的經驗,所以我們讓亞馬遜處理這些細節。

Right Sizing(優化規模)如下:大多數軟件服務只能有效地使用一定數量的資源。有兩個線程的進程不需要 16 個 CPU;一分鐘只寫入一次磁盤的進程不需要每秒可寫入 90000 次的 SSD 存儲;替代的 CPU 架構可能有更高的性價比。從衆多 AWS 產品中挑選合適的組件讓我們得以最大限度地減少開銷和控制成本,最終爲我們的客戶降低每條消息的費用。

自動擴展

EC2 實例組知道如何自動增加或減少組中的實例數量以滿足需求。可用的工具類似 Kubernetes。很顯然,我們針對 AWS 設計的產品不會直接在其他任何雲提供商上運行,但眼下我們不使用任何其他雲提供商。

當然,仍可以手動管理容量。每個自動擴展組中所需的實例數量可以隨時手動設置,自動擴展策略隨後可以接過重任,根據系統負載高低來增減數量。

客戶實際使用多少服務,我們收取多少費用。任何空閒容量的預算都出自我們的口袋,因此我們需要儘可能提高效率,同時即使在意外的負載高峯期間也能保證爲我們的客戶提供良好的服務水準。

入站流量

拋開我們遇到的具體的實施錯誤不談,入站流量是各大雲提供商都已解決的問題——也就是說,前提是您可以始終如一地將接受外部流量的服務映射到它正在運行的那羣機器。

客戶流量可能直接抵達我們的其中一個 NLB,也可能先通過 CloudFront 繞道而行。從每個區域內運行的服務的角度來看,這沒有什麼區別。

無論在哪種情況下,在每個區域使用負載均衡器是實現橫向擴展和靈活性的另一種手段——在這種情況下,可以處理連接數量的大幅度變化,比如重大體育賽事開始、吸引成千上萬的觀衆時。

DevOps

爲了確保我們的工程師能積極參與管理我們的生產級系統這項工作,開發人員可以設置單一的配置值——“該集羣現在務必應運行這個組件的這個版本”,隨着時間的推移,該服務的所有實例都將換成運行新版本的實例。

使用 Kubernetes 又如何?

如果我們將生產環境遷移到 Kubernetes,我們的環境和流程會如何變化(但願改進)?

鑑於我們的基礎設施團隊規模有限,唯一值得考慮的方案是,使用與 AWS 全面集成的託管 Kubernetes。鑑於我們的產品需要全球部署,我們至少需要十個集羣(十個區域各一個)。

如果我們將生產環境遷移到 Kubernetes,Ably 的架構會是這樣子

資源管理

通過 Kubernetes 管理資源時,我們會使用大型實例(可能是最大的可用實例,即. metal 類別),並將它們與容器一起打包,而不是使用大小適合每個服務的 EC2 實例。

打包服務器的一個小優點是使用現有機器上的空閒資源,而不是額外的機器以滿足佔用資源少的服務的需要。它還有這一個大缺點:在同一臺機器上運行異構服務,因而爭奪資源。這不是新的棘手問題:雲提供商在虛擬機方面有同樣的問題,名爲 “嘈雜的鄰居”。然而,雲提供商在其系統中擁有十年來的祕訣,可以儘量爲客戶緩解這個問題。在 Kubernetes 上,您得自行解決該問題。

一種可能的方法是在使用 Kubernetes 時,嘗試保留 “一個虛擬機,一個服務” 模式。Kubernetes minion 不必一模一樣,它們可以是不同大小的虛擬機,Kubernetes 調度約束條件可用來在每個 minion 上就運行一個邏輯服務。不過這提出了一個問題:如果您在特定的 EC2 實例組上運行固定的容器集,爲什麼要多一個 Kubernetes 層而不是就這麼做?

自動擴展

說到改用 Kubernetes,服務的自動擴展看起來很相似:公開自定義的 “當前利用率” 指標,定有根據需要添加或刪除容器的規則。當然,只有集羣節點上有可用容量時,Kubernetes 集羣才能啓動額外的服務 pod。正因爲如此,我們需要部署擁有大量空閒容量的節點,並添加集羣自動擴展器(Cluster Autoscaler),以便按需創建更多節點。

對於集羣自動擴展器而言,擴展集羣比較簡單——“沒有所需的空閒容量時,添加節點”。然而,縮小集羣變得複雜起來:您最終面臨的可能是基本上空閒的節點,但這不是空節點。剩餘的 pod 需要遷移到其他節點以創建一個空節點,然後終止該節點以縮小集羣。

自動擴展方面的結論是,它應該仍像現在一樣運作,但是我們將解決兩個自動擴展問題而不是一個自動擴展問題,而且它們都比我們現在面臨的一個問題來得複雜。按需或計劃的容量管理(手動干預)會稍微複雜一點,因爲我們先要確保有足夠的 Kubernetes 節點,然後確保有足夠的 pod 用於所需的服務。

入站流量

換成 Kubernetes 的話,入站流量會很輕鬆。EKS 團隊在這方面做出了幾個值得稱道的設計選擇:如果集羣以這種方式配置,每個 pod 收到一個與 VPC(EC2 的虛擬網絡層)完全集成的由 AWS 管理的 IP 地址。集羣內運行的東西可直接訪問這些 IP 地址。

當 Ingress(入站)或 Service(服務)部分被添加到服務的 Kubernetes 規範時,控制器會自動創建 AWS 負載均衡器,並將它們直接指向合適的 pod 集。總的來說,這不會比我們現在公開流量路由實例的方式來得複雜。

當然,這裏隱藏的缺點是這種出色的集成程度完全是 AWS 特有的。對於任何嘗試使用 Kubernetes 來實現多雲的人來說,它不是很有幫助。

DevOps

在 Kubernetes 環境中,軟件版本管理在功能上與我們現在擁有的非常相似。我們的開發人員將在 Kubernetes 部署中指定新的目標版本,pod 就會進行滾動替換,而不是在我們的自定義配置系統中指定新的目標版本,所有 EC2 實例就會自動進行滾動替換。

但還有其他好處嗎?

前面部分可以總結如下:我們所做的事大部分一樣,卻來得更復雜了。如果在 Kubernetes 上運行帶來我們討論如何移植現有基礎設施時沒有考慮到的附帶好處,這麼做可能是值得的。不妨看一下通常被稱爲是 Kubernetes 優點的另幾個好處,看看它們是否對我們有幫助。

多雲就緒

每個人都應該擁有多雲戰略!除非它不該擁有。

我們發覺自己屬於 “不該擁有” 這個羣體,目前並未奉行該策略。我們也不完全相信 Kubernetes 是實現多雲就緒的好方法。一旦服務需要訪問自個集羣外的服務,或者需要從自個集羣外可以訪問,或者使用任何類型的持久存儲,各大雲提供商之間的差異確實很重要,Kubernetes 無法成功地抽取掉這些差異、以至於您的開發人員不必關心。

如果您仍需要一種策略來部署到 AWS 上的 Kubernetes,需要另一種相似但不同的策略來部署到 GCP 上的 Kubernetes,那麼採用相似但不同的策略來部署到 AWS 和 GCP、不用 Kubernetes 會困難得多嗎?

混合雲就緒

我們認爲,管理混合雲或本地環境(或換句話說,管理您自己的物理機器)是部署 Kubernetes 的正當理由。說來也巧,這也是最初設計 Borg 以實現的目標。如果我們準備開始構建自己的物理數據中心而不是使用公共雲資源,我們在其中安裝的幾乎肯定是裸機 Kubernetes 集羣。

另一種選擇是嘗試構建基於虛擬化技術的私有云,許多組織選擇這麼做。然而,我們憑以往構建這種環境的經驗就知道,這絕不是一種省錢或輕鬆的選擇。

不過,我們沒準備開始搞自己的數據中心。我們仍需要將規模擴大數倍,那樣自己搭建硬件的好處才能證明在我們的工程部門設立物理基礎設施小組的成本是合理的。

基礎設施即代碼

基礎設施即代碼是我們已經在做的事情,使用 CloudFormation、Terraform 以及我們自己的自定義工具。爲 Kubernetes 編寫 YAML 文件不是管理基礎設施即代碼的唯一方法,在許多情況下,這甚至不是最合適的方法。

擁有龐大而活躍的社區

使用 Kubernetes 的一個常被提及的好處是有龐大的用戶社區可以交流問題和建議。但是您無需運行 Kubernetes 即可訪問龐大的用戶和開發者社區。雲計算還有許多其他方面的社區,我們非常積極地參與其中。使用 AWS 的技術人員組成的社區比 Kubernetes 開發者和用戶社區更龐大,兩者有明顯的重疊。我們部署的許多其他技術(比如 Cassandra)也大受歡迎。我們在 Kubernetes 人羣面前並不覺得孤獨。

要承認的一點是,在許多情況下,使用用戶社區龐大且快速增長的產品實際上沒有幫助。Ably SRE 的幾位工程師之前曾在 Kubernetes 團隊工作過,大量新手用戶很難找到 Kubernetes 相關問題方面的有用信息。很多人使用 Kubernetes,但據我們的經驗,很少有人深入瞭解,因此通過用戶羣如此龐大的社區排除問題比您想象的要困難得多。

大量供應商進入這個領域也帶來了巨大的技術變化,Kubernetes 核心中的功能被快速添加或更改,以適應人們試圖銷售的新的第三方附加組件。龐大而活躍的社區有利也有弊。

Kubernetes 的另外弊端

複雜性,對,複雜性。若想遷移到 Kubernetes,僅僅爲了保持 Kubernetes 集羣順利運行,組織就需要整個工程團隊,其前提是使用託管的 Kubernetes 服務,而且可以依靠另外的基礎設施工程師來維護在組織的實際產品或服務基礎上的其他支持性服務。

比如說,上面提到的那些用於網絡和入站流量的 AWS EKS 服務。那些服務並不隨帶 EKS。您需要創建一個 EKS 集羣,然後在其上面安裝和配置那些服務。還有另外一些服務。

如果我們走服務提供商這條路,這顯然會爲我們減少一些工作,但這有其自身的弊端。我們已經討論了這種充滿活力的 Kubernetes 市場帶來的技術變化,因此從一家供應商換成另一家供應商絕非易事。選擇供應商不是輕鬆的選擇,本身就是對架構方面的承諾。

這個問題不是 AWS 的託管 Kubernetes 產品所特有的,整個行業都這樣。關鍵不是 EKS 團隊做得不好,而是即使擁有真正精心維護的託管 Kubernetes 架構,從基本集羣到可靠的生產環境仍有很多工作要做。

結束語

儘管我們承認 Kubernetes 是一種設計精良的產品,但我們目前並未使用或計劃使用它。倒不是說部署 Kubernetes 永遠沒有意義,只是眼下對我們來說沒有意義。

經過認真的成本效益評估後,採用如此昂貴的組件似乎只會轉移我們的一些問題,而不是真正解決它們。

在我們看來,Kubernetes 對於目前全力投入到 Kubernetes 的許多公司來說沒有意義,但選擇權在它們。如果您看到本文,貴組織目前試圖決定在多大程度上需要 Kubernetes,但願我們的觀點會幫助您爲自己的團隊做出正確的決定。

我們的生產級系統肯定面臨問題和技術債務,就像別人的一樣。我們列出了想要改進的方面,我們在招聘更多的工程師幫助改進。然而,最終,“遷移到 Kubernetes” 不是要改進的其中一項。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/wfCS0sA6UD8USdYC3hKkWQ