0%

Kubeflow 如何搭配 Istio 實作 Multi-user 認證與權限管理(上)

前言

既前一篇在 Kubeflow 部署 中分享如何安裝 Kubeflow v0.7 Multi-User 版本後,接下來將會詳解其實做原理,因為他的做法非常 Kubernetes Native 值得大家參考!

原本的 Kubeflow 各項服務都是獨立的專案,使用方式是分別的操作 Jupyter UI 來開啟 Jupyterhub ,或是使用 Kubeflow Pipeline UI 來創建一個 Workflow 。這使得整體的使用有些破碎, Kubeflow 在接下來的發展將會搭配一個統一的 Dashboard UI 與認證方案來解決,以下是過去的缺點與將帶來的好處。

  • 過去使用者必須對K8s有一定程度的瞭解,甚至在使用 Kubeflow 服務時,必須用 kubectl 來操作 Kubernetes 資源,這提高了 Data Scientists 使用的門檻。
    • 接下來的 Kubeflow 發展將讓使用者更好理解各項服務的資源,將 low-level Kubernetes API Resource 抽象並近一步定義 high level Kubeflow API
  • 過去每一個服務相互獨立,並不方便完成使用者認證與權限管理,使用每一個服務時都必須單獨做認證。
    • 搭配一個統一的 Dashboard UIKubeflow API Entry Point ,使用者使用服務時只要在 Entry Point 這一層做認證。

而當我們定義了一系列 Kubeflow API Resource ,像是 models, trainging dataset, pipelines等。我們就可以在這些資源上自然地執行權限管理。

Kubeflow Multi-user 情境

過去除了缺乏一個統一的 Kubeflow API Entry Point 與 Kubeflow API Resource 外, Multi-user 的情境也是大家夢寐以求的。

一個合理的 Multi-user 情境如下

多個使用者會擁有自己的 Kubeflow 資源,且與其餘使用者隔離,比方說創建的 pipeline 或是 notebook
同時 Kubeflow 也提供共享的 Group 資源,可以讓多個使用者共同分享。

Multi-user, 認證權限管理Kubeflow API Resource 彼此相輔相成,以下開始介紹 Kubeflow 怎麼提出一個完整的解決方法。

Kubeflow/Kubernetes 認證與權限管理

附圖是認證與權限管理的架構流程圖

透過一個 Kubeflow API Gateway ,所有使用 Kubeflow 服務請求可以在這一層做認證與權限管理。

第一點注意到的是,其實我們需要針對兩種資源與服務做認證與權限,也就是 Kubernetes 原生資源與 Kubeflow 資源。

舉幾個例子可以讓大家快速了解這兩個資源使用情境。

  1. 對於 Kubeflow 認證與權限的情境比方說

    • 當透過 Kubeflow/Jupyterhub UI 開一個 notebook ,首先會透過瀏覽器連到 Kubeflow Jupyterhub UI 服務,這邊是 Kubeflow層級服務 需要做 使用者認證 來驗證使用者可否用這個服務。
    • 開啟 notebook 後,哪些帳號可以共同編輯該 notebook ,甚至在這裏引進 group 概念,同一個 group 的成員都可以編輯共享的 notebook。
  2. 對於 Kubernetes 認證與權限的情境比方說

    • 在自己的帳號底下可以列出哪些 notebook pods
    • 使用 kubctl 直接操作 Kubernetes 資源

也因此我們在管理使用者與群組的認證與權限時,必須將 Kubeflow 服務層級與 Kubernetes 原生資源整合。

而 Kubeflow 給出的答案就是使用

  1. 一個獨立的 Authservice
  2. Istio/Istio-RBAC
  3. Kubernetes Namespace/RBAC

Kubeflow Profiles Operator

我們先來看 資源使用權限 如何實作。

Kubeflow使用的是一個 Profile Operator 來管理使用者的資源使用權限。

當在Kubeflow創建一個使用者時,其實是創建了一個 Profile CRD 。同時每一個使用者都會被賦予一個 Namespace 與在該 Namespace 操作創建資源的 Privilege 。這部分便是透過 Profile-Operatoristio RBACK8s RBAC

我們直接從哪些資源會跟著 Profile 創建來看。

Profile CRD

一個 Profile 會包含名稱與信箱,接下來將會實作針對每個使用者的資源限制!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
apiVersion: kubeflow.org/v1beta1
kind: Profile
metadata:
name: kubeflow-user1
spec:
owner:
kind: User
name: user1@abcd.com
plugins:
- kind: WorkloadIdentity
spec:
gcpServiceAccount: kubeflow2@project-id.iam.gserviceaccount.com
# resourceQuotaSpec:
# hard:
# cpu: "10"
# memory: 20Gi
# pods: "20"

Namespace

Controller 會創建一個與使用者同名的 Namespace,並標為 istio-enabled 以利後面引入 Istio 做認證與權限管理。

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Namespace
metadata:
annotations:
owner: admin@kubeflow.org
labels:
istio-injection: enabled
name: admin
spec:
finalizers:
- kubernetes
status:
phase: Active

Istio RBAC

這部分就是利用 Istio 來實作權限認證的環節,限制使用者可以連線使用的服務。方法是在該使用者的Namespace底下創建 Istio-ServiceRoleIstio-ServiceRoleBinding

1
2
3
4
5
6
7
8
9
10
11
12
13
$ kubectl get -o yaml servicerole/ns-access-istio -n admin
apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRole
metadata:
annotations:
role: admin
user: admin@kubeflow.org
name: ns-access-istio
namespace: admin
spec:
rules:
- services:
- '*'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ kubectl get -o yaml servicerolebinding/owner-binding-istio -n admin
apiVersion: rbac.istio.io/v1alpha1
kind: ServiceRoleBinding
metadata:
annotations:
role: admin
user: admin@kubeflow.org
name: owner-binding-istio
namespace: admin
spec:
roleRef:
kind: ServiceRole
name: ns-access-istio
subjects:
- properties:
request.headers[kubeflow-userid]: admin@kubeflow.org

透過 Istio-ServiceRoleIstio-ServiceRoleBinding 使得只有該使用者有權限可以連線該 Namespace 底下的服務。可以看到的是這邊如何認知送來的請求是該使用者,檢查的是 Header 裡面的 kubeflow-userid 欄位。這個欄位就是在使用者登入後覆寫夾帶的欄位,後面會介紹這部分的環節。

Owner rbac permission

剛剛是利用 Istio 來實作服務的權限管理,接下來是 Kubernetes原生資源 的權限管理,這邊就是用大家比較熟悉的 RBAC,也就是 ClusterRoleRoleBinding 。另外特別需要注意的就是 ClusterRole 雖然是 Cluster scoped 的權限,但是當他透過 Namespace scoped 的 RoleBinding 綁定到使用者後,就是 Namespace scoped 的權限。

以下 RoleBindingadmin權限 綁定到 admin 這個 user 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
role: admin
user: admin@kubeflow.org
name: namespaceAdmin
namespace: admin #Namespace permission
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin # original Kubernetes ClusterRole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: admin@kubeflow.org

ServiceAccount

  1. default-deitor: 帶有 edit 權限的 ServiceAccount ,可以改動 Namespace admin 底下的所有資源,除了 RBAC 。用途比方說, Jupyterhub 在該 Namespace 底下的 notebook pod 就會是綁定這個 ServiceAccount
1
2
3
4
5
6
7
8
9
$ kubectl get -o yaml serviceaccount/default-editor -n admin

apiVersion: v1
kind: ServiceAccount
metadata:
name: default-editor
namespace: admin # under admin namespace
secrets:
- name: default-editor-token-qrllp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ kubectl get -o yaml rolebinding/default-editor -n admin

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: default-editor
namespace: admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole # Original K8s ClusterRole edit
name: edit
subjects:
- kind: ServiceAccount
name: default-editor
namespace: admin # The Clusterrole is binding with namespace-scoped ServiceAccoun.
  1. default-viewer: 帶有 view 權限的 ServiceAccount ,可以 list/get Namespace admin 底下的所有資源。
1
2
3
4
5
6
7
8
9
10
kubectl get -o yaml serviceaccount/default-viewer -n admin

apiVersion: v1
kind: ServiceAccount
metadata:
name: default-viewer
namespace: admin
secrets:
- name: default-viewer-token-sdr96
apiVersion: rbac.authorization.k8s.io/v1
1
2
3
4
5
6
7
8
9
10
11
12
kind: RoleBinding
metadata:
name: default-viewer
namespace: admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: default-viewer
namespace: admin

小結

Kubeflow 使用 Profile 來管理使用者,圍繞這個 CRD,管理 K8s RBACIstio RBAC 等相關資源來管理 資源使用權限

而透過這樣的資源全限管理,我們便可以發展多使用者與群組的功能,回顧一下一開始的情境圖。

也因此剩下的工作就是如何處理最外面的 Istio Gateway,並進而針對使用者做認證。