1. 程式人生 > >【Kubernetes】基於角色的許可權控制:RBAC

【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