1. 程式人生 > 實用技巧 >Kubernetes RBAC

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

屬於Core API Group,而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的角色

  1. 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就是對這些資源物件執行的操作

  2. 建立這個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進行繫結

  1. 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

  2. 檢視

    # 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  
  3. 驗證

    # 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

  1. sa.yaml

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: tunan-sa
      namespace: kube-system

  2. 建立sa

    # kubectl create -f sa.yaml
    ​
    # kubectl get sa tunan-sa -n kube-system
    NAME       SECRETS   AGE
    tunan-sa   1         19s

  3. 建立一個新的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]

  4. 建立一個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

  5. 驗證

    每個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這兩種資源物件了。

  1. 建立新的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

  2. 建立一個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

  3. 獲取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資源