本文已超過一年。較舊的文章可能包含過時的內容。請檢查頁面中的資訊自發布以來是否已變得不正確。

介紹分層命名空間

在單個 Kubernetes 叢集上安全地託管大量使用者一直是一項棘手的任務。其中一個主要原因是不同的組織以不同的方式使用 Kubernetes,因此沒有一種租戶模型可能適合所有人。相反,Kubernetes 為您提供了構建塊來創建您自己的租戶解決方案,例如基於角色的訪問控制 (RBAC) 和 NetworkPolicies;這些構建塊越好,安全地構建多租戶叢集就越容易。

用於租戶的命名空間

到目前為止,這些構建塊中最重要的是命名空間,它構成了幾乎所有 Kubernetes 控制平面安全和共享策略的支柱。例如,RBAC、NetworkPolicies 和 ResourceQuotas 預設都尊重命名空間,並且諸如 Secrets、ServiceAccounts 和 Ingresses 之類的物件可以自由地在任何一個命名空間使用,但與其他命名空間完全隔離。

命名空間具有兩個關鍵屬性,使其成為策略實施的理想選擇。首先,它們可以用於表示所有權。大多數 Kubernetes 物件必須在命名空間中,因此如果您使用命名空間來表示所有權,您始終可以指望存在所有者。

其次,命名空間具有授權的創建和使用。只有高度特權的使用者才能創建命名空間,而其他使用者需要明確的權限才能使用這些命名空間 - 即在這些命名空間中創建、查看或修改物件。這允許在非特權使用者可以創建“常規”物件(如 pod 和服務)之前,仔細創建它們並應用適當的策略。

命名空間的限制

但是,在實踐中,命名空間不夠靈活,無法滿足一些常見的使用案例。例如,假設一個團隊擁有幾個具有不同密鑰和配額的微服務。理想情況下,他們應該將這些服務放入不同的命名空間中,以便將它們彼此隔離,但這會帶來兩個問題。

首先,這些命名空間沒有共同的所有權概念,即使它們都由同一個團隊擁有。這意味著,如果團隊控制多個命名空間,不僅 Kubernetes 沒有任何關於其共同所有者的記錄,而且命名空間範圍的策略也無法在它們之間統一應用。

其次,團隊通常在可以自主運作時效果最佳,但由於命名空間創建是高度特權的,因此開發團隊的任何成員都不太可能被允許創建命名空間。這意味著,每當團隊想要一個新的命名空間時,他們都必須向叢集管理員提出票證。雖然這對於小型組織來說可能是可以接受的,但隨著組織的發展,這會產生不必要的苦差事。

介紹分層命名空間

分層命名空間Kubernetes 多租戶工作組 (wg-multitenancy) 開發的一個新概念,旨在解決這些問題。在其最簡單的形式中,分層命名空間是一個常規的 Kubernetes 命名空間,其中包含一個小型自定義資源,用於標識單個可選的父命名空間。這建立了命名空間的所有權概念,而不僅僅是在命名空間

這種所有權概念啟用了兩種額外的行為類型

  • 策略繼承:如果一個命名空間是另一個命名空間的子命名空間,則策略物件(例如 RBAC RoleBindings)會從父命名空間複製到子命名空間
  • 委派創建:您通常需要叢集級別的權限才能創建命名空間,但分層命名空間添加了一種替代方案:子命名空間,可以使用父命名空間中有限的權限來操作它。

這解決了我們開發團隊的兩個問題。叢集管理員可以為團隊創建一個單一的“根”命名空間,以及所有必要的策略,然後將創建子命名空間的權限委派給該團隊的成員。然後,這些團隊成員可以創建子命名空間供自己使用,而不會違反叢集管理員施加的策略。

分層命名空間的實踐操作

分層命名空間由稱為 分層命名空間控制器HNC 的 Kubernetes 擴展提供。HNC 由兩個組件組成

  • 管理器在您的叢集上運行,管理子命名空間,傳播策略物件,確保您的層次結構合法並管理擴展點。
  • 名為 kubectl-hnskubectl 插件,使使用者可以輕鬆地與管理器互動。

兩者都可以從我們的 repo 的發布頁面輕鬆安裝。

讓我們看看 HNC 的實際操作。假設我沒有命名空間創建權限,但我可以查看命名空間 team-a 并在其中創建子命名空間1。使用該插件,我現在可以說

$ kubectl hns create svc1-team-a -n team-a

這將創建一個名為 svc1-team-a 的子命名空間。請注意,由於子命名空間只是常規的 Kubernetes 命名空間,因此所有子命名空間名稱仍然必須是唯一的。

我可以透過請求樹狀視圖來查看這些命名空間的結構

$ kubectl hns tree team-a
# Output:
team-a
└── svc1-team-a

如果父命名空間中有任何策略,這些策略現在也會出現在子命名空間中2。例如,假設 team-a 有一個名為 sres 的 RBAC RoleBinding。此角色綁定也將出現在子命名空間中

$ kubectl describe rolebinding sres -n svc1-team-a
# Output:
Name:         sres
Labels:       hnc.x-k8s.io/inheritedFrom=team-a  # inserted by HNC
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  admin
Subjects: ...

最後,HNC 會將標籤添加到這些命名空間,其中包含有關層次結構的有用資訊,您可以使用這些資訊來應用其他策略。例如,您可以創建以下 NetworkPolicy

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-team-a
  namespace: team-a
spec:
  ingress:
  - from:
    - namespaceSelector:
        matchExpressions:
          - key: 'team-a.tree.hnc.x-k8s.io/depth' # Label created by HNC
            operator: Exists

此策略既會傳播到 team-a 的所有後代,會允許這些命名空間之間的所有入口流量。“tree”標籤只能由 HNC 應用,並保證反映最新的層次結構。

您可以從使用者指南中了解有關 HNC 功能的所有資訊。

後續步驟和參與

如果您認為分層命名空間可以為您的組織工作,則 HNC v0.5.1 在 GitHub 上可用。我們很想知道您對它的看法、您正在使用它解決哪些問題以及您最希望看到添加哪些功能。與所有早期軟體一樣,您應謹慎在生產環境中使用 HNC,但我們獲得的回饋越多,我們就能越快推動 HNC 1.0。

我們也歡迎其他貢獻者,無論是修復或報告錯誤,還是幫助原型化新功能,例如例外、改進的監控、分層資源配額或細粒度配置。

請透過我們的 repo郵件列表Slack 與我們聯繫 - 我們期待您的來信!


Adrian Ludwin 是一位軟體工程師,也是分層命名空間控制器的技術主管。

注意 1:從技術上講,您在父命名空間中創建一個名為“子命名空間錨點”的小物件,然後 HNC 為您創建子命名空間。

注意 2:預設情況下,僅傳播 RBAC 角色和 RoleBindings,但您可以配置 HNC 來傳播任何命名空間範圍的 Kubernetes 物件。