Kubernetes RBAC
一、簡介
RBAC
(Role-Based Access Control,基於角色的訪問控制),作為Kubernetes安裝方式的預設選項,足見其重要程度,相對於其他訪問控制方式,RBAC具有以下優勢:
-
對叢集中的資源和非資源許可權均有完整的覆蓋
-
整個RBAC完全由幾個API物件完成,同其他API物件一樣,可以用kubect或API進行操作
-
可以在執行時進行調整,無須重啟啟動API Server
RBAC
使用 rbac.authorization.k8s.io
API Group來實現授權決策,允許管理員通過kubernetes API動態配置策略,要啟用RBAC
,需要在apiserver 中新增引數 --authorization-mode=RBAC
二、RBAC API物件
Kubernetes
有一個很基本的特性就是它的所有資源物件都是模型化的API物件,允許執行CRUD(Create、Read、Update、Delete)操作(也就是我們常說的增、刪、改、查操作),比如下面的資源:
-
Pods
-
ConfigMaps
-
Deployments
-
Nodes
-
Secrets
-
Namespaces
上面的這些資源物件的可能存在的操作:
-
create
-
get
-
delete
-
list
-
update
-
edit
-
watch
-
exec
在更上層,這些資源和API Group進行關聯,比如Pods
Deployment
屬於apps API Group,要在Kubernetes
中進行RBAC
的管理,除了上面的這些資源和操作外,我們還需要另外的一些物件:
-
Rule:規則,規則是一組屬於不同API Group資源上的一組操作的集合
-
Role 和 ClusterRole:角色和叢集角色,這兩個物件都包含上面的Rule元素,二者區別在於,在Role中,定義的規則只適用於單個名稱空間,也就是和namespace關聯的,而ClusterRole是叢集範圍內的,因此定義的規則不受名稱空間的約束。另外Role和ClusterRole在Kubernetes中都被定義為叢集內部的API資源,和Pod、ConfigMap這些類似,都是叢集資源的物件,所有同意的可以使用kubectl相關命令來進行操作
-
Subject:主題,對應在叢集中嘗試操作的物件,叢集中定義了3種類型的主題資源:
-
User Account:使用者,這是由外部獨立服務進行管理的,管理員進行私鑰的分配,使用者可以使用KeyStone或者Google賬號,甚至一個使用者名稱和密碼的檔案列表也可以。對於使用者的管理叢集內部沒有一個關聯的資源物件,所以使用者不能通過叢集內部的API進行管理
-
Group:組,這是用來關聯多個賬戶的,叢集中有一些預設建立的組,比如cluster-admin
-
Service Account:服務賬號,通過Kubernetes API來管理的一些使用者賬號,和namespace進行關聯,適用於叢集內部執行的應用程式,需要通過API來完成許可權認證,所以在叢集內部進行許可權操作,我們都需要使用到Service Account
-
-
Role Binding和ClusterRoleBinding:角色繫結和叢集角色繫結,簡單的來說就是把宣告的Subject和我們的Role進行繫結的 過程(給某個使用者繫結上操作的許可權),二者的區別也是作用範圍的區別:RoleBinding只會影響到當前namespace下面的資源操作許可權,而ClusterRoleBinding會影響到所有的namespace。
三、建立一個只能訪問某個namespace的使用者
3.1 建立一個User Account,只能訪問kube-system這個名稱空間
-
username: tunan
-
group:jiang
(1)給使用者tunan建立一個私鑰,命名為:tunan.key
# openssl genrsa -out tunan.key 2048
(2)使用剛剛建立的私鑰新建一個證書籤名請求檔案:tunan.csr,確保引數-subj引數中指定使用者名稱和組(CN表示使用者名稱,O表示組)
# openssl req -new -key tunan.key -out tunan.csr -subj "/CN=tunan/O=jiang"
(3)找到kubernetes叢集的CA,利用叢集的ca.crt和ca.key兩個檔案來批准上面的證書請求,並設定500天有效期
# openssl x509 -req -in tunan.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki//ca.key -CAcreateserial -out tunan.crt -days 500
(4)檢視證書
# ls tunan.crt tunan.csr tunan.key
(5)使用剛建立的證書檔案和私鑰檔案在叢集中建立新的憑證和上下文(Context)
# kubectl config set-credentials tunan --client-certificate=tunan.crt --client-key=tunan.key User "tunan" set.
(6)為這個使用者設定新的Context
# kubectl config set-context tunan-context --cluster=kubernetes --namespace=kube-system --user=tunan Context "tunan-context" created.
(7)此時使用這個配置檔案來操作kubectl會出錯,因為還沒有定義任何操作許可權
# kubectl get pods --context=tunan-context Error from server (Forbidden): pods is forbidden: User "tunan" cannot list resource "pods" in API group "" in the namespace "kube-system"
3.2 建立角色
使用者完成後,接下來需要給使用者新增操作許可權,建立一個允許使用者操作Deployment、Pod、ReplicaSets的角色
-
tunan-role.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: tunan-role namespace: kube-system rules: - apiGroups: ["","extensions","apps"] resources: ["deployments","replicasets","pods"] verbs: ["get","list","watch","create","patch","delete"] # 全部許可權可以使用["*"]
apiGroups中[""] 代表核心API Group,
ReplicasSets
屬於extensions
這個API Group,而Deployments
屬於apps
這個API Group。上面的verbs
就是對這些資源物件執行的操作 -
建立這個Role
# kubectl create -f tunan-role.yaml role.rbac.authorization.k8s.io/tunan-role created
3.3 建立角色繫結
Role建立完成後,但是這個Role和使用者tunan還沒有任何關係,這裡就需要建立一個RoleBinding物件,在kube-system這個名稱空間下面將上面的tunan-role 角色和使用者 tunan進行繫結
-
tunan-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tunan-rolebinding namespace: kube-system subjects: - kind: User name: tunan apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: tunan-role apiGroup: rbac.authorization.k8s.io
-
檢視
# kubectl describe role tunan-role -n kube-system Name: tunan-role Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- deployments [] [] [get list watch create patch delete] pods [] [] [get list watch create patch delete] replicasets [] [] [get list watch create patch delete] deployments.apps [] [] [get list watch create patch delete] pods.apps [] [] [get list watch create patch delete] replicasets.apps [] [] [get list watch create patch delete] deployments.extensions [] [] [get list watch create patch delete] pods.extensions [] [] [get list watch create patch delete] replicasets.extensions [] [] [get list watch create patch delete] # kubectl describe rolebinding tunan-rolebinding -n kube-system Name: tunan-rolebinding Labels: <none> Annotations: <none> Role: Kind: Role Name: tunan-role Subjects: Kind Name Namespace ---- ---- --------- User tunan
-
驗證
# kubectl get pods --context=tunan-context NAME READY STATUS RESTARTS AGE coredns-66bff467f8-hqqz7 1/1 Running 10 12d coredns-66bff467f8-z2hr4 1/1 Running 10 12d etcd-master 1/1 Running 11 12d kube-apiserver-master 1/1 Running 11 12d kube-controller-manager-master 1/1 Running 13 12d ...
四、建立一個只能訪問某個namespace的ServiceAccount
建立一個叢集內部的使用者ServiceAccount,只能操作kube-system這個名稱空間下面的pods和deployments
-
sa.yaml
apiVersion: v1 kind: ServiceAccount metadata: name: tunan-sa namespace: kube-system
-
建立sa
# kubectl create -f sa.yaml # kubectl get sa tunan-sa -n kube-system NAME SECRETS AGE tunan-sa 1 19s
-
建立一個新的Role物件
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: tunan-sa-role namespace: kube-system rules: - apiGroups: [""] resources: ["pods"] verbs: ["get","watch","list"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ['get','list','watch','create','update','patch','delete'] # kubectl create -f tunan-sa-role.yaml role.rbac.authorization.k8s.io/tunan-sa-role created # kubectl get role tunan-sa-role -n kube-system NAME CREATED AT tunan-sa-role 2020-06-17T03:40:00Z # kubectl describe role tunan-sa-role -n kube-system Name: tunan-sa-role Labels: <none> Annotations: <none> PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- deployments.apps [] [] [get list watch create update patch delete] pods [] [] [get watch list]
-
建立一個Rolebinding,將上面的tunan-sa 和 tunan-sa-role進行繫結
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tunan-sa-rolebinding namespace: kube-system subjects: - kind: ServiceAccount name: tunan-sa namespace: kube-system roleRef: kind: Role name: tunan-sa-role apiGroup: rbac.authorization.k8s.io # kubectl get rolebinding tunan-sa-rolebinding -n kube-system NAME ROLE AGE tunan-sa-rolebinding Role/tunan-sa-role 30s # kubectl describe rolebinding tunan-sa-rolebinding -n kube-system Name: tunan-sa-rolebinding Labels: <none> Annotations: <none> Role: Kind: Role Name: tunan-sa-role Subjects: Kind Name Namespace ---- ---- --------- ServiceAccount tunan-sa kube-system
-
驗證
每個ServiceAccount會生成一個Srcret物件和它進行對映,這個Secret裡面包含一個token,可以利用這個token去登入Dashboard,可以在Dashboard中驗證功能是否符合預期
# kubectl get secret -n kube-system |grep tunan-sa # kubectl get secret tunan-sa-token-hn97d -o jsonpath={.data.token} -n kube-system | base64 -d
會得到一個很長的token,利用這個token去登入Dashboard
除了名稱空間kube-system中的內容,其他都無法檢視,結果是符合預期的
五、建立一個可以訪問所有namespace的ServiceAccount
新建立一個ServiceAccount,具有操作所有namespace的許可權,這個時候就需要使用到ClusterRole和ClusterRoleBinding這兩種資源物件了。
-
建立新的ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: name: cluster-tunan-sa namespace: kube-system
# kubectl get sa cluster-tunan-sa -n kube-system NAME SECRETS AGE cluster-tunan-sa 1 64s
-
建立一個ClusterRoleBinding物件
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: clusterrolebinding-tunan-sa subjects: - kind: ServiceAccount name: cluster-tunan-sa namespace: kube-system roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
# kubectl create -f cluster-rolebinding-tunan.yaml clusterrolebinding.rbac.authorization.k8s.io/clusterrolebinding-tunan-sa created
# kubectl get clusterrolebinding clusterrolebinding-tunan-sa -n kube-system NAME ROLE AGE clusterrolebinding-tunan-sa ClusterRole/cluster-admin 65s -
獲取token
# kubectl get secret -n kube-system | grep cluster-tunan-sa cluster-tunan-sa-token-zj95w kubernetes.io/service-account-token 3 6m51s
# kubectl get secret cluster-tunan-sa-token-zj95w -o jsonpath={.data.token} -n kube-system | base64 -d登入Dashboard驗證,可以訪問所有的namespace資源