多租戶
本頁面概述了叢集多租戶可用的組態選項與最佳實務。
共用叢集可以節省成本並簡化管理。然而,共用叢集也帶來了安全性、公平性以及管理吵雜鄰居等挑戰。
叢集可以透過多種方式共用。在某些情況下,不同的應用程式可能會在同一個叢集中執行。在其他情況下,同一個應用程式的多個執行個體可能會在同一個叢集中執行,每個最終使用者一個執行個體。所有這些共用類型經常使用總括術語多租戶來描述。
雖然 Kubernetes 沒有最終使用者或租戶的一級概念,但它提供了多項功能來協助管理不同的租戶需求。這些將在下面討論。
使用案例
判斷如何共用叢集的第一步是了解您的使用案例,以便您可以評估可用的模式與工具。一般而言,Kubernetes 叢集中的多租戶分為兩大類,儘管許多變體與混合形式也是可能的。
多個團隊
多租戶的常見形式是在組織內的多個團隊之間共用叢集,每個團隊可以運作一個或多個工作負載。這些工作負載經常需要彼此通訊,以及與位於相同或不同叢集上的其他工作負載通訊。
在這種情況下,團隊成員通常透過 kubectl
等工具直接存取 Kubernetes 資源,或透過 GitOps 控制器或其他類型的發布自動化工具間接存取。不同團隊成員之間通常存在一定程度的信任,但 Kubernetes 策略(例如 RBAC、配額與網路策略)對於安全且公平地共用叢集至關重要。
多個客戶
另一種主要形式的多租戶通常涉及軟體即服務 (SaaS) 供應商為客戶執行工作負載的多個執行個體。這種商業模式與這種部署樣式密切相關,以至於許多人稱其為「SaaS 租戶」。然而,「多客戶租戶」可能是一個更好的術語,因為 SaaS 供應商也可能使用其他部署模型,而且這種部署模型也可以在 SaaS 之外使用。
在這種情況下,客戶無法存取叢集; Kubernetes 從他們的角度來看是不可見的,僅供供應商用於管理工作負載。成本最佳化通常是至關重要的考量因素,而 Kubernetes 策略用於確保工作負載彼此強烈隔離。
術語
租戶
在討論 Kubernetes 中的多租戶時,「租戶」沒有單一的定義。相反地,租戶的定義將根據討論的是多團隊還是多客戶租戶而有所不同。
在多團隊使用情境中,租戶通常是一個團隊,每個團隊通常部署少量的工作負載,這些工作負載會隨著服務的複雜性而擴展。然而,「團隊」的定義本身可能很模糊,因為團隊可能會組織成更高層級的部門或細分為更小的團隊。
相反地,如果每個團隊為每個新客戶部署專用工作負載,他們正在使用多客戶租戶模型。在這種情況下,「租戶」只是一群共用單一工作負載的使用者。這可能像一家公司一樣大,也可能像公司中的一個團隊一樣小。
在許多情況下,同一個組織可能會在不同的情境中使用「租戶」的不同定義。例如,一個平台團隊可能會向多個內部「客戶」提供共用服務,例如安全工具和資料庫,而 SaaS 供應商也可能有多個團隊共用一個開發叢集。最後,混合架構也是可能的,例如 SaaS 供應商結合使用針對敏感資料的每客戶工作負載,以及多租戶共用服務。

顯示共存租戶模型的叢集
隔離
有多種方法可以使用 Kubernetes 設計和建置多租戶解決方案。這些方法各有優缺點,會影響隔離等級、實作工作量、操作複雜性和服務成本。
Kubernetes 叢集由執行 Kubernetes 軟體的控制平面,以及由工作節點組成的資料平面所構成,租戶工作負載在工作節點上以 Pods 形式執行。租戶隔離可以根據組織需求應用於控制平面和資料平面。
提供的隔離等級有時會使用「硬」多租戶(表示強隔離)和「軟」多租戶(表示較弱隔離)等術語來描述。特別是,「硬」多租戶通常用於描述租戶彼此不信任的情況,通常是從安全性和資源共用角度來看(例如,防範資料外洩或阻斷服務 (DoS) 等攻擊)。由於資料平面通常具有更大的攻擊面,「硬」多租戶通常需要額外關注資料平面的隔離,儘管控制平面隔離仍然至關重要。
然而,「硬」和「軟」這些術語通常會造成混淆,因為沒有單一的定義適用於所有使用者。更確切地說,「硬度」或「軟度」最好理解為一個廣泛的 spectrum,其中有許多不同的技術可用於在叢集中維護不同類型的隔離,具體取決於您的需求。
在更極端的情況下,完全放棄任何叢集層級的共用,並為每個租戶分配專用叢集可能更容易或更必要,如果虛擬機器 (VM) 不被認為是足夠的安全邊界,甚至可能在專用硬體上執行。對於託管 Kubernetes 叢集而言,這可能會更容易,因為建立和操作叢集的 overhead 至少在某種程度上由雲端供應商承擔。《多叢集 SIG》負責處理這些類型的使用案例。更強大的租戶隔離的好處必須根據管理多個叢集的成本和複雜性來評估。
本頁的其餘部分重點介紹用於共用 Kubernetes 叢集的隔離技術。但是,即使您正在考慮專用叢集,檢閱這些建議也可能很有價值,因為如果您的需求或能力發生變化,這將使您能夠靈活地轉移到共用叢集。
控制平面隔離
控制平面隔離確保不同的租戶無法存取或影響彼此的 Kubernetes API 資源。
命名空間
在 Kubernetes 中,《命名空間》提供了一種機制,用於隔離單一叢集內的 API 資源群組。這種隔離具有兩個關鍵層面
命名空間中的物件名稱可以與其他命名空間中的名稱重疊,類似於資料夾中的檔案。這允許租戶命名其資源,而無需考慮其他租戶正在做什麼。
許多 Kubernetes 安全策略的作用域都限定在命名空間。例如,RBAC 角色和網路策略是命名空間作用域的資源。使用 RBAC,使用者和服務帳戶可以被限制在一個命名空間中。
在多租戶環境中,命名空間有助於將租戶的工作負載劃分為邏輯上且不同的管理單元。事實上,常見的做法是將每個工作負載隔離在其自己的命名空間中,即使多個工作負載由同一個租戶操作也是如此。這確保了每個工作負載都有自己的身分,並且可以使用適當的安全策略進行配置。
命名空間隔離模型需要配置其他幾個 Kubernetes 資源、網路外掛程式,並遵守安全最佳實務,才能正確隔離租戶工作負載。以下將討論這些考量因素。
存取控制
對於控制平面而言,最重要的隔離類型是授權。如果團隊或其工作負載可以存取或修改彼此的 API 資源,他們就可以變更或停用所有其他類型的策略,從而抵消這些策略可能提供的任何保護。因此,務必確保每個租戶都僅對其需要的命名空間擁有適當的存取權限,且不多也不少。這被稱為「最小權限原則」。
基於角色的存取控制 (RBAC) 通常用於在 Kubernetes 控制平面中強制執行授權,適用於使用者和工作負載(服務帳戶)。《角色》和《角色綁定》是 Kubernetes 物件,在命名空間層級使用,以在您的應用程式中強制執行存取控制;類似的物件也存在於授權存取叢集層級物件,儘管這些物件對於多租戶叢集而言不太有用。
在多團隊環境中,必須使用 RBAC 來限制租戶對適當命名空間的存取,並確保只有叢集管理員等特權使用者才能存取或修改叢集範圍的資源。
如果策略最終授予使用者超出其需求的權限,這很可能表示包含受影響資源的命名空間應重構為更細微的命名空間。命名空間管理工具可以透過將常見的 RBAC 策略應用於不同的命名空間,同時仍然允許在必要時使用細微的策略,來簡化這些更細微命名空間的管理。
配額
Kubernetes 工作負載會消耗節點資源,例如 CPU 和記憶體。在多租戶環境中,您可以使用《資源配額》來管理租戶工作負載的資源使用量。對於多個團隊的使用案例,在這些案例中,租戶可以存取 Kubernetes API,您可以使用資源配額來限制租戶可以建立的 API 資源數量(例如:Pods 的數量或 ConfigMaps 的數量)。對物件計數的限制確保了公平性,並旨在避免吵雜的鄰居問題影響共用控制平面的其他租戶。
資源配額是命名空間物件。透過將租戶對應到命名空間,叢集管理員可以使用配額來確保租戶不會獨佔叢集的資源或使其控制平面不堪重負。命名空間管理工具簡化了配額的管理。此外,雖然 Kubernetes 配額僅在單一命名空間內應用,但一些命名空間管理工具允許命名空間群組共用配額,與內建配額相比,這為管理員提供了更大的彈性,同時減少了工作量。
配額可防止單一租戶消耗超過其分配的資源份額,從而最大限度地減少「吵雜的鄰居」問題,即一個租戶會對其他租戶工作負載的效能產生負面影響。
當您將配額應用於命名空間時,Kubernetes 要求您也為每個容器指定資源請求和限制。限制是容器可以消耗的資源量的上限。嘗試消耗超過配置限制的資源的容器將會受到節流或終止,具體取決於資源類型。當資源請求設定低於限制時,每個容器都會保證獲得請求的量,但工作負載之間仍然可能存在一些潛在的影響。
配額無法防範所有類型的資源共用,例如網路流量。節點隔離(如下所述)可能是解決此問題的更好方法。
資料平面隔離
資料平面隔離確保不同租戶的 Pods 和工作負載得到充分隔離。
網路隔離
預設情況下,Kubernetes 叢集中的所有 Pods 都被允許彼此通訊,並且所有網路流量都未加密。這可能會導致安全漏洞,其中流量意外或惡意地發送到非預期的目的地,或被受損節點上的工作負載攔截。
可以使用《網路策略》來控制 Pod 到 Pod 的通訊,網路策略使用命名空間標籤或 IP 位址範圍來限制 Pod 之間的通訊。在需要租戶之間嚴格網路隔離的多租戶環境中,建議從拒絕 Pod 之間通訊的預設策略開始,並使用另一個允許所有 Pod 查詢 DNS 伺服器以進行名稱解析的規則。在制定此類預設策略後,您可以開始新增更寬鬆的規則,以允許命名空間內的通訊。也建議不要在網路策略定義中對 namespaceSelector 欄位使用空標籤選取器 '{}',以防需要在命名空間之間允許流量。可以根據需要進一步完善此方案。請注意,這僅適用於單一控制平面內的 Pods;屬於不同虛擬控制平面的 Pods 無法透過 Kubernetes 網路彼此通訊。
命名空間管理工具可以簡化預設或常見網路策略的建立。此外,其中一些工具允許您在整個叢集中強制執行一致的命名空間標籤集,確保它們成為您策略的受信任基礎。
警告
網路策略需要支援網路策略實作的《CNI 外掛程式》。否則,NetworkPolicy 資源將被忽略。更進階的網路隔離可以由服務網格提供,除了命名空間之外,服務網格還提供基於工作負載身分識別的 OSI 第 7 層策略。這些更高等級的策略可以更輕鬆地管理基於命名空間的多租戶,尤其是在多個命名空間專用於單一租戶時。它們通常還提供使用相互 TLS 的加密,即使在存在受損節點的情況下也能保護您的資料,並且適用於專用或虛擬叢集。但是,它們的管理可能非常複雜,並且可能不適合所有使用者。
儲存隔離
Kubernetes 提供多種類型的卷宗,可用作工作負載的持久儲存。為了安全性和資料隔離,建議使用《動態卷宗佈建》,並且應避免使用節點資源的卷宗類型。
《StorageClasses》允許您根據服務品質等級、備份策略或叢集管理員確定的自訂策略來描述叢集提供的自訂「類別」儲存。
Pods 可以使用《PersistentVolumeClaim》請求儲存。PersistentVolumeClaim 是一種命名空間資源,可以隔離儲存系統的一部分,並將其專用於共用 Kubernetes 叢集內的租戶。但是,重要的是要注意,PersistentVolume 是一種叢集範圍的資源,並且具有獨立於工作負載和命名空間的生命週期。
例如,您可以為每個租戶配置單獨的 StorageClass,並使用它來加強隔離。如果 StorageClass 是共用的,您應該設定《回收策略為 Delete
》,以確保 PersistentVolume 無法在不同的命名空間之間重複使用。
沙箱容器
Kubernetes Pods 由一個或多個在工作節點上執行的容器組成。容器利用作業系統層級的虛擬化,因此提供的隔離邊界比利用硬體式虛擬化的虛擬機器弱。
在共用環境中,應用程式和系統層中的未修補漏洞可能會被攻擊者利用,進行容器突破和遠端程式碼執行,從而允許存取主機資源。在某些應用程式中,例如內容管理系統 (CMS),可能會允許客戶上傳和執行不受信任的腳本或程式碼。在任何一種情況下,都希望使用強隔離機制來進一步隔離和保護工作負載。
沙箱提供了一種隔離在共用叢集中執行的工作負載的方法。它通常涉及在單獨的執行環境中執行每個 Pod,例如虛擬機器或使用者空間核心。當您執行不受信任的程式碼時,通常建議使用沙箱,在這種情況下,工作負載被假定為惡意的。之所以需要這種隔離類型,部分原因是容器是在共用核心上執行的進程;它們從底層主機掛載檔案系統,例如 /sys
和 /proc
,這使得它們不如在具有自己核心的虛擬機器上執行的應用程式安全。雖然可以使用 seccomp、AppArmor 和 SELinux 等控制項來加強容器的安全性,但很難將一組通用的規則應用於在共用叢集中執行的所有工作負載。在沙箱環境中執行工作負載有助於將主機與容器逃逸隔離開來,在容器逃逸中,攻擊者會利用漏洞來取得對主機系統以及在該主機上執行的所有進程/檔案的存取權。
虛擬機器和使用者空間核心是兩種常見的沙箱方法。以下沙箱實作可用
- gVisor 攔截來自容器的系統呼叫,並透過以 Go 語言編寫的使用者空間核心執行它們,該核心對底層主機的存取受到限制。
- Kata Containers 提供安全的容器執行階段,允許您在虛擬機器中執行容器。Kata 中可用的硬體虛擬化為執行不受信任程式碼的容器提供了額外的安全層。
節點隔離
節點隔離是另一種可用於隔離租戶工作負載彼此隔離的技術。透過節點隔離,一組節點專用於執行來自特定租戶的 Pods,並且禁止混合租戶 Pods。此配置減少了吵雜的租戶問題,因為在節點上執行的所有 Pods 都將屬於單一租戶。使用節點隔離,資訊洩露的風險略低,因為設法從容器逃逸的攻擊者將僅有權存取容器和掛載到該節點的卷宗。
雖然來自不同租戶的工作負載在不同的節點上執行,但務必注意,kubelet 和 API 服務(除非使用虛擬控制平面)仍然是共用服務。熟練的攻擊者可能會使用分配給 kubelet 或在節點上執行的其他 Pods 的權限,在叢集中橫向移動,並取得對在其他節點上執行的租戶工作負載的存取權。如果這是一個主要問題,請考慮實作補償性控制項,例如 seccomp、AppArmor 或 SELinux,或探索使用沙箱容器或為每個租戶建立單獨的叢集。
從計費的角度來看,節點隔離比沙箱容器更容易理解,因為您可以按節點而不是按 Pod 收費。它也具有較少的相容性和效能問題,並且可能比沙箱容器更容易實作。例如,可以為每個租戶的節點配置污點,以便只有具有相應容忍度的 Pods 才能在它們上面執行。然後可以使用 mutating webhook 自動將容忍度和節點親和性新增到部署到租戶命名空間的 Pods,以便它們在為該租戶指定的特定節點集上執行。
節點隔離可以使用《Pod 節點選取器》或《Virtual Kubelet》來實作。
其他考量因素
本節討論其他與多租戶相關的 Kubernetes 建構和模式。
API 優先順序與公平性
《API 優先順序和公平性》是 Kubernetes 的一項功能,允許您為叢集中執行的某些 Pods 分配優先順序。當應用程式呼叫 Kubernetes API 時,API 伺服器會評估分配給 Pod 的優先順序。來自具有較高優先順序的 Pods 的呼叫將優先於具有較低優先順序的呼叫得到滿足。當競爭激烈時,較低優先順序的呼叫可能會排隊,直到伺服器不那麼忙碌,或者您可以拒絕請求。
除非您允許客戶執行與 Kubernetes API 介面連接的應用程式(例如,控制器),否則在 SaaS 環境中使用 API 優先順序和公平性將不是很常見。
服務品質 (QoS)
當您執行 SaaS 應用程式時,您可能希望能夠為不同的租戶提供不同的服務品質 (QoS) 層級的服務。例如,您可能擁有免費增值服務,其效能保證和功能較少,以及具有特定效能保證的付費服務層級。幸運的是,有幾個 Kubernetes 建構可以幫助您在共用叢集中完成此操作,包括網路 QoS、儲存類別以及 Pod 優先順序和搶佔。這些建構的想法是為租戶提供他們付費購買的服務品質。讓我們先看看網路 QoS。
通常,節點上的所有 Pods 共用一個網路介面。如果沒有網路 QoS,某些 Pods 可能會消耗過多的可用頻寬,而犧牲其他 Pods 的利益。Kubernetes《頻寬外掛程式》為網路建立了一個《擴充資源》,允許您使用 Kubernetes 資源建構(即請求/限制)透過使用 Linux tc 佇列將速率限制應用於 Pods。請注意,根據《網路外掛程式》文件,該外掛程式被認為是實驗性的,應在生產環境中使用之前進行徹底測試。
對於儲存 QoS,您可能需要建立具有不同效能特性的不同儲存類別或設定檔。每個儲存設定檔都可以與針對不同工作負載(例如 IO、冗餘或輸送量)最佳化的不同服務層級相關聯。可能需要額外的邏輯來允許租戶將適當的儲存設定檔與其工作負載相關聯。
最後,還有《Pod 優先順序和搶佔》,您可以在其中為 Pods 分配優先順序值。在排程 Pods 時,當資源不足以排程分配了較高優先順序的 Pods 時,排程器將嘗試驅逐具有較低優先順序的 Pods。如果您有一個使用案例,其中租戶在共用叢集中具有不同的服務層級,例如免費和付費,您可能希望使用此功能為某些層級提供更高的優先順序。
DNS
Kubernetes 叢集包括網域名稱系統 (DNS) 服務,用於為所有服務和 Pods 提供從名稱到 IP 位址的轉換。預設情況下,Kubernetes DNS 服務允許跨叢集中所有命名空間的查詢。
在租戶可以存取 Pods 和其他 Kubernetes 資源的多租戶環境中,或者在需要更強隔離的環境中,可能需要阻止 Pods 查詢其他命名空間中的服務。您可以透過為 DNS 服務配置安全規則來限制跨命名空間 DNS 查詢。例如,CoreDNS(Kubernetes 的預設 DNS 服務)可以利用 Kubernetes metadata 將查詢限制為命名空間內的 Pods 和服務。如需更多資訊,請閱讀 CoreDNS 文件中配置此功能的《範例》。
當使用《每個租戶一個虛擬控制平面》模型時,必須為每個租戶配置 DNS 服務,或者必須使用多租戶 DNS 服務。以下是一個《自訂版本的 CoreDNS》範例,該版本支援多個租戶。
Operators
《Operators》是管理應用程式的 Kubernetes 控制器。Operators 可以簡化多個應用程式執行個體的管理,例如資料庫服務,這使得它們成為多消費者 (SaaS) 多租戶使用案例中的常見建構區塊。
在多租戶環境中使用的 Operators 應遵循更嚴格的準則集。具體而言,Operator 應
- 支援在不同的租戶命名空間中建立資源,而不僅僅是在部署 Operator 的命名空間中。
- 確保 Pods 配置了資源請求和限制,以確保排程和公平性。
- 支援配置 Pods 以用於資料平面隔離技術,例如節點隔離和沙箱容器。
實作
有兩種主要方式可以共用 Kubernetes 叢集以實現多租戶:使用命名空間(即,每個租戶一個命名空間)或透過虛擬化控制平面(即,每個租戶一個虛擬控制平面)。
在這兩種情況下,也建議使用資料平面隔離,以及管理其他考量因素,例如 API 優先順序和公平性。
Kubernetes 很好地支援命名空間隔離,資源成本可忽略不計,並提供允許租戶適當互動的機制,例如允許服務對服務的通訊。但是,它可能難以配置,並且不適用於無法命名空間化的 Kubernetes 資源,例如自訂資源定義、StorageClasses 和 Webhooks。
控制平面虛擬化允許隔離非命名空間化的資源,但代價是稍高的資源使用率和更困難的跨租戶共用。當命名空間隔離不足,但專用叢集不受歡迎時,這是一個不錯的選擇,原因是在本地維護它們的成本很高,或者由於它們的 overhead 較高且缺乏資源共用。但是,即使在虛擬化控制平面中,您也可能會看到使用命名空間的好處。
以下章節將更詳細地討論這兩個選項。
每個租戶一個命名空間
如前所述,您應該考慮將每個工作負載隔離在其自己的命名空間中,即使您使用專用叢集或虛擬化控制平面也是如此。這確保了每個工作負載僅有權存取其自己的資源,例如 ConfigMaps 和 Secrets,並允許您為每個工作負載量身定制專用的安全策略。此外,最佳實務是為每個命名空間命名在您的整個 fleet 中都是唯一的名稱(即,即使它們位於單獨的叢集中),因為這使您能夠靈活地在未來在專用和共用叢集之間切換,或使用多叢集工具,例如服務網格。
相反地,在租戶層級(而不僅僅是工作負載層級)分配命名空間也有優勢,因為通常有適用於單一租戶擁有的所有工作負載的策略。但是,這也會帶來自身的問題。首先,這使得難以或不可能自訂針對個別工作負載的策略,其次,可能難以提出應給予命名空間的單一「租戶」層級。例如,一個組織可能會有部門、團隊和子團隊 - 應該分配哪個命名空間?
為了解決這個問題,Kubernetes 提供了《階層式命名空間控制器 (HNC)》,它允許您將命名空間組織成層次結構,並在它們之間共用某些策略和資源。它還可以幫助您管理命名空間標籤、命名空間生命週期和委派管理,並在相關命名空間之間共用資源配額。這些功能在多團隊和多客戶情境中都很有用。
以下列出了其他提供類似功能並協助管理命名空間資源的專案。
多團隊租戶
多客戶租戶
策略引擎
策略引擎提供驗證和產生租戶配置的功能
每個租戶一個虛擬控制平面
另一種形式的控制平面隔離是使用 Kubernetes 擴充功能為每個租戶提供虛擬控制平面,從而實現叢集範圍 API 資源的區隔。《資料平面隔離》技術可以與此模型一起使用,以安全地管理跨租戶的工作節點。
基於虛擬控制平面的多租戶模型透過為每個租戶提供專用的控制平面組件來擴展基於命名空間的多租戶,因此可以完全控制叢集範圍的資源和附加服務。工作節點在所有租戶之間共用,並由通常租戶無法存取的 Kubernetes 叢集管理。此叢集通常被稱為超級叢集(或有時稱為主機叢集)。由於租戶的控制平面未直接與底層運算資源關聯,因此稱為虛擬控制平面。
虛擬控制平面通常由 Kubernetes API 伺服器、控制器管理員和 etcd 資料儲存庫組成。它透過 metadata 同步控制器與超級叢集互動,該控制器協調跨租戶控制平面和超級叢集控制平面的變更。
透過使用每個租戶專用的控制平面,解決了由於在所有租戶之間共用一個 API 伺服器而引起的大多數隔離問題。範例包括控制平面中的吵雜鄰居、策略錯誤配置的不可控制的爆炸半徑,以及叢集範圍物件(例如 Webhooks 和 CRDs)之間的衝突。因此,虛擬控制平面模型特別適用於每個租戶都需要存取 Kubernetes API 伺服器並期望完全叢集可管理性的情況。
改進的隔離是以執行和維護每個租戶的個別虛擬控制平面為代價的。此外,每個租戶的控制平面並不能解決資料平面中的隔離問題,例如節點層級的吵雜鄰居或安全威脅。這些問題仍然必須單獨解決。
Kubernetes《Cluster API - Nested (CAPN)》專案提供了虛擬控制平面的實作。
其他實作
本頁上的項目參考了第三方產品或專案,這些產品或專案提供了 Kubernetes 所需的功能。Kubernetes 專案作者不對這些第三方產品或專案負責。如需更多詳細資訊,請參閱《CNCF 網站準則》。
在提出新增額外第三方連結的變更之前,您應該閱讀《內容指南》。