Istio 軟性多租戶支援

使用 Kubernetes 命名空間和 RBAC 建立 Istio 軟性多租戶環境。

2018 年 4 月 19 日 | 作者:John Joyce 和 Rich Curran

多租戶 (Multi-tenancy) 通常在許多不同應用程式中的許多環境中使用,但在每個租戶的基礎上提供的實作細節和功能並不遵循所有環境中的單一模型。Kubernetes 多租戶工作組正在努力定義多租戶的使用案例和應在 Kubernetes 中提供的功能。但是,從他們目前的工作來看,很明顯由於無法完全防止惡意容器或工作負載存取其他租戶的 Pod 或核心資源,因此只有「軟性多租戶」是可行的。

軟性多租戶

在本部落格中,「軟性多租戶」定義為具有單一 Kubernetes 控制平面,多個 Istio 控制平面和多個網格,每個租戶一個控制平面和一個網格。叢集管理員可以控制和查看所有 Istio 控制平面,而租戶管理員只能控制特定的 Istio 實例。租戶之間的隔離由 Kubernetes 命名空間和 RBAC 提供。

此部署模型的一個使用案例是共享公司基礎架構,其中不期望發生惡意行為,但仍然需要乾淨地分離租戶。

本部落格的底部描述了未來潛在的 Istio 多租戶部署模型。

部署

多個 Istio 控制平面

部署多個 Istio 控制平面首先要將資訊清單檔案中的所有 namespace 參考取代為所需的命名空間。以 istio.yaml 為例,如果需要兩個租戶級別的 Istio 控制平面;第一個可以使用 istio.yaml 的預設名稱 istio-system,而第二個控制平面可以透過產生具有不同命名空間的新 yaml 檔案來建立。例如,以下命令會建立一個 yaml 檔案,其 Istio 命名空間為 istio-system1

$ cat istio.yaml | sed s/istio-system/istio-system1/g > istio-system1.yaml

istio.yaml 檔案包含 Istio 控制平面部署的詳細資訊,包括構成控制平面的 Pod (Mixer、Pilot、Ingress、Galley、CA)。部署兩個 Istio 控制平面 yaml 檔案

$ kubectl apply -f install/kubernetes/istio.yaml
$ kubectl apply -f install/kubernetes/istio-system1.yaml

會在兩個命名空間中執行兩個 Istio 控制平面。

$ kubectl get pods --all-namespaces
NAMESPACE       NAME                                       READY     STATUS    RESTARTS   AGE
istio-system    istio-ca-ffbb75c6f-98w6x                   1/1       Running   0          15d
istio-system    istio-ingress-68d65fc5c6-dnvfl             1/1       Running   0          15d
istio-system    istio-mixer-5b9f8dffb5-8875r               3/3       Running   0          15d
istio-system    istio-pilot-678fc976c8-b8tv6               2/2       Running   0          15d
istio-system1   istio-ca-5f496fdbcd-lqhlk                  1/1       Running   0          15d
istio-system1   istio-ingress-68d65fc5c6-2vldg             1/1       Running   0          15d
istio-system1   istio-mixer-7d4f7b9968-66z44               3/3       Running   0          15d
istio-system1   istio-pilot-5bb6b7669c-779vb               2/2       Running   0          15d

如果需要,Istio Sidecar附加元件資訊清單也必須部署以符合租戶 Istio 控制平面正在使用的已設定 namespace

這兩個 yaml 檔案的執行是叢集管理員的責任,而不是租戶級別管理員的責任。叢集管理員也需要設定和套用額外的 RBAC 限制,將租戶管理員限制為僅限分配的命名空間。

拆分通用和命名空間特定資源

Istio 儲存庫中的資訊清單檔案會建立所有 Istio 控制平面都會使用的通用資源,以及每個控制平面都會複製的資源。雖然透過取代上述的 istio-system 命名空間參考來部署多個控制平面是一件簡單的事情,但更好的方法是將資訊清單分成一個所有租戶部署一次的通用部分和一個租戶特定的部分。對於 自訂資源定義,角色和角色綁定應與提供的 Istio 資訊清單分開。此外,提供的 Istio 資訊清單中的角色和角色綁定可能不適合多租戶環境,應按照下一節所述進行修改或擴充。

Istio 控制平面資源的 Kubernetes RBAC

若要將租戶管理員限制為單一 Istio 命名空間,叢集管理員將建立一個包含至少一個 RoleRoleBinding 的資訊清單,類似於下方的範例。在此範例中,名為 *sales-admin* 的租戶管理員被限制為命名空間 istio-system1。完整的資訊清單將在 Role 下包含更多 apiGroups,為租戶管理員提供資源存取權。

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: istio-system1
  name: ns-access-for-sales-admin-istio-system1
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["*"]
  verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: access-all-istio-system1
  namespace: istio-system1
subjects:
- kind: User
  name: sales-admin
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: ns-access-for-sales-admin-istio-system1
  apiGroup: rbac.authorization.k8s.io

監視特定命名空間以進行服務探索

除了建立 RBAC 規則以限制租戶管理員對特定 Istio 控制平面的存取之外,還必須更新 Istio 資訊清單,以指定 Pilot 應監視其 xDS 快取建立的應用程式命名空間。這是透過使用額外的命令行參數 --appNamespace, ns-1 啟動 Pilot 元件來完成的。其中 *ns-1* 是租戶應用程式將部署在其中的命名空間。以下顯示了 istio-system1.yaml 檔案的範例片段。

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: istio-pilot
  namespace: istio-system1
  annotations:
    sidecar.istio.io/inject: "false"
spec:
  replicas: 1
  template:
    metadata:
      labels:
        istio: pilot
    spec:
      serviceAccountName: istio-pilot-service-account
      containers:
      - name: discovery
        image: docker.io/<user ID>/pilot:<tag>
        imagePullPolicy: IfNotPresent
        args: ["discovery", "-v", "2", "--admission-service", "istio-pilot", "--appNamespace", "ns-1"]
        ports:
        - containerPort: 8080
        - containerPort: 443

在命名空間中部署租戶應用程式

現在,叢集管理員已建立租戶的命名空間 (例如 istio-system1),並且 Pilot 的服務探索已設定為監視特定的應用程式命名空間 (例如 *ns-1*),請建立應用程式資訊清單以部署在該租戶的特定命名空間中。例如

apiVersion: v1
kind: Namespace
metadata:
  name: ns-1

並將命名空間參考新增至應用程式資訊清單檔案中包含的每個資源類型。例如

apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
  namespace: ns-1

雖然未顯示,但應用程式命名空間也將具有限制對某些資源存取的 RBAC 設定。這些 RBAC 設定可以由叢集管理員和/或租戶管理員設定。

在多租戶環境中使用 kubectl

定義路由規則目標策略時,必須確保 kubectl 命令的範圍限定在 Istio 控制平面正在執行的命名空間中,以確保資源在正確的命名空間中建立。此外,規則本身必須限定在租戶的命名空間中,以便正確套用至該租戶的網格。 -i 選項用於在部署 Istio 控制平面的命名空間中建立 (或取得或描述) 規則。 -n 選項會將規則限定在租戶的網格中,並且應設定為部署租戶應用程式的命名空間。請注意,如果資源的 .yaml 檔案正確地限定了範圍,則可以在命令行上跳過 -n 選項。

例如,需要以下命令才能將路由規則新增至 istio-system1 命名空間

$ kubectl –i istio-system1 apply -n ns-1 -f route_rule_v2.yaml

可以使用以下命令顯示

$ kubectl -i istio-system1 -n ns-1 get routerule
NAME                  KIND                                  NAMESPACE
details-Default       RouteRule.v1alpha2.config.istio.io    ns-1
productpage-default   RouteRule.v1alpha2.config.istio.io    ns-1
ratings-default       RouteRule.v1alpha2.config.istio.io    ns-1
reviews-default       RouteRule.v1alpha2.config.istio.io    ns-1

請參閱本文件的多個 Istio 控制平面部分,以取得有關多租戶環境中 namespace 需求的更多詳細資訊。

測試結果

按照上述說明,叢集管理員可以建立一個環境,透過 RBAC 和命名空間限制租戶管理員可以部署的內容。

部署後,允許存取分配給特定租戶管理員的 Istio 控制平面 Pod

$ kubectl get pods -n istio-system
NAME                                      READY     STATUS    RESTARTS   AGE
grafana-78d649479f-8pqk9                  1/1       Running   0          1d
istio-ca-ffbb75c6f-98w6x                  1/1       Running   0          1d
istio-ingress-68d65fc5c6-dnvfl            1/1       Running   0          1d
istio-mixer-5b9f8dffb5-8875r              3/3       Running   0          1d
istio-pilot-678fc976c8-b8tv6              2/2       Running   0          1d
istio-sidecar-injector-7587bd559d-5tgk6   1/1       Running   0          1d
prometheus-cf8456855-hdcq7                1/1       Running   0          1d

但是,不允許存取所有叢集的 Pod

$ kubectl get pods --all-namespaces
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods at the cluster scope

也不允許存取另一個租戶的命名空間

$ kubectl get pods -n istio-system1
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods in the namespace "istio-system1"

租戶管理員可以在為該租戶設定的應用程式命名空間中部署應用程式。例如,更新 Bookinfo 資訊清單,然後在租戶的應用程式命名空間 *ns-0* 下部署,允許列出此租戶命名空間正在使用的 Pod

$ kubectl get pods -n ns-0
NAME                              READY     STATUS    RESTARTS   AGE
details-v1-64b86cd49-b7rkr        2/2       Running   0          1d
productpage-v1-84f77f8747-rf2mt   2/2       Running   0          1d
ratings-v1-5f46655b57-5b4c5       2/2       Running   0          1d
reviews-v1-ff6bdb95b-pm5lb        2/2       Running   0          1d
reviews-v2-5799558d68-b989t       2/2       Running   0          1d
reviews-v3-58ff7d665b-lw5j9       2/2       Running   0          1d

但無法存取另一個租戶的應用程式命名空間

$ kubectl get pods -n ns-1
Error from server (Forbidden): pods is forbidden: User "dev-admin" cannot list pods in the namespace "ns-1"

如果部署了 附加工具,例如 Prometheus,(也受 Istio namespace 限制),則傳回的統計結果僅代表從該租戶的應用程式命名空間看到的流量。

結論

執行的評估表明 Istio 具有足夠的功能和安全性來滿足少數多租戶使用案例。它還表明 Istio 和 Kubernetes 無法為其他使用案例提供足夠的功能和安全性,特別是那些需要在不受信任的租戶之間完全安全和隔離的使用案例。要達到更安全的安全性及隔離模型所需的改進需要在容器技術 (例如 Kubernetes) 中進行,而不是 Istio 功能的改進。

問題

其他多租戶模型的挑戰

考慮了其他多租戶部署模型

  1. 具有多個應用程式的單一網格,每個租戶在網格上一個。叢集管理員可以控制和查看整個網格和所有應用程式,而租戶管理員只能控制特定的應用程式。

  2. 具有多個網格的單一 Istio 控制平面,每個租戶一個網格。叢集管理員可以控制和查看整個 Istio 控制平面和所有網格,而租戶管理員只能控制特定的網格。

  3. 單一雲端環境 (叢集控制),但有多個 Kubernetes 控制平面 (租戶控制)。

這些選項要么在沒有程式碼變更的情況下無法正確支援,要么無法完全解決使用案例。

目前的 Istio 功能不適合支援第一個模型,因為它缺乏足夠的 RBAC 功能來支援叢集與租戶操作。此外,在一個網格下有多個租戶對於目前的網格模型以及 Istio 將組態驅動到 Envoy Proxy 的方式而言,太不安全。

關於第二個選項,目前的 Istio 範例假設每個 Istio 控制平面一個網格。支援此模型所需的變更很大。它們需要根據命名空間對資源和安全網域進行更精細的範圍設定,以及額外的 Istio RBAC 變更。此模型可能會在未來的工作中解決,但目前無法實現。

第三個模型不符合大多數使用案例,因為大多數叢集管理員更喜歡他們作為 PaaS 提供給租戶的通用 Kubernetes 控制平面。

未來工作

允許單一 Istio 控制平面控制多個網格,顯然是下一個重要的功能。另一個改進之處是提供一個單一網格,可以託管不同的租戶,並且在租戶之間提供一定程度的隔離和安全性。這可以透過在單一控制平面內使用與 Kubernetes 相同的邏輯命名空間概念進行分割來實現。Istio 社群已開始撰寫一份文件,以定義額外的使用案例以及支援這些使用案例所需的 Istio 功能。

參考資料

分享此文章