你真的須要Kubernetes嗎?

近幾年,Kubernetes 很火,我也從事與之相關的工做有數年時間。Kubernetes 的價值是什麼?它適用於哪些場景?咱們應該使用 Kubernetes 嗎?...... 本文試圖回答這些問題。數組

我常常從團隊——不管是新團隊仍是成熟團隊——那裏聽到一個問題:「咱們應該將軟件棧託管在 Kubernetes 上嗎?」鑑於 Kubernetes 在科技界的名聲大噪,不少人都認爲應該這麼作。我從事 K8s 的相關工做有好幾年了——一般是在很是強大而複雜的平臺上,我認爲實際狀況會更加微妙一些。在這篇文章中,我試着弄清楚這個問題。本文主要針對那些負責託管本身產品的初創公司和自給自足的團隊,不過對於大型組織傳統 IT 部門的人員來講,可能也有必定的價值。緩存

1. Kubernetes 能爲你帶來什麼

Kubernetes 不只僅是 2018 年的一個流行詞而已,它是一個健壯、高度可伸縮的系統,讓你能在原語 (Pod、Service、Ingress 等) 基礎上進行應用程序部署,而後盡其所能實現你想要的東西。在應用程序發生崩潰時,它會從新啓動它們。若是你正在運行不少服務 (可能採用了微服務架構),而且追求效率、彈性和好的部署方法,那麼它能爲你作不少事情。安全

想要讓你的服務具備基本程度的彈性?那就部署多個副本,而後在它們之間均衡流量。網絡

若是你的工做負載具備「爆發」(例如大量的 API 流量) 的特色,能夠在此基礎上經過設置自動伸縮來增長必要的容量。這能爲你節省不少錢,你不須要一直爲峯值容量付費,只須要提供一個基本負載來保持平臺運行,並在必要時提供更多副本。若是你能夠將隊列長度導入到系統中,那麼自動伸縮功能也適用於基於隊列的工做負載。架構

擔憂代碼會出問題?那就配置就緒探針,在服務發生崩潰時,Kubernetes 會自動重啓它們。對於硬件故障也是同樣——我看到過一個集羣,它有一半節點發生癱瘓,但仍然像什麼都沒發生同樣繼續運行。通過精心配置和維護的 Kubernetes 集羣能夠變得很是健壯。若是你有足夠的資源,甚至能夠嘗試運行相似 Chaos Monkey 這樣的工具,確保你的軟件棧能容忍常常性的故障。app

Kubernetes 能夠與 CI 工做流很好地集成在一塊兒。最多見的模式是將鏡像推送到 Docker 註冊表,而後啓動 K8s 集羣來加載它 (理想狀況下,全部項目都是標準化的)。這能夠根據具體狀況經過修改部署來拉出新的標記,或者將標記指向新鏡像,並觸發 K8s 從新加載全部 Pod。在大多數狀況下,部署能夠是徹底自動化的。若是你對測試頗有信心,那就能夠 100% 自動化 (也就是持續交付),若是不是頗有信心,在構建以後進行手動檢查仍然能幫你減輕痛苦。不管哪一種方式,開發人員都應該能在沒有 Kubernetes 專家幫助的狀況下將大多數構建版本發佈到集羣中。負載均衡

與 CI 相似,它能夠幫你對應用程序的日誌和監控進行標準化。這些並非 Kubernetes 獨有的,但無論怎樣,使用一個集羣將全部服務的數據收集到一塊兒能夠極大地減輕調試的痛苦。less

我看到有人用 fluentd 將 JSON 結構的日誌從應用程序傳輸到 AWS CloudWatch,並經過 Insights 進行查詢,效果很是好。運維

最後,它能夠極大地提升效率——不只在託管層,並且還能夠減小開發人員部署軟件所需的時間。人力成本高於計算機成本,所以對大多數組織來講,這是最大的勝利。但 Kubernetes 並不是魔法——我看到過一些漂亮、高效的集羣,也看到了一些「紙老虎」。要想讓 Kubernetes 爲你省錢,必須用對它。ide

2. Kubernetes 適用於哪些場景

首先,分析一下你的工做負載。你須要運行什麼類型的應用程序?它們之間以及與外部世界之間是如何通訊的?根據個人經驗,我認爲能夠經過如下這些屬性來判斷是否可使用 Kubernetes:

  • 你採用的是微服務架構嗎?若是你只有一個應用程序,那麼使用 Kubernetes 就沒有什麼價值。你須要容器化應用程序,而後將它們部署到 K8s 上。從項目開始時就這樣作有助於你思考服務之間的邊界。

  • 你的服務是否經過 HTTP 對外公開?這很適合 K8s 的模型,你能夠在服務前面使用 ingress 控制器。

  • 你的應用程序適合進行負載均衡嗎?沒有本地狀態 (使用 PostgreSQL/Redis/ 其餘),經過已知端點通訊,能夠快速啓動 / 關閉。這並非說你不能在集羣中保留像 Redis 緩存這樣的短壽命狀態,在不少狀況下,你最好是使用雲提供商提供的服務。

  • Kubernetes 也很是適用於 headless 應用程序,如批處理 (經過做業控制器) 和長時間運行的隊列消費者客戶端應用程序。

  • 內存 (以及在必定程度上 CPU) 使用狀況是可預測的嗎?Kubernetes 會嘗試在相同的物理機器上託管應用程序,所以,若是其中一臺機器出現故障並消耗了全部內存,那麼其餘工做負載可能會被隨機終止。根據個人經驗,這是 Kubernetes 集羣最大的不穩定性來源。若是瞭解應用程序的資源使用狀況,就能夠設置好 resources.requests 和 resources.limits,保證它們總有足夠的內存,不會影響其餘應用程序。

相反,對於下面這些工做負載,我認爲不該該使用 Kubernetes:

  • 靜態網站。一般,你會將內容打包成基於 Nginx 的鏡像,並經過集羣的 ingress 控制器來公開它。這是一種糟糕的託管靜態內容的方式:全部的 Nginx 副本都須要維護,效率很低。固然,你也能夠把它放在 CDN 後面,但既然你要這麼作,爲何不託管在雲服務上呢?

  • 託管不受信任的代碼。它們多是客戶提供的應用程序或有安全問題的第三方代碼,例如 Wordpress 或來自 NPM 不可靠的庫。默認狀況下,Kubernetes 提供的用於隔離工做負載的特性並非很好。你能夠添加 Calico 之類的東西來控制網絡訪問,但這很容易出錯,並且你的安全模型老是 100% 依賴於容器運行時。默認狀況下 (Docker,基於 Linux cgroup),這爲應用程序提供了一個巨大的***面:若是你的集羣運行的代碼被黑,***者就很容易訪問集羣的其他部分。cgroup 的替代品 (例如 Kata Container) 正在作一些有趣的工做,但它還不夠主流,不能推薦給普通用戶。

即便 Kubernetes 不太適用於你的工做負載,你仍然能夠選擇使用它 (例如,可使用捲來保存生命週期較長的狀態),只是你要花費大量的時間。無論怎樣,其中有不少都是很差的實踐,只會進一步傷害你。

3. 沒有銀彈

Kubernetes 並不是一顆銀彈。它有助於將託管應用程序的複雜性轉移到本身設計的層中,但不會讓它們消失。你必須始終作好保護和維護平臺的工做。

要讓集羣對工做負載發揮效用,須要大量的附加組件。有些幾乎人人都在使用,有些則有點小衆,好比 Nginx ingress 控制器、cert-manager 和 cluster-autoscaler,在沒有足夠的容量時可用來添加額外的節點。擁有一組有用的定製工具會讓你的集羣變得像一片雪花同樣,因此須要對其進行管理。

此外,它們須要按期更新,有時可能會發生故障。像 Helm 或 Terraform 這樣的配置管理工具幾乎是不可缺乏的:手動維護集羣存在較大風險,若是沒有聲明性設置,你將永遠沒法以徹底相同的方式啓動另外一個集羣。在維護或替換成更成熟的集羣時,這樣會致使無窮無盡的問題。

在 Kubernetes 上部署重要的軟件棧時,老是須要進行必定程度的管理。任何人均可以爲所欲爲地部署你的集羣,這隻會致使混亂。最終,你將看到不少命名不一致的應用程序分散在幾十個 (更糟糕的是一個) 名稱空間中,而沒有人知道它們是如何組合在一塊兒的。那麼恭喜你,你用「新口味的意大利麪基礎設施替代了舊口味的意大利麪基礎設施」,只是換成了更好看的盤子而已。

我見過的最成功的 Kubernetes 實現,是基礎設施專家與開發人員一塊兒確保工做負載配置良好、標準化、相互保護並定義了通訊模式。他們對部署在基礎設施中的應用程序進行初始設置,並集成到構建 / 發佈系統中,這樣開發團隊就能夠在沒有幫助的狀況下發布新版本。在不少方面,這反映了組織文化——若是工程糟糕,溝通混亂,責任不明,那麼託管環境也會反映出這些問題。在最好的狀況下,這會致使不可靠,在最壞的狀況下,這是一種不可靠、不可維護、代價高昂的混亂。

4. 自有 Kubernetes 集羣的成本

若是你正在大規模運行應用程序,那麼 Kubernetes 能爲你節省不少錢。能夠看看一些特性,好比自動伸縮 (集羣和副本集) 和 Spot 實例池 (EC2) 或搶佔式 VM(谷歌)。

有一個優秀的工具生態系統能夠幫助任何一個工程師搭建出一個玩具集羣來測試他們的應用程序。從某種程度上說,這樣很好,由於學習曲線變得不那麼陡峭,但在你意識到須要多大規模以前,Kubernetes 就已經進入到生產環境中,併成爲業務的關鍵部分。它的故障模式很複雜,要充分利用它須要不少專業技能。讓一個沒有經驗的開發團隊匆忙搭建一個集羣(使用 Kops 是一種反模式)就是一場災難:剛開始幾個月或許沒問題,但若是你須要作出重大變動,從新配置集羣或排除故障,你的好日子就到頭了。

從頭構建 K8s 集羣就像是本身編譯內核:這是一種很好的學習方式,但對於運行生產應用程序來講則是很糟糕的方法。相反,你應該使用已有的解決方案,如 AWS EKS 或谷歌的 GKE。比咱們還要聰明的人花了大量時間作出這些東西,即便你每月爲此付出幾百美圓也是值得的。

即便使用已有的 Kubernetes 解決方案,你也須要專業技能。控制平面是亞馬遜提供的,但早晚你會在節點上觸發一些錯誤,一般是在業務最繁忙的時候。你必須準備好資源,併爲之支付費用。Kubernetes 的發佈週期很短,因此你至少須要每一年更新一次集羣,並按期修改它的 API,這是一項很重要的工做。任何一個附加組件都須要維護。若是你是一個輕量級的在線小商店,使用臨時資源就能夠了,但請相信我,當你全部的容器在凌晨 4 點由於一個線程錯誤而崩潰時,你不得不向別人求助。

全部這些都讓我相信,有效利用 Kubernetes 是有一個規模大小和複雜性的閾值的。若是你運行的是少許 (好比少於 5 個) 簡單的服務,那麼就不值得這麼麻煩了。它真正的亮點在於那些具備高度部署複雜性的環境、動態的工做負載或者經過對工具進行標準化能夠大幅下降複雜性 / 成本的場景。

5. 那麼,我應該怎麼辦?

絕不驚喜地說,答案是「視狀況而定」。

若是你只有屈指可數的幾個服務,不但願它們成倍增加,那麼可能有更簡單、更便宜的方式來託管它們。能夠看看 AWS 的 ECS(特別是與 Fargate 一塊兒使用的 ECS),把你的 API 或批處理做業重構成 Lambdas/Cloud Function,甚至可使用簡單的 PaaS 提供商 (如 Heroku) 來託管你的應用程序。儘管聽起來彷佛有些過期,但不要小看了這些運行在 Linux 機器上的低流量應用程序所帶來的價值和健壯性。

安全性和合規需求可能會影響你的決策。若是必須在本地託管工做負載,則可能會有較大的運維開銷,儘管這並不妨礙使用 Kubernetes,但傳統的解決方案可能更適合你。若是你須要使用一組附加組件,但爲了合規性,你不得不檢查它們的每個部分,那麼這樣作可能不現實。

我見過不少創業公司,他們認爲本身須要 Kubernetes,但實際上並不須要,結果他們投入大量資源。仔細考慮一下你是否真的須要這些,以及你是否負擔得起成本。若是你的需求和可以從中獲得的好處是至關的,那就去作吧。若是不是,那麼能夠考慮是否在未來採用 Kubernetes,並將其加入到技術決策中。在一開始就用 Docker 打包應用程序 (Docker -compose 對於開發和生產來講都頗有價值),並仔細考慮是否須要存儲本地狀態。

另外一方面,評估將來的增加空間也很重要。若是你如今只有幾個簡單的服務,可能不須要 K8s。可是,它們是否會在將來變成幾十個?若是是的話,你的團隊是否應該開始學習管理這種複雜性的技能?當雙翼飛機能夠知足載客量的時候,你不會想要建造一架 747,可是,當 300 名乘客出如今登機口時,「駱駝」戰鬥機就沒有多大用處了。

總而言之,基礎設施決策一般與軟件架構決策有關。不要讓你的基礎設施成爲過後纔去考慮的事情,不要忘了你須要的越多須要付出的成本也就越高。若是你須要的話,在複雜的系統上投入是值得的,但在投入以前要三思!

相關文章
相關標籤/搜索