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

介紹分層名字空間

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

用於租戶的名稱空間

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

名稱空間具有兩個關鍵特性,使其成為策略執行的理想選擇。首先,它們可以用於**表示所有權**。大多數 Kubernetes 物件**必須**位於名稱空間中,因此如果您使用名稱空間來表示所有權,您總能確定存在一個所有者。

其次,名稱空間具有**授權建立和使用**。只有高許可權使用者才能建立名稱空間,其他使用者需要明確的許可權才能使用這些名稱空間——即,在這些名稱空間中建立、檢視或修改物件。這使得它們能夠在非特權使用者建立 Pod 和 Service 等“常規”物件之前,仔細建立並附帶適當的策略。

名稱空間的限制

然而,在實踐中,名稱空間不夠靈活,無法滿足一些常見用例。例如,假設一個團隊擁有多個微服務,這些微服務具有不同的 Secret 和配額。理想情況下,他們應該將這些服務放置在不同的名稱空間中,以便彼此隔離,但這帶來了兩個問題。

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

其次,團隊通常在能夠自主操作時表現最佳,但由於名稱空間建立是高度特權的,因此開發團隊的任何成員都不太可能被允許建立名稱空間。這意味著每當團隊想要一個新的名稱空間時,他們必須向叢集管理員提交工單。雖然這對於小型組織來說可能是可以接受的,但隨著組織的增長,這會產生不必要的麻煩。

引入分層名稱空間

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

這個所有權概念支援另外兩種行為:

  • **策略繼承:**如果一個名稱空間是另一個名稱空間的子級,則 RBAC RoleBindings 等策略物件會從父級**複製到子級**。
  • **委派建立:**通常您需要叢集級許可權才能建立名稱空間,但分層名稱空間增加了一種替代方案:**子名稱空間**,只需父名稱空間中的有限許可權即可操作。

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

實踐分層名稱空間

分層名稱空間由一個名為**分層名稱空間控制器**(Hierarchical Namespace Controller,或稱**HNC**)的 Kubernetes 擴充套件提供。HNC 包含兩個元件:

  • **管理器**在您的叢集上執行,管理子名稱空間,傳播策略物件,確保您的層級結構合法並管理擴充套件點。
  • **kubectl 外掛**,稱為 `kubectl-hns`,讓使用者可以輕鬆與管理器互動。

兩者都可以從我們的倉庫釋出頁面輕鬆安裝。

讓我們看看 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 會為這些名稱空間新增標籤,其中包含有關層級結構的有用資訊,您可以使用這些資訊來應用其他策略。例如,您可以建立以下網路策略:

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 的釋出。

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

請透過我們的倉庫郵件列表或在 Slack 上與我們聯絡——我們期待您的來信!


Adrian Ludwin 是一名軟體工程師,也是分層名稱空間控制器的技術負責人。

注 1:實際上,您在父名稱空間中建立了一個名為“子名稱空間錨點”的小物件,然後 HNC 會為您建立子名稱空間。

注 2:預設情況下,只傳播 RBAC Role 和 RoleBinding,但您可以配置 HNC 以傳播任何名稱空間的 Kubernetes 物件。