1. 程式人生 > 其它 >Kubernetes 多租戶:多租戶介紹

Kubernetes 多租戶:多租戶介紹

多租戶叢集由多個使用者和/或工作負載共享,這些使用者和/或工作負載被稱為“租戶”。多租戶叢集的運營方必須將租戶彼此隔離,以最大限度地減少被盜用的租戶或惡意租戶可能對叢集和其他租戶造成的損害。此外,必須在租戶之間公平地分配叢集資源。

在規劃多租戶架構時,您應該考慮 Kubernetes 中的資源隔離層:叢集、名稱空間、節點、Pod 和容器。您還應該考慮在租戶之間共享不同型別資源的安全隱患。例如,將來自不同租戶的 Pod 排程到同一節點上可以減少叢集中所需的機器數量。另一方面,您可能需要阻止某些工作負載共置。例如,您可能不允許來自組織外部的不受信任的程式碼與處理敏感資訊的容器在同一節點上執行。

雖然 Kubernetes 不能保證租戶之間完全安全地隔離,但它為特定使用場景提供了足夠的相關功能。您可以將每個租戶及其 Kubernetes 資源分隔到各自的名稱空間中。然後,您可以使用一些限制策略來強制執行租戶隔離。現在策略通常按名稱空間劃分,可用於限制 API 訪問、資源使用以及允許容器執行的操作。

多租戶叢集的租戶共享以下資源:

  • 擴充套件程式、控制器、外掛和自定義資源定義 (CRD)。
  • 叢集控制平面。這意味著叢集操作、安全性和稽核是集中管理的。

與運營多個單租戶叢集相比,運營多租戶叢集有幾個優點:

  • 減少管理開銷
  • 減少資源碎片
  • 新租戶無需等待叢集建立

多租戶使用用例

本部分介紹如何為各種多租戶使用用例配置叢集。

企業多租戶

在企業環境中,叢集的租戶是組織內的不同團隊。通常,每個租戶對應一個名稱空間,同一個名稱空間內的網路流量不受限制,但不同名稱空間之間的網路流量必須明確列入白名單。可以使用 Kubernetes 網路策略來實現這些隔離。

叢集的使用者根據其許可權分為三種不同的角色:

  • 叢集管理員:此角色適用於在整個叢集中管理所有租戶的管理員。叢集管理員可以建立、讀取、更新和刪除任何策略物件。他們可以建立名稱空間並將其分配給名稱空間管理員。
  • 名稱空間管理員:此角色適用於特定單一租戶的管理員,名稱空間管理員可以管理其名稱空間中的使用者。
  • 開發者:此角色的成員可以建立、讀取、更新和刪除名稱空間內的非策略物件,如 Pod、Job 和 Ingress。開發者只在他們有權訪問的名稱空間中擁有這些許可權。

SaaS 提供商多租戶

SaaS 提供商叢集的租戶是應用的各個客戶專用例項,以及 SaaS 的控制平面。要充分利用按名稱空間劃分的政策,應將各個應用例項安排到其各自的名稱空間中,SaaS 控制平面的元件也應如此。終端使用者無法直接與 Kubernetes 控制平面互動,而是使用 SaaS 的介面,由後者與 Kubernetes 控制平面進行互動。

例如,部落格平臺可以在多租戶叢集上執行,在這種情況下,租戶是每個客戶的部落格例項和平臺自己的控制平面。平臺的控制平面和每個託管部落格都將在不同的名稱空間中執行。客戶將通過平臺的介面來建立和刪除部落格、更新部落格軟體版本,但無法瞭解叢集的運作方式。

多租戶策略

在 Kubernetes 中提供了幾項可用於管理多租戶叢集的功能。下面我們來分別介紹下這些功能。

名稱空間

Kubernetes 中的多租戶都是根據 Namespace 來進行劃分的,Namespace 是一組邏輯的叢集,可以大概類似於租戶的概念,可以做到一定程度的資源隔離、Quota。

如下面的兩條命令:

$ kubectl –namespace=abc run nginx –image=nginx
$ kubectl run nginx –image=nginx

這兩條命令雖然都是 run 起來一個 nginx,但是作用域卻不一樣。第一條命令是在一個叫 abc 的 namespace 裡執行nginx,第二條命令則是在 Default 這個名稱空間中。

訪問許可權控制

對於多租戶來說,訪問許可權控制是非常重要的,我們可以使用 Kubernetes 內建的 RBAC 來進行許可權控制,可以為叢集中的特定資源和操作授予細化的許可權。

對於 RBAC 的詳細使用可以參考 RBAC 章節

網路策略

通過叢集網路策略,我們可以控制叢集的 Pod 之間的通訊,策略可以指定 Pod 可以與哪些名稱空間、標籤和 IP 地址範圍進行通訊。

對於網路策略的詳細使用可以參考 網路策略 章節

資源配額

資源配額用於管理名稱空間中物件使用的資源量,我們可以按 CPU 和記憶體用量或物件數量來設定配額。通過資源配額,可以確保租戶不會使用超過其分配份額的叢集資源。

對於資源配額的使用可以參考 資源配額 章節.

Pod 安全策略

PodSecurityPolicies 是一種 Kubernetes API 型別,用於驗證建立和更新 Pod 的請求。PodSecurityPolicies 定義 Pod 規範中的安全敏感欄位的預設值和要求。您可以建立策略來限制部署那些會訪問主機檔案系統、網路、PID 名稱空間、卷等資源的 Pod。

瞭解 PSP 更多資訊,檢視 Pod 安全策略 章節

Pod 反親和性

注意:惡意租戶可以規避 Pod 反親和性規則。以下示例應僅用於具有受信任租戶的叢集,或租戶無法直接訪問 Kubernetes 控制平面的叢集。 我們可以利用 Pod 反親和性來防止不同租戶的 Pod 被排程到同一節點上。例如,下面的 Pod 規範描述了一個標籤為 team: billing 的 Pod,以及阻止該 Pod 與沒有該標籤的 Pod 排程到一起的反親和性規則。

apiVersion: v1
kind: Pod
metadata:
  name: bar
  labels:
    team: "billing"
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:  # 硬策略
      - topologyKey: "kubernetes.io/hostname"
        labelSelector:
          matchExpressions:
          - key: "team"
            operator: NotIn
            values: ["billing"]

上面這個資源清單的意思就是 bar 這個 Pod 不能排程到不具有 team: billing 這樣的標籤的 Pod 所在的節點,不過這種做法的缺點是惡意使用者可以通過將 team: billing 標籤新增到任意 Pod 來規避規則,僅使用 Pod 反親和性機制不足以在具有不受信任的租戶的叢集上安全地強制執行政策。

汙點和容忍

注意:惡意租戶可以規避由節點汙點和容忍機制強制執行的政策。以下示例應僅用於具有受信任租戶的叢集,或租戶無法直接訪問 Kubernetes 控制平面的叢集。

節點汙點是控制工作負載排程的另一種方法,您可以使用節點汙點來將專用節點留給某些租戶使用。例如,您可以將配備 GPU 的節點專門留給那些工作負載需要 GPU 的特定租戶。要將某個節點池專門留給某個租戶,請將具有 effect: "NoSchedule" 的汙點應用於該節點池,然後,只有具備相應容忍設定的 Pod 可以被排程到該節點池中的節點。

這種做法的缺點是惡意使用者可以通過為其 Pod 新增相應容忍設定來訪問專用節點池,所以僅使用節點汙點和容忍機制不足以在具有不受信任的租戶的叢集上安全地強制執行政策。

如果一個節點標記為汙點(Taints),除非 Pod 也被標識為可以容忍汙點節點,否則該 Taints 節點不會被排程 pod。

比如使用者希望把 Master 節點保留給 Kubernetes 系統元件使用,或者把一組具有特殊資源預留給某些 Pod,則汙點就很有用了,Pod 不會再被排程到 taint 標記過的節點。我們使用 kubeadm 搭建的叢集預設就給 master 節點添加了一個汙點標記,所以我們看到我們的普通 Pod 都沒有被排程到 master 上去:

$ kubectl describe node master
Name:               master
Roles:              master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=master
                    node-role.kubernetes.io/master=
......
Taints:             node-role.kubernetes.io/master:NoSchedule
Unschedulable:      false
......

我們可以使用上面的命令檢視 master 節點的資訊,其中有一條關於 Taints 的資訊:node-role.kubernetes.io/master:NoSchedule,就表示給 master 節點打了一個汙點的標記,其中影響的引數是NoSchedule,表示 Pod 不會被排程到標記為 taints 的節點,除了 NoSchedule 外,還有另外兩個選項:

  • PreferNoSchedule:NoSchedule 的軟策略版本,表示儘量不排程到汙點節點上去
  • NoExecute:該選項意味著一旦 Taint 生效,如該節點內正在執行的 Pod 沒有對應 Tolerate 設定,會直接被逐出

汙點 taint 標記節點的命令如下:

$ kubectl taint nodes node02 test=node02:NoSchedule
node "node02" tainted

上面的命名將 node02 節點標記為了汙點,影響策略是 NoSchedule,只會影響新的 Pod 排程,如果仍然希望某個 Pod 排程到 taint 節點上,則必須在 Spec 中做出 Toleration 定義,才能排程到該節點,比如現在我們想要將一個 Pod 排程到 master 節點:(taint-demo.yaml)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: taint
  labels:
    app: taint
spec:
  selector:
    matchLabels:
      app: taint
  replicas: 2
  template:
    metadata:
      labels:
        app: taint
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - name: http
          containerPort: 80
      tolerations:
      - key: "node-role.kubernetes.io/master"
        operator: "Exists"
        effect: "NoSchedule"

由於 master 節點被標記為了汙點節點,所以我們這裡要想 Pod 能夠排程到 master 節點去,就需要增加容忍的宣告:

tolerations:
- key: "node-role.kubernetes.io/master"
  operator: "Exists"
  effect: "NoSchedule"

然後建立上面的資源,檢視結果:

$ kubectl create -f taint-demo.yaml
deployment.apps "taint" created
$ kubectl get pods -o wide
NAME                                      READY     STATUS             RESTARTS   AGE       IP             NODE
......
taint-845d8bb4fb-57mhm                    1/1       Running            0          1m        10.244.4.247   node02
taint-845d8bb4fb-bbvmp                    1/1       Running            0          1m        10.244.0.33    master
taint-845d8bb4fb-zb78x                    1/1       Running            0          1m        10.244.4.246   node02
......

我們可以看到有一個 Pod 副本被排程到了 master 節點,這就是容忍的使用方法。

對於 tolerations 屬性的寫法,其中的 key、value、effect 與節點的 Taint 設定需保持一致, 還有以下幾點說明:

  • 如果 operator 的值是 Exists,則 value 屬性可省略
  • 如果 operator 的值是 Equal,則表示其 key 與 value 之間的關係是 equal(等於)
  • 如果不指定 operator 屬性,則預設值為 Equal

另外,還有兩個特殊值:

  • 空的 key 如果再配合 Exists 就能匹配所有的 key 與 value,也就是能容忍所有節點的所有 Taints
  • 空的 effect 匹配所有的 effect

最後,如果我們要取消節點的汙點標記,可以使用下面的命令:

$ kubectl taint nodes node02 test-
node "node02" untainted