Kubernetes RBAC 詳解

原文鏈接:Kubernetes RBAC 詳解
前面兩節(jié)課我們學(xué)習(xí)了Kubernetes中的兩個(gè)用于配置信息的重要資源對(duì)象:ConfigMapSecret,其實(shí)到這里我們基本上學(xué)習(xí)的內(nèi)容已經(jīng)覆蓋到Kubernetes中一些重要的資源對(duì)象了,來(lái)部署一個(gè)應(yīng)用程序是完全沒(méi)有問(wèn)題的了。在我們演示一個(gè)完整的示例之前,我們還需要給大家講解一個(gè)重要的概念:RBAC - 基于角色的訪問(wèn)控制。

RBAC使用rbac.authorization.k8s.io API Group 來(lái)實(shí)現(xiàn)授權(quán)決策,允許管理員通過(guò) Kubernetes API 動(dòng)態(tài)配置策略,要啟用RBAC,需要在 apiserver 中添加參數(shù)--authorization-mode=RBAC,如果使用的kubeadm安裝的集群,1.6 版本以上的都默認(rèn)開(kāi)啟了RBAC,可以通過(guò)查看 Master 節(jié)點(diǎn)上 apiserver 的靜態(tài)Pod定義文件:

$ cat /etc/kubernetes/manifests/kube-apiserver.yaml
...
    - --authorization-mode=Node,RBAC
...

如果是二進(jìn)制的方式搭建的集群,添加這個(gè)參數(shù)過(guò)后,記得要重啟 apiserver 服務(wù)。

RBAC API 對(duì)象

Kubernetes有一個(gè)很基本的特性就是它的所有資源對(duì)象都是模型化的 API 對(duì)象,允許執(zhí)行 CRUD(Create、Read、Update、Delete)操作(也就是我們常說(shuō)的增、刪、改、查操作),比如下面的這下資源:

  • Pods
  • ConfigMaps
  • Deployments
  • Nodes
  • Secrets
  • Namespaces

上面這些資源對(duì)象的可能存在的操作有:

  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec

在更上層,這些資源和 API Group 進(jìn)行關(guān)聯(lián),比如Pods屬于 Core API Group,而Deployements屬于 apps API Group,要在Kubernetes中進(jìn)行RBAC的管理,除了上面的這些資源和操作以外,我們還需要另外的一些對(duì)象:

  • Rule:規(guī)則,規(guī)則是一組屬于不同 API Group 資源上的一組操作的集合

  • Role 和 ClusterRole:角色和集群角色,這兩個(gè)對(duì)象都包含上面的 Rules 元素,二者的區(qū)別在于,在 Role 中,定義的規(guī)則只適用于單個(gè)命名空間,也就是和 namespace 關(guān)聯(lián)的,而 ClusterRole 是集群范圍內(nèi)的,因此定義的規(guī)則不受命名空間的約束。另外 Role 和 ClusterRole 在Kubernetes中都被定義為集群內(nèi)部的 API 資源,和我們前面學(xué)習(xí)過(guò)的 Pod、ConfigMap 這些類似,都是我們集群的資源對(duì)象,所以同樣的可以使用我們前面的kubectl相關(guān)的命令來(lái)進(jìn)行操作

  • Subject:主題,對(duì)應(yīng)在集群中嘗試操作的對(duì)象,集群中定義了3種類型的主題資源:

    • User Account:用戶,這是有外部獨(dú)立服務(wù)進(jìn)行管理的,管理員進(jìn)行私鑰的分配,用戶可以使用 KeyStone或者 Goolge 帳號(hào),甚至一個(gè)用戶名和密碼的文件列表也可以。對(duì)于用戶的管理集群內(nèi)部沒(méi)有一個(gè)關(guān)聯(lián)的資源對(duì)象,所以用戶不能通過(guò)集群內(nèi)部的 API 來(lái)進(jìn)行管理
    • Group:組,這是用來(lái)關(guān)聯(lián)多個(gè)賬戶的,集群中有一些默認(rèn)創(chuàng)建的組,比如cluster-admin
    • Service Account:服務(wù)帳號(hào),通過(guò)Kubernetes API 來(lái)管理的一些用戶帳號(hào),和 namespace 進(jìn)行關(guān)聯(lián)的,適用于集群內(nèi)部運(yùn)行的應(yīng)用程序,需要通過(guò) API 來(lái)完成權(quán)限認(rèn)證,所以在集群內(nèi)部進(jìn)行權(quán)限操作,我們都需要使用到 ServiceAccount,這也是我們這節(jié)課的重點(diǎn)
  • RoleBinding 和 ClusterRoleBinding:角色綁定和集群角色綁定,簡(jiǎn)單來(lái)說(shuō)就是把聲明的 Subject 和我們的 Role 進(jìn)行綁定的過(guò)程(給某個(gè)用戶綁定上操作的權(quán)限),二者的區(qū)別也是作用范圍的區(qū)別:RoleBinding 只會(huì)影響到當(dāng)前 namespace 下面的資源操作權(quán)限,而 ClusterRoleBinding 會(huì)影響到所有的 namespace。

接下來(lái)我們來(lái)通過(guò)幾個(gè)示例來(lái)演示下RBAC的配置方法。

創(chuàng)建一個(gè)只能訪問(wèn)某個(gè) namespace 的用戶

我們來(lái)創(chuàng)建一個(gè) User Account,只能訪問(wèn) kube-system 這個(gè)命名空間:

  • username: haimaxy
  • group: youdianzhishi

第1步:創(chuàng)建用戶憑證

我們前面已經(jīng)提到過(guò),Kubernetes沒(méi)有 User Account 的 API 對(duì)象,不過(guò)要?jiǎng)?chuàng)建一個(gè)用戶帳號(hào)的話也是挺簡(jiǎn)單的,利用管理員分配給你的一個(gè)私鑰就可以創(chuàng)建了,這個(gè)我們可以參考官方文檔中的方法,這里我們來(lái)使用OpenSSL證書來(lái)創(chuàng)建一個(gè) User,當(dāng)然我們也可以使用更簡(jiǎn)單的cfssl工具來(lái)創(chuàng)建:

  • 給用戶 haimaxy 創(chuàng)建一個(gè)私鑰,命名成:haimaxy.key:
$ openssl genrsa -out haimaxy.key 2048
  • 使用我們剛剛創(chuàng)建的私鑰創(chuàng)建一個(gè)證書簽名請(qǐng)求文件:haimaxy.csr,要注意需要確保在-subj參數(shù)中指定用戶名和組(CN表示用戶名,O表示組):
$ openssl req -new -key haimaxy.key -out haimaxy.csr -subj "/CN=haimaxy/O=youdianzhis"
  • 然后找到我們的Kubernetes集群的CA,我們使用的是kubeadm安裝的集群,CA相關(guān)證書位于/etc/kubernetes/pki/目錄下面,如果你是二進(jìn)制方式搭建的,你應(yīng)該在最開(kāi)始搭建集群的時(shí)候就已經(jīng)指定好了CA的目錄,我們會(huì)利用該目錄下面的ca.crtca.key兩個(gè)文件來(lái)批準(zhǔn)上面的證書請(qǐng)求

  • 生成最終的證書文件,我們這里設(shè)置證書的有效期為500天:

$ openssl x509 -req -in haimaxy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out haimaxy.crt -days 500

現(xiàn)在查看我們當(dāng)前文件夾下面是否生成了一個(gè)證書文件:

$ ls
haimaxy.csr haimaxy.key haimaxy.crt
  • 現(xiàn)在我們可以使用剛剛創(chuàng)建的證書文件和私鑰文件在集群中創(chuàng)建新的憑證和上下文(Context):
$ kubectl config set-credentials haimaxy --client-certificate=haimaxy.crt  --client-key=haimaxy.key

我們可以看到一個(gè)用戶haimaxy創(chuàng)建了,然后為這個(gè)用戶設(shè)置新的 Context:

$ kubectl config set-context haimaxy-context --cluster=kubernetes --namespace=kube-system --user=haimaxy

到這里,我們的用戶haimaxy就已經(jīng)創(chuàng)建成功了,現(xiàn)在我們使用當(dāng)前的這個(gè)配置文件來(lái)操作kubectl命令的時(shí)候,應(yīng)該會(huì)出現(xiàn)錯(cuò)誤,因?yàn)槲覀冞€沒(méi)有為該用戶定義任何操作的權(quán)限呢:

$ kubectl get pods --context=haimaxy-context
Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"

第2步:創(chuàng)建角色

用戶創(chuàng)建完成后,接下來(lái)就需要給該用戶添加操作權(quán)限,我們來(lái)定義一個(gè)YAML文件,創(chuàng)建一個(gè)允許用戶操作 Deployment、Pod、ReplicaSets 的角色,如下定義:(haimaxy-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: haimaxy-role
  namespace: kube-system
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # 也可以使用['*']

其中Pod屬于 core 這個(gè) API Group,在YAML中用空字符就可以,而Deployment屬于 apps 這個(gè) API Group,ReplicaSets屬于extensions這個(gè) API Group(我怎么知道的?點(diǎn)這里查文檔),所以 rules 下面的 apiGroups 就綜合了這幾個(gè)資源的 API Group:["", "extensions", "apps"],其中verbs就是我們上面提到的可以對(duì)這些資源對(duì)象執(zhí)行的操作,我們這里需要所有的操作方法,所以我們也可以使用['*']來(lái)代替。

然后創(chuàng)建這個(gè)Role

$ kubectl create -f haimaxy-role.yaml

注意這里我們沒(méi)有使用上面的haimaxy-context這個(gè)上下文了,因?yàn)槟居袡?quán)限啦

第3步:創(chuàng)建角色權(quán)限綁定

Role 創(chuàng)建完成了,但是很明顯現(xiàn)在我們這個(gè) Role 和我們的用戶 haimaxy 還沒(méi)有任何關(guān)系,對(duì)吧?這里我就需要?jiǎng)?chuàng)建一個(gè)RoleBinding對(duì)象,在 kube-system 這個(gè)命名空間下面將上面的 haimaxy-role 角色和用戶 haimaxy 進(jìn)行綁定:(haimaxy-rolebinding.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: haimaxy-rolebinding
  namespace: kube-system
subjects:
- kind: User
  name: haimaxy
  apiGroup: ""
roleRef:
  kind: Role
  name: haimaxy-role
  apiGroup: ""

上面的YAML文件中我們看到了subjects關(guān)鍵字,這里就是我們上面提到的用來(lái)嘗試操作集群的對(duì)象,這里對(duì)應(yīng)上面的 User 帳號(hào) haimaxy,使用kubectl創(chuàng)建上面的資源對(duì)象:

$ kubectl create -f haimaxy-rolebinding.yaml

第4步. 測(cè)試

現(xiàn)在我們應(yīng)該可以上面的haimaxy-context上下文來(lái)操作集群了:

$ kubectl get pods --context=haimaxy-context
....

我們可以看到我們使用kubectl的使用并沒(méi)有指定 namespace 了,這是因?yàn)槲覀円呀?jīng)為該用戶分配了權(quán)限了,如果我們?cè)诤竺婕由弦粋€(gè)-n default試看看呢?

$ kubectl --context=haimaxy-context get pods --namespace=default
Error from server (Forbidden): pods is forbidden: User "haimaxy" cannot list pods in the namespace "default"

是符合我們預(yù)期的吧?因?yàn)樵撚脩舨](méi)有 default 這個(gè)命名空間的操作權(quán)限

創(chuàng)建一個(gè)只能訪問(wèn)某個(gè) namespace 的ServiceAccount

上面我們創(chuàng)建了一個(gè)只能訪問(wèn)某個(gè)命名空間下面的普通用戶,我們前面也提到過(guò) subjects 下面還有一直類型的主題資源:ServiceAccount,現(xiàn)在我們來(lái)創(chuàng)建一個(gè)集群內(nèi)部的用戶只能操作 kube-system 這個(gè)命名空間下面的 pods 和 deployments,首先來(lái)創(chuàng)建一個(gè) ServiceAccount 對(duì)象:

$ kubectl create sa haimaxy-sa -n kube-system

當(dāng)然我們也可以定義成YAML文件的形式來(lái)創(chuàng)建。

然后新建一個(gè) Role 對(duì)象:(haimaxy-sa-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: haimaxy-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"]

可以看到我們這里定義的角色沒(méi)有創(chuàng)建、刪除、更新 Pod 的權(quán)限,待會(huì)我們可以重點(diǎn)測(cè)試一下,創(chuàng)建該 Role 對(duì)象:

$ kubectl create -f haimaxy-sa-role.yaml

然后創(chuàng)建一個(gè) RoleBinding 對(duì)象,將上面的 haimaxy-sa 和角色 haimaxy-sa-role 進(jìn)行綁定:(haimaxy-sa-rolebinding.yaml)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: haimaxy-sa-rolebinding
  namespace: kube-system
subjects:
- kind: ServiceAccount
  name: haimaxy-sa
  namespace: kube-system
roleRef:
  kind: Role
  name: haimaxy-sa-role
  apiGroup: rbac.authorization.k8s.io

添加這個(gè)資源對(duì)象:

$ kubectl create -f haimaxy-sa-rolebinding.yaml

然后我們?cè)趺慈ヲ?yàn)證這個(gè) ServiceAccount 呢?我們前面的課程中是不是提到過(guò)一個(gè) ServiceAccount 會(huì)生成一個(gè) Secret 對(duì)象和它進(jìn)行映射,這個(gè) Secret 里面包含一個(gè) token,我們可以利用這個(gè) token 去登錄 Dashboard,然后我們就可以在 Dashboard 中來(lái)驗(yàn)證我們的功能是否符合預(yù)期了:

$ kubectl get secret -n kube-system |grep haimay-sa
haimay-sa-token-nxgqx                  kubernetes.io/service-account-token   3         47m
$ kubectl get secret haimay-sa-token-nxgqx -o jsonpath={.data.token} -n kube-system |base64 -d
# 會(huì)生成一串很長(zhǎng)的base64后的字符串

使用這里的 token 去 Dashboard 頁(yè)面進(jìn)行登錄:


Dashboard

我們可以看到上面的提示信息,這是因?yàn)槲覀兊卿涍M(jìn)來(lái)后默認(rèn)跳轉(zhuǎn)到 default 命名空間,我們切換到 kube-system 命名空間下面就可以了:


Dashboard

我們可以看到可以訪問(wèn)pod列表了,但是也會(huì)有一些其他額外的提示:events is forbidden: User “system:serviceaccount:kube-system:haimaxy-sa” cannot list events in the namespace “kube-system”,這是因?yàn)楫?dāng)前登錄用只被授權(quán)了訪問(wèn) pod 和 deployment 的權(quán)限,同樣的,訪問(wèn)下deployment看看可以了嗎?

同樣的,你可以根據(jù)自己的需求來(lái)對(duì)訪問(wèn)用戶的權(quán)限進(jìn)行限制,可以自己通過(guò) Role 定義更加細(xì)粒度的權(quán)限,也可以使用系統(tǒng)內(nèi)置的一些權(quán)限……

創(chuàng)建一個(gè)可以訪問(wèn)所有 namespace 的ServiceAccount

剛剛我們創(chuàng)建的haimaxy-sa這個(gè) ServiceAccount 和一個(gè) Role 角色進(jìn)行綁定的,如果我們現(xiàn)在創(chuàng)建一個(gè)新的 ServiceAccount,需要他操作的權(quán)限作用于所有的 namespace,這個(gè)時(shí)候我們就需要使用到 ClusterRole 和 ClusterRoleBinding 這兩種資源對(duì)象了。同樣,首先新建一個(gè) ServiceAcount 對(duì)象:(haimaxy-sa2.yaml)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: haimaxy-sa2
  namespace: kube-system

創(chuàng)建:

$ kubectl create -f haimaxy-sa2.yaml

然后創(chuàng)建一個(gè) ClusterRoleBinding 對(duì)象(haimaxy-clusterolebinding.yaml):

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: haimaxy-sa2-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: haimaxy-sa2
  namespace: kube-system
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

從上面我們可以看到我們沒(méi)有為這個(gè)資源對(duì)象聲明 namespace,因?yàn)檫@是一個(gè) ClusterRoleBinding 資源對(duì)象,是作用于整個(gè)集群的,我們也沒(méi)有單獨(dú)新建一個(gè) ClusterRole 對(duì)象,而是使用的 cluster-admin 這個(gè)對(duì)象,這是Kubernetes集群內(nèi)置的 ClusterRole 對(duì)象,我們可以使用kubectl get clusterrolekubectl get clusterrolebinding查看系統(tǒng)內(nèi)置的一些集群角色和集群角色綁定,這里我們使用的 cluster-admin 這個(gè)集群角色是擁有最高權(quán)限的集群角色,所以一般需要謹(jǐn)慎使用該集群角色。

創(chuàng)建上面集群角色綁定資源對(duì)象,創(chuàng)建完成后同樣使用 ServiceAccount 對(duì)應(yīng)的 token 去登錄 Dashboard 驗(yàn)證下:

$ kubectl create -f haimaxy-clusterolebinding.yaml
$ kubectl get secret -n kube-system |grep haimay-sa2
haimay-sa2-token-nxgqx                  kubernetes.io/service-account-token   3         47m
$ kubectl get secret haimay-sa2-token-nxgqx -o jsonpath={.data.token} -n kube-system |base64 -d
# 會(huì)生成一串很長(zhǎng)的base64后的字符串

我們?cè)谧铋_(kāi)始接觸到RBAC認(rèn)證的時(shí)候,可能不太熟悉,特別是不知道應(yīng)該怎么去編寫rules規(guī)則,大家可以去分析系統(tǒng)自帶的 clusterrole、clusterrolebinding 這些資源對(duì)象的編寫方法,怎么分析?還是利用 kubectl 的 get、describe、 -o yaml 這些操作,所以kubectl最基本的用戶一定要掌握好。

RBAC只是Kubernetes中安全認(rèn)證的一種方式,當(dāng)然也是現(xiàn)在最重要的一種方式,后面我們?cè)俸痛蠹乙黄鹆囊涣?code>Kubernetes中安全設(shè)計(jì)。

本文節(jié)選自視頻教程從 Docker 到 Kubernetes 進(jìn)階

掃描下面的二維碼(或微信搜索k8s技術(shù)圈)關(guān)注我們的微信公眾帳號(hào),在微信公眾帳號(hào)中回復(fù) 加群 即可加入到我們的 kubernetes 討論群里面共同學(xué)習(xí)。

qrcode

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容