【Kubernetes】基於角色的許可權控制:RBAC
Kubernetes中所有的API物件,都儲存在Etcd裡,對這些API物件的操作,一定都是通過訪問kube-apiserver實現的,原因是需要APIServer來做授權工作。
在Kubernetes中,負責完成授權(Authorization)工作的機制,就是RBAC:基於角色的訪問控制(Role-Based Access Control)
RBAC中有三個最基本的概念:
1、Role:角色,它其實是一組規則,定義了一組對Kubernetes API物件的操作許可權
Role本身是一個Kubernetes的API物件,定義如下所示:
kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: mynamespace ## 指定它能產生作用的Namespace name: example-role rules: ## 定義許可權規則 - apiGroups: [""] resources: ["pods"] ## 對mynamespace下面的Pod物件 verbs: ["get", "watch", "list"] ## 進行GET、WATCH、LIST操作
2、Subject:被作用者,既可以是“人”,也可以是“機器”,也可以是Kubernetes裡定義的“使用者”
3、RoleBinding:定義了“被作用者”和“角色”的繫結關係
RoleBingding本身也是一個Kubernetes的API物件
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-rolebinding namespace: mynamespace subjects: ## 被作用者 - kind: User ## 型別是User name: example-user ## 使用者名稱是example-user apiGroup: rbac.authorization.k8s.io roleRef: ## 通過roleRef欄位,RoleBinding物件可以直接通過名字來引用Role物件,從而定義了被作用者(Subject)和角色(Role)之間的關係 kind: Role name: example-role apiGroup: rbac.authorization.k8s.io
需要注意的是:Role和RoleBinding物件都是Namespaced物件,它們對許可權限制規則僅在它們自己的Namespace內有效,roleRef也只能引用當前Namespace裡的Role物件
那對於非Namespaced物件(如: node)或者一個Role想作用於所有的Namespace的時候,又該如何去做授權呢?
這個時候就必須要使用ClusterRole和ClusterRoleBinding這個組合了,這兩個API物件的用法跟Role和RoleBinding完全一樣,只不過它們的定義裡沒有了Namespace欄位
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-clusterrole rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-clusterrolebinding subjects: - kind: User name: example-user apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: example-clusterrole apiGroup: rbac.authorization.k8s.io
上面的例子裡意味著名叫example-user的使用者擁有對所有Namespace裡的Pod進行GET、WATCH和LIST操作的許可權。
如果想要賦予使用者所有許可權,那可以給它指定一個verbs欄位的全集
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
Role物件的Rules欄位也可以進一步細化,如可以只針對某一個具體的物件進行許可權設定
rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-config"] verbs: ["get"]
那現在還有一個問題,在Kubernetes中其實並沒有一個叫做“User”的API物件,那這個User從哪裡來呢?
在Kubernetes的User只是一個授權系統裡的邏輯概念,在大多數私有的使用環境中,只需要使用Kubernetes提供的內建“使用者”足夠了。負責管理內建使用者的是ServiceAccount
首先定義一個ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: namespace: mynamespace name: example-sa
然後通過編寫RoleBinding的YAML檔案,來為這個ServiceAccount分配許可權
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: example-rolebinding namespace: mynamespace subjects: - kind: ServiceAccount name: example-sa namespace: mynamespace roleRef: kind: Role name: example-role apiGroup: rbac.authorization.k8s.io
接著建立這個三個物件
$ kubectl create -f svc-account.yaml $ kubectl create -f role-binding.yaml $ kubectl create -f role.yaml $ kubectl get sa -n mynamespace -o yaml - apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: 2018-09-08T12:59:17Z name: example-sa namespace: mynamespace resourceVersion: "409327" ... secrets: - name: example-sa-token-vmfg6
可以看到,Kubernetes會為一個ServiceAccount自動建立並分配一個Secret物件。這個Secret就是ServiceAccount對應的、用來跟APIServer進行互動的授權檔案,一般稱為Token。 Token檔案的內容一般是證書或者密碼,它以一個Secret物件的方式儲存在Etcd中。
這時候,使用者的Pod就可以宣告使用這個ServiceAccount了
apiVersion: v1 kind: Pod metadata: namespace: mynamespace name: sa-token-test spec: containers: - name: nginx image: nginx:1.7.9 serviceAccountName: example-sa $ kubectl describe pod sa-token-test -n mynamespace Name: sa-token-test Namespace: mynamespace ... Containers: nginx: ... Mounts: /var/run/secrets/kubernetes.io/serviceaccount from example-sa-token-vmfg6 (ro)
如果一個Pod沒有宣告serviceAccountName,Kubernetes會自動在它的Namespace下建立一個名叫default的預設ServiceAccount,然後分配給這個Pod,這個預設的ServiceAccount並沒有關聯任何Role。
除了 前面使用的User,Kubernetes還有使用者組(Group)的概念
實際上一個ServiceAccount,在Kubernetes裡對應的User的名字是:
system:serviceaccount:<ServiceAccount 名字 >
那它對應的Group的名字就是
system:serviceaccounts:<Namespace 名字 >
現在可以在RoleBinding裡定義如下的subjects:
subjects: - kind: Group name: system:serviceaccounts:mynamespace ## Role許可權規則作用於Namespace裡所有的ServiceAccount apiGroup: rbac.authorization.k8s.io subjects: - kind: Group name: system:serviceaccounts ## Role許可權規則作用於整個系統裡所有ServiceAccount apiGroup: rbac.authorization.k8s.io