若是你使用Kubernetes做爲應用程序的操做平臺,那麼你應該會遇到一些有關使用集羣的方式的基本問題:前端
你應該有多少集羣?數據庫
它們應該多大?後端
它們應該包含什麼?安全
本文將深刻討論這些問題,並分析你所擁有的一些選擇的利弊。網絡
做爲一個軟件建立者,你應該開發並運行了多個應用程序。並且,你應該在不一樣的環境中運行這些應用程序的多個實例——例如,你應該有開發、測試以及生產環境。那麼,不一樣的環境和應用程序的組合,咱們能夠獲得一個「矩陣」:架構
在以上例子中,有3個應用程序和3個環境,兩兩組合爲9個應用程序實例。每一個應用程序實例是一個獨立的部署單位,能夠獨立運行。app
請注意,一個應用程序實例可能由多個組件組成,如前端、後端、數據庫等。在一個微服務應用程序中,一個應用程序實例將由全部微服務構成。負載均衡
那麼做爲一個Kubernetes用戶,此時會遇到一些問題:框架
應該在一個集羣中運行全部應用程序實例嗎?運維
或者每一個應用程序實例都應該有一個單獨的集羣嗎?
或者應該以上二者相結合?
以上這些都是行之有效的方法——Kubernetes是一個靈活的系統,它並不會直接告訴你某一條指定的使用方法。
關於集羣的搭配你有如下選擇:
一個大型的共享集羣
許多小型的一次性集羣
每一個應用程序有一個集羣
每一個環境中有一個集羣
前兩種方法分別是大型集羣和小型集羣的極端,其規模大小關係以下:
總而言之,若是一個集羣包含了大量的節點和Pod,那麼它就能夠被定義爲大於另外一個集羣。例如,一個有10個節點和100Pod的集羣大於有1個節點和10個Pod的集羣。
釐清了概念和選項,那麼咱們如今開始吧!
這個方法是指將你全部的工做負載都運行在一個集羣中:
經過這種方法,咱們能夠像通用基礎架構平臺同樣使用該集羣——不管你須要運行什麼,均可將其部署到現有的Kubernetes集羣中。
Kubernetes中有一個命名空間的概念,能夠 在邏輯上將集羣的各個部分彼此分開。在上述狀況下,你能夠爲每一個應用程序實例建立單獨的命名空間。
接下來,咱們來看看這個方法的優劣勢。
若是你只有一個Kubernetes集羣,那麼你只須要擁有運行和管理Kubernetes集羣所需的全部資源的一個副本。這包含了master節點——一個Kubernetes集羣一般有3個master節點。若是你只擁有一個集羣,你一共只須要3個master節點(比起擁有10個集羣,須要30個master節點來講輕鬆很多)。
固然了,確定不止master節點,還包括其餘集羣範圍的服務,例如負載均衡器、Ingress controller、身份驗證、日誌和監控。若是你只有一個集羣,你能夠爲全部工做負載重複使用這些服務,而且不須要擁有多個副本。
因爲上述緣由,較少的集羣一般更便宜,由於集羣數量較大,意味着資源更多,所以會花費更多的費用。對於主節點來講尤爲如此,這可能會用掉你大量的費用——不管你的集羣是在本地仍是在雲中。
有一些Kubernetes託管服務會提供免費的控制平面,如Google Kubernetes Engine(GKE)或Azure Kubernetes Service(AKS),在這種狀況下成本也許就不是問題。然而,有些託管的Kubernetes服務會爲運行一個Kubernetes集羣收取固定的費用,如Amazon Elastic Kubernetes Service(EKS)。
管理一個集羣總比管理多個集羣簡單不少。管理集羣可能包含如下任務:
升級Kubernetes版本
設置CI/CD流水線
安裝一個CNI插件
設置用戶身份驗證系統
安裝一個admission controller
等等……
若是你只有一個集羣,這一切你只須要完成一次便可。若是你有許多集羣,那麼你須要將以上任務執行不少次,這須要你開發一些自動化流程以及工具,使其可以在全部集羣中同步。
如今來講說缺點
若是你只有一個集羣,若是這個集羣剛好崩潰了,那麼你的全部工做負載都會宕機。
有不少方式可能會致使出錯:
Kubernetes升級過程當中產生的「反作用」
集羣範圍的組件(如CNI 插件)沒法正常運行
對集羣的其中一個組件進行了錯誤的配置
底層基礎架構發生故障
若是隻有一個共享集羣,那麼只要相似的事情發生可能會對全部工做負載形成重大損害。
若是有多個app運行在同一個Kubernetes集羣中,這意味着這些應用程序在集羣的節點上共享硬件、網絡和操做系統。具體而言,在同一節點上運行的兩個不一樣的應用程序的兩個容器是在相同硬件和操做系統內核上運行的兩個進程。
Linux容器提供了一些隔離的形式,但這種隔離不如虛擬機所提供的隔離強。在後臺,容器中的進程仍然只是在主機操做系統上運行的進程。
從安全角度來看,這的確是一個問題。從理論上講,它容許不相關的應用程序(有意地和無心地)彼此交互。並且,在一個Kubernetes集羣中的全部工做負載共享某些集羣範圍的服務,如DNS——它能夠容許應用程序發現集羣內的其餘APP的服務。
以上所提到的這些也許會成爲一個問題,也許不會,這取決於應用程序對安全性的要求。
Kubernetes自己提供了各類方法來防止安全漏洞,如PodSecurityPolicies以及NetworkPolicies。可是,要徹底正確地使用這些工具須要一些經驗,而且它們也沒法防止全部的安全漏洞。
請牢記一點,Kubernetes是爲共享而設計的,而不是隔離和安全。
既然在Kubernetes集羣中有許多共享資源,那麼許多不一樣的應用程序就能夠經過各類方式互相擠佔資源。例如,一個app可能獨佔了某些共享資源,如CPU或內存,所以致使同一節點上運行的其餘應用沒有資源可用。
Kubernetes提供各類方法來控制這一行爲,如resource requests and limits、ResourceQuota以及LimitRanges。可是,一樣地,要正確使用這些工具並不是易事,並且它們也沒法防止全部沒必要要的反作用。
若是你只有一個集羣,那麼在企業內部會有許多人必須得訪問這一集羣。越多的人訪問,破壞的風險就會越高。
在集羣內部,你能夠控制哪些人可使用基於角色的訪問控制(RBAC)進行操做。可是,這仍然不能防止用戶在受權範圍內進行破壞。
若是你給全部的工做負載使用一個集羣,這個集羣規模大機率已經很大了(從節點和Pod的角度來講)。然而,Kubernetes集羣沒法無限擴大。理論上,集羣的大小是有上限的,在Kubernetes中的定義大概事5000節點、150,000Pod以及300,000個容器。
然而,實際上,比上述規模更小的集羣已經會開始面臨諸多挑戰,例如500節點。緣由是較大的集羣對Kubernetes控制平面形成了更大的壓力,這須要仔細計劃以保持集羣的功能和效率。
接下來,咱們來看看第二個選項——許多小型集羣
使用這種方法,你能夠爲每一個部署單元使用單獨的Kubernetes集羣:
在本文中,一個部署單元即爲一個應用程序實例——如一個應用程序的開發版本。
經過這種策略,Kubernetes就能夠像用於各個應用程序實例的專用應用程序運行時同樣使用。
接下來,咱們看看這種方法的優點和劣勢。
若是一個集羣出現故障,那麼僅會損害運行在該集羣上的工做負載,並非全部工做負載都會受到影響。
各個集羣中運行的工做負載不會共享資源,如CPU、內存、操做系統、網絡以及其餘服務。這樣能夠在不相關的應用程序之間提供強大的隔離,對於提高應用程序安全性十分有效。
若是每一個集羣僅運行一小組工做負載,那麼就只須要更少的人訪問這一集羣。越少的人訪問集羣,集羣出現故障的機率就越低。
接下來看一下這一方法的缺點。
正如以前所說起的,每一個Kubernetes集羣須要一組管理資源,如master節點、控制平面組件、監控和日誌解決方案等。若是你有許多小型集羣,那麼你只能爲這些管理功能犧牲資源使用的百分比。
低效的資源利用天然就會致使更高的成本。例如,若是你必須運行30個master節點,而不是3個才能得到相同的計算機功能,你看看每個月的帳單就能體會到這一點。
同時管理許多Kubernetes集羣比管理單個集羣要複雜得多。例如,你須要爲每一個集羣設置身份驗證和受權;若是你想升級Kubernetes版本,你須要執行這一操做不少次。你可能須要開發一些自動化流程,這樣會使這些操做更高效。
接下來,咱們看一下其餘場景的集羣。
使用這種方法,對於特定應用程序的全部實例,你都有一個單獨的集羣:
你能夠將其視爲每一個團隊單獨擁有本身的集羣,由於一般一個團隊會開發一個或多個應用程序。
接下來,咱們看看這個方法的優劣。
若是一個應用程序有特定的需求,這些需求能夠在它的集羣內安裝,而無需影響其餘集羣。這樣的要求可能包括GUI worker節點、一個特定的CNI插件、一個服務網格或其餘服務。如此以來,每一個集羣均可以徹底配備相應應用程序所需的配置——很少也很多。
這個方法的一個不足時來自不一樣環境的應用程序實例運行在同一個集羣中。例如,應用程序的生產版本和開發版本都運行在同一個集羣中,這意味着開發人員須要在生產版本應用程序運行的相同集羣中工做。
因此,若是開發人員或一個有bug的開發版本在集羣中形成了某些損害,那麼生產版本絕對會所以受到影響——這是一個巨大的不足。
使用這種方法,你能夠爲每一個環境建立一個單獨的集羣:
例如,你能夠分別有一個開發、測試和生產集羣,你能夠在其中運行特定環境中的全部應用程序實例。
一般狀況下,這個方法會使得全部環境彼此隔離,而這對生產環境而言十分重要。生產版本的應用程序如今不會受到其餘集羣以及應用程序環境的任何影響。因此,若是某些錯誤配置在你的開發集羣中形成破壞,你的生產版本的app依舊能夠持續運行,彷彿什麼也沒發生。
你能夠爲環境優化每一個集羣,例如:
安裝開發和調試工具在開發集羣中
安裝測試框架和工具在測試集羣中
給生產集羣使用性能更好的硬件和網絡
這樣可以同時提高app的開發和運維效率。
沒有人真的須要在生產集羣內工做,因此你能夠限制訪問它。你甚至能夠根本不向任何人授予生產集羣的訪問權限——能夠經過自動化CI/CD工具對該集羣進行部署。這將極大下降生產集羣中人爲錯誤的風險,這十分重要!
如今,來看看缺點。
這一方法的主要不足是應用程序之間缺乏硬件和資源的隔離。不相關的應用程序共享集羣資源,例如操做洗頭膏內核、CPU、內存和其餘服務。如上文所述,這多是一個安全問題。
若是一個app有特殊的要求,這些要求則必須在全部集羣中獲得知足。例如,若是一個應用程序須要一個GPU,那麼每一個集羣至少必須得有一個GPU worker節點——即使只有一個應用程序使用它。這會致使更高的成本和更低效的資源利用。
總而言之,若是你有給定的一組應用程序,你能夠將它們運行在幾個大型集羣上或多個小型集羣上。本文討論了從幾個大型集羣到多個小型集羣的各類方法的優缺點:
一個大型的共享集羣
許多小型的一次性集羣
每一個應用程序有一個集羣
每一個環境中有一個集羣
如下一張表格,總結了不一樣方法的優劣勢:
因此你應該選擇哪一種方法呢?
一般狀況下,這取決於你的實際用例——你必須權衡不一樣方法的優缺點,才能找到最合適你的解決方案。可是,選擇不只限於上述示例,也能夠是它們的任意組合。例如,您可能考慮爲每一個團隊創建兩個集羣:一個開發集羣(用於開發和測試環境)和一個生產集羣(用於生產環境)。
經過了解以上示例方案,您能夠相應地結合特定方案的利弊。
做者: Daniel Weibel