普通程序員看k8s基於角色的訪問控制(RBAC)

1、知識準備

● 上一節描述了k8s的帳戶管理,本文描述基於角色的訪問控制
● 網上RBAC的文章很是多,具體概念大神們也解釋得很詳細,本文沒有站在高屋建瓴的角度去描述RBAC,而是站在一個普通程序員的視角,去看待RBAC
● 我理解的基於角色的訪問控制,如圖:node

+------------+
                          +------------>|all:resource|-+
                          |             +------------+ |       +----------------+
                     +----+---+                        |       |                |
+------+             |role:   |                        +------>+  namespaces    |
|user1 |------------>|admin   |                                |                |
+------+             +--------+         +------------+         |  pod           |
                                  +---->|get:pod     |-------->+                |
                                  |     +------------+         |  service       |
                                  |                            |                |
+------+             +--------+   |                            |  deployment    |
|user2 |------------>|role:   |---+                            |                |
+------+             |guest   |         ....                   |  daemonsets    |
                     +--------+                                |                |
                                                               |  ...           |
                                        +------------+         |                |
                                        |list:service|         +----------------+
                                        +------------+

帳戶:請求kube-api必要的身份驗證。身份驗證以後只是被容許進入集羣,可是不必定有訪問資源的權限
角色:帳戶登陸以後扮演的角色
規則:在k8s集羣內容許的操做。好比get namespace、get pod等
資源:k8s各類各樣的資源
角色綁定:資源與規則組成訪問權限,將角色綁定在訪問權限上,最後帳戶登陸以後扮演不一樣的角色nginx


2、環境準備

組件 版本
OS Ubuntu 18.04.1 LTS
docker 18.06.0-ce
k8s v1.10.1


3、建立角色

角色分爲role與clusterrole,區別在於前者是namespace級別,後者是整個k8s cluster級別程序員

(1)建立role

建立一個default namespace的普通角色,權限是對pod的get、list、watchdocker

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: po_r
  namespace: default
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

(2)建立clusterrole

建立一個具備pod的get、list、watch的clusterrole,這個角色是cluster級別的,也就是全部的namespaceapi

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster_po_r
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

4、userAccount角色綁定

(1)role綁定

先將上一節的mrvolleyball帳號綁定一個namespace級別的role,使用rolebindingui

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mrvolleyball
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: po_r
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: mrvolleyball

再看mrvolleyball的帳戶,已經擁有了對default namespace的get pod權限spa

root@k8s-master:~# kubectl get pod
NAME                                      READY     STATUS    RESTARTS   AGE
busybox                                   1/1       Running   89         3d
nginx-deployment-77d7f55978-lvfkf         1/1       Running   0          21h

不過他既沒有service的訪問權限,更沒有別的namespace的訪問權限3d

root@k8s-master:~# kubectl get svc
Error from server (Forbidden): services is forbidden: User "mrvolleyball" cannot list services in the namespace "default"
root@k8s-master:~# kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "mrvolleyball" cannot list pods in the namespace "kube-system"

(2)clusterrole綁定

綁定clusterrole,讓mrvollerball可以讀取全部namespace的podcode

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: mrvolleyball
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster_po_r
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: mrvolleyball

這時候mrvolleyball也能夠讀取其餘namespace的podserver

root@k8s-master:~# kubectl get pod -n kube-system
NAME                                        READY     STATUS             RESTARTS   AGE
calico-kube-controllers-55c94797d7-vr9k6    1/1       Running            0          15d
calico-node-86xgg                           1/1       Running            0          7d
calico-node-drsl2                           1/1       Running            0          7d
calico-node-l67h4                           1/1       Running            0          7d
coredns-794b5f8589-vgclz                    1/1       Running            4809       15d
coredns-794b5f8589-xzpxd                    1/1       Running            0          130d
default-http-backend-6cb5c56987-tcx92       1/1       Running            0          139d
kubernetes-dashboard-77c46fc984-djdd4       1/1       Running            0          139d
nginx-ingress-controller-6d95468cc8-ft6nn   1/1       Running            0          140d

這裏須要注意幾種資源的綁定:

rolebinding --> role
clusterrolebinding --> clusterrole
rolebinding --> clusterrole

● 第一種是namespace級別的綁定,只對role所在的namespace生效
● 第二種是cluster級別的綁定,對於集羣全部的namespace都生效
● 第三種是namespace級別的綁定,只對role所在的namespace生效

有同窗要問,第一種和第三種有什麼區別:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: mrvolleyball
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster_po_r
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: mrvolleyball

區別主要是爲了方便管理:
● 好比有10個namespace,分配給了10個不一樣的團隊,那每一個團隊都須要使用本身的userAccount操做本身所在的namespace
● 最簡單的作法,就是在10個不一樣namespace建立10個role,而後經過rolebinding將role綁定userAccount。若是須要添加userAccount,那這個管理成本就會升高
● 這時候建立一個clusterrole,因爲他們對各自的namespace的行爲都是同樣的,那就只須要經過rolebinding將clusterrole綁定在userAccount,只須要建立1次clusterrole

5、serviceAccount角色綁定

serviceAccount要提供給pod內訪問,或者是外部服務的訪問。爲了驗證serviceAccount,咱們來模擬pod去訪問api

首先先建立一個serviceAccount

root@k8s-master:/etc/kubernetes/ssl# kubectl create serviceaccount helloworld
serviceaccount "helloworld" created
root@k8s-master:/etc/kubernetes/ssl# kubectl get sa helloworld -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: 2019-03-12T06:36:00Z
  name: helloworld
  namespace: default
  resourceVersion: "24381027"
  selfLink: /api/v1/namespaces/default/serviceaccounts/helloworld
  uid: 1987b4e6-4491-11e9-96bc-525400c34cf1
secrets:
- name: helloworld-token-sr9xb

serviceAccount獲取默認生成一個token,該token是用於pod訪問kube-api的身份驗證(詳情訪問上一篇文章)

root@k8s-master:/etc/kubernetes/ssl# kubectl get secret helloworld-token-sr9xb -o yaml
apiVersion: v1
data:
...
  token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSmtaV1poZFd4MElpd2lhM1ZpWlhKdVpYUmxjeTVwYnk5elpYSjJhV05sWVdOamIzVnVkQzl6WldOeVpYUXVibUZ0WlNJNkltaGxiR3h2ZDI5eWJHUXRkRzlyWlc0dGMzSTVlR0lpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1dVlXMWxJam9pYUdWc2JHOTNiM0pzWkNJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExuVnBaQ0k2SWpFNU9EZGlOR1UyTFRRME9URXRNVEZsT1MwNU5tSmpMVFV5TlRRd01HTXpOR05tTVNJc0luTjFZaUk2SW5ONWMzUmxiVHB6WlhKMmFXTmxZV05qYjNWdWREcGtaV1poZFd4ME9taGxiR3h2ZDI5eWJHUWlmUS5zTTQ3dnBMV25nVmZ1Q2c3RGRfNWlVSGFCa0loeHNvNXY1ZHotRzh3X3ctZUNaS05pZlRyUE9xd3R3QjR4MnZnS3dPaExXX2c0UWxtRDNXS3QyejhlNHVJeFV0cHZkc0lRYkdrYjVrUUdsV1p4cnZwTUZHbTF0eVRsU1lVc3gxa25GdnViWTV0bWU5Y2JkNExOc2RQQ1IxTXBBYnBkYjlqZFh6OWRxMVAyb1Z1LVVuYmVBTkFMcE5tSGJHZjFSdVRPUEJBcUNPNlI3Zm0zUUxpZFZOSDBjRUkwX1Joa0NKR2xPUi1rUlZ5bE5GYXJOVWhvQnJGSEJpTWJyOHd6UHpRNk42Z0hpblctWUc1ekFCY2JNaUR1QUZrRDBCXzBNbDlJandHaDgtbHlrSUZBTU1sbTktUS1hTjJTUjkwSnJyelRYcUtUV3NJU0ZQWHhCTUItX3BXTTlEMEhiZTU4TURCQ1VlSlp0SUcyNno4alBiU0Y1aHRuTy1YSFJRWm1CUzJoaXFLelE2aG9TMkxEa045WUdwcFRETkJUY0dySjg2U0ZQaDlkRWtaYWw0QU9XLWlfTHdEYnY0V2luQjBDOG1Pc3c1WkhDdEVxTVNUTE90aXFyOWZ3bEYzb2lldERqV3FSSXhKeG5rY1NRYTBOTHR4cENiQjFvOGRDTjlqaE1WLVRZMDdidUVNNUpJUGhzeERBMVpqTjNJenVpc3VTVWZMRjd5NkgwZ1JxaGdITzdyMVZvdU5ubGFybjNhSmxMYmF3NUk3RnIwM1ZrQ0pqSmotX0FFRmpSWGlNVmRtenM0el9nWVRfUGR0TXR4YnFfd1p5ZXJHWXpuUk9NQ3p0b2gtRlRCWktOT2dfZjBmTEN3c29rd2NJaEtWWFh2YXMtcjN0YXFBcXZEbWtOOA==
kind: Secret
metadata:
  annotations:
    kubernetes.io/service-account.name: helloworld
    kubernetes.io/service-account.uid: 1987b4e6-4491-11e9-96bc-525400c34cf1
  creationTimestamp: 2019-03-12T06:36:00Z
  name: helloworld-token-sr9xb
  namespace: default
  resourceVersion: "24381026"
  selfLink: /api/v1/namespaces/default/secrets/helloworld-token-sr9xb
  uid: 198c824f-4491-11e9-96bc-525400c34cf1
type: kubernetes.io/service-account-token

拿到該token,將其轉碼以後做爲鏈接kube-api的身份驗證

root@k8s-master:/etc/kubernetes/ssl# token=`kubectl get secret helloworld-token-sr9xb -o yaml | grep "token:" | awk '{print $2}' | base64 -d`
root@k8s-master:/etc/kubernetes/ssl# kubectl config set-credentials helloworld --token=$token
User "helloworld" set.

配置rolebinding,po_r這個role只能對default namespace的pod有讀權限

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: helloworld-role-binding
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: po_r
subjects:
- kind: ServiceAccount
  name: helloworld
  namespace: default

嘗試訪問一下:

root@k8s-master:~# kubectl config use-context context@helloworld
Switched to context "context@helloworld".
root@k8s-master:~# kubectl get pod
NAME                                      READY     STATUS    RESTARTS   AGE
busybox                                   1/1       Running   187        7d

該serviceAccount也只有default namespace的訪問權限

root@k8s-master:~# kubectl get pod -n kube-system
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:helloworld" cannot list pods in the namespace "kube-system"

6、小結

● 本文介紹了k8s基於權限的訪問,詳細k8s當中role、clusterrole與rolebinding、clusterrolebinding
● 而且模擬了不一樣類型的帳戶訪問kube-api時不一樣的認證方式



至此,本文結束 在下才疏學淺,有撒湯漏水的,請各位不吝賜教...

相關文章
相關標籤/搜索