API Server的身份认证、授权、准入控制

之前我们使用的是kubectl反向代理,通过使kubectl反向代理API Server,可以直接使用kubectl命令的认证授权来访问API Server。然而,当在实际工作中使用API Server时,根本不会在Master节点上直接访问API Server,而对于不同的角色,也将设定合适的权限,根本不会有完整权限。

API Server的实际使用比之前的示例复杂很多,要经过三大关卡才能够访问合适的资源。由于API Server是访问和管理资源对象的唯 一入口,因此每一次的访问请求都需要进行合法性检验,需要在一系列验证通过之后才能访问或者存储数据到etcd当中。

访问API Server需要经过身份认证、授权及准入控制这三大关卡,如下图所示。只有这三大关卡都能通过,才可以访问Kubernetes集群中的资源。

访问API Server的三大关卡

../../_images/image-20220420145604803.png

身份认证主要用于确定用户能不能访问,授权则决定用户能够访问哪些资源,而准入控制决定用户访问这些资源时需要基于什么规范 或准则。

1. 身份认证

要访问API Server,首先需要经过的第一个关卡就是身份认证。之前我们在使用 kubectl反向代理或者直接使用kubectl命令时,其实也经历了身份认证。kubectl命令的认证是使用~/.kube/config文件进行的。通过$ kubectl config view命令,可以查看它的认证情况

$ kubectl config view
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: DATA+OMITTED
    server: https://192.168.1.161:6443
  name: kubernetes
contexts:
- context:
    cluster: kubernetes
    user: kubernetes-admin
  name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED

在安装完成后,Kubernetes会在Master节点上开启6443端口,这就是API Server的访问入口

在本例中,API Server的地址为https://192.168.1.161:6443,如果没有经过认证,将无法访问API Server。我们可以先试试没有认证时的访问效果。执行以下命令查询Pod。

命令执行后,会发现无法正常查询

$ curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {

  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:anonymous\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
  "code": 403

要访问API Server,要先进行身份认证。Kubernetes中的身份认证主要分为以下两类。

  • 常规用户认证:主要供普通用户或独立于Kubernetes之外的其他外部应用使用,以便能从外部访问API Server。

  • ServiceAccount认证:主要供集群内部的Pod使用,用来给Pod中的进程提供访问API Server的身份标识,以便Pod可以从内部调用 API Server。

1.1 常规用户认证

常规用户认证主要供普通用户或独立于Kubernetes之外的其他外部应用来使用,它主要有3种认证方式。

  • HTTPS证书认证:基于CA证书签名的数字证书认证。

  • HTTP令牌认证:通过令牌来识别用户。

  • HTTP Base认证:通过用户名和密码认证。

从使用角度来说,HTTP令牌认证是最实用也最易普及的方式,本节主要介绍这种方式。

首先,使用以下命令生成一个随机的令牌。

$ head -c 16 /dev/urandom | od -An -t x | tr -d ' '
937eadfa60efc23102f636f881d3d99e

拿到令牌后,就可以给Kubernetes创建令牌认证文件,命令如下。

$ vim /etc/Kubernetes/pki/token_auth_file

认证文件中可填入多行认证信息,一行对应一个用户,每行都须具备令牌、用户名、用户ID这3个字段。例如,可填入以下信息。

Token1,username1,1
Token2,username2,2
......

本例中使用刚才生成好的令牌来创建一个名为 exampleuser 的用户。这只需要在/etc/Kubernetes/pki/token_auth_file文件中填入以下内容然后保存文件即可。

937eadfa60efc23102f636f881d3d99e,exampleuser,1

现在认证文件已成功创建,只需要在API Server的启动参数中加入对该文件的引用。要修改启动参数,应编辑/etc/kubernetes/manifests/kube-apiserver.yaml文件,然后在spec属性部分加入- –token-auth- file=/etc/Kubernetes/pki/token_auth_file参数,如以下代码所示。

apiVersion: v1
...
spec:
  containers:
  - command:
    - kube-apiserver
    ...
    - --tls-cert-file=/etc/Kubernetes/pki/apiserver.crt
    - --tls-private-key-file=/etc/Kubernetes/pki/apiserver.key
    - --token-auth-file=/etc/Kubernetes/pki/token_auth_file

之后,API Server就会引用刚才创建的令牌认证文件。如果要以exampleuser身份访问API Server,只需要在请求中带上 一个Header即可,其格式为Authorization: Bearer {Token值},在本例中为Authorization:Bearer937eadfa60efc23102f636f881d3d99e。

此时带上令牌,以exampleuser身份调用API Server,获取Pod信息,命令如下。

$ curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods -H \
"Authorization:Bearer 937eadfa60efc23102f636f881d3d99e"

Kubernetes已经识别出exampleuser正在进行访问,但因为只通过了认证,还没有授权,所以访问仍会失败。认证已经完成。

1.2 ServiceAccount认证

ServiceAccount认证主要供集群内部Pod中的进程使用,以便Pod可以从内部调用API Server。

常规用户认证是不限制命名空间(namespace)的,但ServiceAccount认证的局限于它所在的命名空间中。

默认ServiceAccount

每个命名空间都有一个默认的ServiceAccount,如果在创建Pod时没有明确指定用哪个ServiceAccount,就会用默认的 ServiceAccount。

可以通过$ kubectl get serviceaccount命令查看当前已有的ServiceAccount

$ kubectl get serviceaccount
NAME      SECRETS   AGE
default   1         176d

可以看到在当前命名空间下,拥有一个名为default的ServiceAccount。

此时再通过$kubectl describe serviceaccount default命令查看其详情,

可以看到它关联了一个名为default-token-znfnr的Secret,里面存放了ServiceAccount的认证信息,通过这些认证信息可以访问APIServer。

# ServiceAccount查询结果
$ kubectl describe serviceaccount default
Name:                default
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   default-token-znfnr
Tokens:              default-token-znfnr
Events:              <none>

$ kubectl get secrets
NAME                  TYPE                                  DATA   AGE
default-token-znfnr   kubernetes.io/service-account-token   3      176d

接下来,创建一个示例Pod,用它来进行讲解,其定义如下所示。

apiVersion: v1
kind: Pod
metadata:
  name: examplepodforheadlessservice
spec:
  containers:
  - name: testcontainer
    image: docker.io/appropriate/curl
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c']
    args: ['echo "test pod for headless service!"; sleep 3600']

这个Pod的镜像为appropriate/curl。它是一种工具箱,里面存放了一些用于测试网络的工具,例如,curl命令正好可用于测试 API Server的访问。调用sleep 3600命令让该容器长期处于运行状态。

此时执行$ kubectl get pod examplepodforheadlessservice -o yaml命令查看Pod定义的 详情(或使用$ kubectl describe pod examplepodforheadlessservice命令查看Pod详情),

可以发现Pod中引用了一个Secret类型的存储卷,这个存储卷我们并没有在模板中定义,而是由Kubernetes自动附加的

../../_images/image-20220420214329999.png ../../_images/image-20220420214438456.png

Kubernetes在这个命名空间下以默认形式自动创建了一个ServiceAccount,而在default-token-znfnr里面存放了ServiceAccount的认证信息。

使用这些认证信息,就可以访问APIServer。

$ kubectl describe pod examplepodforheadlessservice
Name:         examplepodforheadlessservice
Namespace:    default
Priority:     0
Node:         gitee-k8s-w02/192.168.1.36
Start Time:   Wed, 20 Apr 2022 21:36:28 +0800
Labels:       <none>
Annotations:  <none>
......
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-sl2w8 (ro)

执行$ kubectl get secret default-token-znfnr -o yaml命令

(或$ kubectl describe secret default-token-znfnr命令),查看Secret定义的详情,

可以发现它主要存放了3个信息——ca.crt(证书)、namespace、token。

../../_images/image-20220420215311073.png ../../_images/image-20220420215601123.png

由于该Secret是以存储卷形式挂载到Pod容器当中的,因此可以使用映射路径获得证书和令牌,并用它们来访问API Server,例如,可 以使用以下路径。

/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
/var/run/secrets/kubernetes.io/serviceaccount/token

接下来,通过以下命令进入Pod内部,以便在Pod内部执行命令行。

$ kubectl exec -it pod/examplepodforheadlessservice -- /bin/s

现在可以使用ServiceAccount的令牌来访问API Server,只需要执行以下命令。

$ curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods -H \
"Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

在本例中,我们通过cat /var/run/secrets/Kubernetes.io/serviceaccount/ token输出了存放在映射路径下的令牌。命令执行后,结果如下图 所示,Kubernetes已经通过认证,识别到名为default的ServiceAccount正在进行访问,由于还未授权,因此访问会失败。

../../_images/image-20220420221321670.png

自定义ServiceAccount

一般情况下,我们并不会更改默认ServiceAccount的授权。如果某些Pod需要访问API Server,通常会让它引用自定义ServiceAccount,并设置其授权。

ServiceAccount的定义非常简单。首先,通过以下命令创建一个名为exampleserviceaccount的自定义ServiceAccount。

exampleserviceaccount.yml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: exampleserviceaccount

运行以下命令,通过模板创建ServiceAccount。

$ kubectl apply -f exampleserviceaccount.yml

此时再执行以下命令,查询当前命名空间下的ServiceAccount。

可以看到刚才创建的ServiceAccount。

$ kubectl get serviceaccount
NAME                    SECRETS   AGE
default                 1         176d
exampleserviceaccount   1         2m3s

另外,还可以通过命令查看ServiceAccount的详细信息。

$ kubectl describe serviceaccounts exampleserviceaccount
Name:                exampleserviceaccount
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   exampleserviceaccount-token-t4265
Tokens:              exampleserviceaccount-token-t4265
Events:              <none>

Kubernetes在创建ServiceAccount时自动为其生成了一个Secret(在本例中为exampleserviceaccount-token-t4265)。

和之前默认ServiceAccount的Secret一样,里面存放了与该ServiceAccount相关的证书和令牌等认证信息。

此时再创建一个Pod,将它的spec.serviceAccountName属性设置为刚才创建的自定义ServiceAccount。

首先,通过以下命令,创建模板文件。

examplepodforserviceaccount.yml

apiVersion: v1
kind: Pod
metadata:
  name: examplepodforserviceaccount
spec:
  serviceAccountName: exampleserviceaccount
  containers:
  - name: testcontainer
    image: docker.io/appropriate/curl
    imagePullPolicy: IfNotPresent
    command: ['sh', '-c']
    args: ['echo "test pod for headless service!"; sleep 3600']

在这个 Pod 的定义中,引用了先前创建的名为exampleserviceaccount 的自定义ServiceAccount。

接下来,运行以下命令,通过模板创建Pod。

$ kubectl apply -f examplepodforserviceaccount.yml

Pod创建后再执行$ kubectl get pod examplepodforserviceaccount -o yaml

命令查看Pod定义的详情(或用$ kubectl describe pod examplepodforserviceaccount命令查看Pod详情),

可以发现Pod中使用了自定义ServiceAccount的Secret,并将其配置为存储卷。

../../_images/image-20220421092530850.png

可以看到cm配置文件已经挂载到容器中了。

../../_images/image-20220421092718760.png

与默认的ServiceAccount一样,我们依然可以进入Pod内部,然后使用ServiceAccount的令牌来访问API Server。

$ curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods -H \
"Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

Kubernetes会识别到examplepodforserviceaccount这个自定义ServiceAccount正在发起请求,但因为我们只设置了认证还没进行授权,所以访问会失败,下一节将基于该示例演示如何授权。

2. RBAC授权

Kubernetes中有基于属性的访问控制(Attribute Based AccessControl,ABAC)、

基于角色的访问控制(Role Based AccessControl,RBAC)、

基于HTTP回调机制的访问控制(Webhook)、

Node认证等授权模式,但从1.6版本开始,Kubernetes默认启用的是RBAC授权模式。本节将主要讲述RBAC授权模式。

RBAC授权主要分为两个步骤。

(1)角色定义:指定角色名称,定义允许访问哪些资源及允许的访问方式。

(2)角色绑定:将角色与用户(常规用户或ServiceAccount)进行绑定,这样用户就拥有与角色对应的权限。

RBAC授权的原理如图

../../_images/image-20220421093626151.png

角色定义和角色绑定分为两种。

  • 只拥有单一指定命名空间访问权限的角色:角色定义关键字为Role,角色绑定关键字为RoleBinding。

  • 拥有集群级别(不限命名空间)访问权限的角色:角色定义关键字为ClusterRole,角色绑定关键字为ClusterRoleBinding。

2.1 普通角色的定义与绑定

普通角色定义

首先,定义一个普通角色,创建一个名为podreader.yml的模板文件。命令如下。

podreader.yml

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

这里介绍一下文件中的主要属性。

  • kind表示模板的类型,这里使用Role关键字以表示普通角色。

  • apiVersion表示使用的API版本,有关RBAC授权的API版本为rbac. authorization.k8s.io/v1。

  • metadata中指定角色的名称为podreader。namespace属性为default,这个属性可以不用填写,默认为default。

  • rules表示角色的规则定义。apiGroups表示可对哪些API组的资源进行操作。这里设置为空字符串,表示没有限制条件。 resources表示可以访问的资源列表,这里设置为pods。verbs表示可以对资源进行哪几种访问方式。这里设置为 get、watch和list,分别表示可以查询单条资源、监控资源并查询列表资源。

运行以下命令,通过模板创建普通角色。

$ kubectl apply -f podreader.yml

通角色创建成功后,可以通过$ kubectl get role命令查看。另外,还可以通过$ kubectl describe role podreader 命令查看普通角色podreader的详情

$ kubectl get role
NAME        CREATED AT
podreader   2022-04-21T01:39:18Z

# 可以清晰地看到资源类型以及允许的访问方式。
$ kubectl describe role podreader
Name:         podreader
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [get watch list]

提示:要了解角色定义模板中支持的resources和verbs属性,可以通过以下方式来查询。

在Master节点上打开kubectl反向代理,本例中的命令为kubectl proxy –port=8080,然后访问 http://localhost:8080/{APIVersion}来查看资源列表,其中name属性表示支持的资源名称,verbs属性表示支持的操作。

例如,要查看Pod中有resources属性的类别以及支持的verbs属性,

可以执行命令$ curl http://localhost:8080/api/v1,然后在返回结果中找到与Pod相关的信息。

../../_images/image-20220421094957631.png

如果要查看Daemonsets控制器中resources属性的类别以及支持的verbs属性,

可以执行命令$ curl http://localhost:8080/apis/apps/v1

然后在返回结果中找到与Daemonsets控制器相关的信息。

与Daemonsets控制器相关的resources及verbs属性

../../_images/image-20220421095116198.png

普通角色绑定

定义角色后就可以绑定角色了。绑定可以针对常规用户认证,也可以针对ServiceAccount认证。

在之前的示例中,我们创建过基于常规用户认证的用户,其名称为exampleuser,

还设置过一个自定义ServiceAccount,其名称为exampleserviceaccount(另一个名为 examplepodforserviceaccount的Pod引用了这个自定义ServiceAccount)。为了同时为它们进行角色绑定,首先,创建模板文件,命令如下。

podreaderbinding.yml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: podreaderbinding
  namespace: default
subjects:
  - kind: User
    name: exampleuser
    apiGroup: ""
  - kind: ServiceAccount
    name: exampleserviceaccount
    apiGroup: ""
roleRef:
  kind: Role
  name: podreader
  apiGroup: ""

这里介绍一下它的主要属性。

  • kind表示模板的类型,这里使用RoleBinding关键字以表示普通角色绑定。

  • apiVersion 表示使用的 API 版本,有关 RBAC 授权的 API 版本为 rbac. authorization.k8s.io/v1。

  • metadata中定义角色的名称为podreaderbinding。namespace属性为default,这个属性可以不用填写,默认为default。

  • subjects表示将角色绑定给哪些认证主体,它是一个数组。 第一个认证主体是之前创建的常规用户认证示例,这里设置其kind为User,名称为之前设置的exampleuser,apiGroup为默认值表示没有限制。 第二个认证主体是之前创建的 ServiceAccount 认证示例,这里设置其 kind 为ServiceAccount,名称为之前设定的exampleserviceaccount。 roleRef表示要绑定的角色,这里的kind设置为Role以表示普通角色,名称为之前定义的podreader。

运行以下命令,通过模板创建普通角色绑定。

$ kubectl apply -f podreaderbinding.yml

普通角色绑定创建成功后,可以通kubectl get rolebinding命令查看它。

另外,还可以通过$ kubectl describe rolebinding podreaderbinding命令查看普通角色 绑定podreaderbinding的详情。如下所示,可以清晰地看到所绑定的认证主体,以及用于绑定的角色。

$ kubectl get rolebinding
NAME               ROLE             AGE
podreaderbinding   Role/podreader   <invalid>

$ kubectl describe rolebinding podreaderbinding
Name:         podreaderbinding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  podreader
Subjects:
  Kind            Name                   Namespace
  ----            ----                   ---------
  User            exampleuser
  ServiceAccount  exampleserviceaccount

角色绑定后就可以访问 API Server 了。接下来分别使用之前创建的常规用户认证和ServiceAccount认证来访问API Server。

为了使用常规用户认证,基于之前创建的用户exampleuser中的令牌,通过API Server访问Pod,命令如下。

$ curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods -H \
"Authorization:Bearer 937eadfa60efc23102f636f881d3d99e"

为了使用ServiceAccount认证,首先,通过以下命令进入Pod内部,以便在Pod内部执行命令行。

podreaderbinding-v2.yml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: podreaderbinding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: exampleserviceaccount
    apiGroup: ""
roleRef:
  kind: Role
  name: podreader
  apiGroup: ""
$ kubectl exec -ti examplepodforserviceaccount -- /bin/sh

# curl --insecure https://192.168.1.161:6443/api/v1/namespaces/default/pods -H \
"Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"

可以发现通过ServiceAccount也成功获取了Pod列表信息。

2.2 集群角色的定义与绑定

集群角色与普通角色类似,但二者存在以下区别。

  • 使用的关键字不同。普通角色使用的关键字为Role,绑定普通角色使用的关键字为RoleBinding;集群角色使用的关键字为ClusterRole,绑定集群角色使用的关键字为ClusterRoleBinding。

  • 集群角色不属于任何命名空间,模板也无须指定命名空间。而普通角色要求指定命名空间,如果未指定,则默认为default命名空 间。

  • 集群角色可以访问全部命名空间下的资源,也可以访问不在命名空间下的资源(如Node、StorageClass等),可以通过$kubectl api-resources --namespaced=false命令查看不在命名空间下的资源。

Kubernetes系统在安装时就会设置一系列的集群角色定义和绑定,Kubernetes系统组件将会使用这些角色。

可以分别通过$ kubectl get clusterrole命令和$ kubectl get clusterrolebinding命令查看已有的角色定义及角色绑定。

集群角色定义的查询结果

$ kubectl get clusterrole
NAME                                                                   CREATED AT
admin                                                                  2021-10-26T11:49:18Z
cilium                                                                 2021-10-26T12:08:24Z
cilium-operator                                                        2021-10-26T12:08:24Z
cluster-admin                                                          2021-10-26T11:49:18Z
edit                                                                   2021-10-26T11:49:18Z
efk-nfs-storage-nfs-client-provisioner-runner                          2022-01-07T10:51:17Z
ingress-nginx                                                          2021-10-26T12:54:18Z
kube-state-metrics                                                     2022-04-15T08:00:09Z
kubeadm:get-nodes                                                      2021-10-26T11:49:20Z
kubernetes-dashboard                                                   2021-10-26T12:49:52Z
kubernetes-dashboard-view                                              2021-10-26T12:48:47Z
managed-nfs-storage-nfs-client-provisioner-runner                      2022-01-09T06:03:49Z
mysql-nfs-storage-nfs-client-provisioner-runner                        2022-02-25T08:22:17Z
pod-impersonation-shell-fhb5s                                          2021-10-29T11:47:15Z
prometheus                                                             2022-04-15T08:00:09Z
system:aggregate-to-admin                                              2021-10-26T11:49:18Z
system:aggregate-to-edit                                               2021-10-26T11:49:18Z
system:aggregate-to-view                                               2021-10-26T11:49:18Z
system:aggregated-metrics-reader                                       2021-10-26T14:07:20Z
system:auth-delegator                                                  2021-10-26T11:49:18Z
system:basic-user                                                      2021-10-26T11:49:18Z
system:certificates.k8s.io:certificatesigningrequests:nodeclient       2021-10-26T11:49:18Z
system:certificates.k8s.io:certificatesigningrequests:selfnodeclient   2021-10-26T11:49:18Z
system:certificates.k8s.io:kube-apiserver-client-approver              2021-10-26T11:49:18Z
system:certificates.k8s.io:kube-apiserver-client-kubelet-approver      2021-10-26T11:49:18Z
system:certificates.k8s.io:kubelet-serving-approver                    2021-10-26T11:49:18Z
system:certificates.k8s.io:legacy-unknown-approver                     2021-10-26T11:49:18Z
system:controller:attachdetach-controller                              2021-10-26T11:49:18Z
system:controller:certificate-controller                               2021-10-26T11:49:18Z
system:controller:clusterrole-aggregation-controller                   2021-10-26T11:49:18Z
system:controller:cronjob-controller                                   2021-10-26T11:49:18Z
system:controller:daemon-set-controller                                2021-10-26T11:49:18Z
.....

集群角色绑定的查询结果

$ kubectl get clusterrolebinding
NAME                                                   ROLE                                                                               AGE
cilium                                                 ClusterRole/cilium                                                                 176d
cilium-operator                                        ClusterRole/cilium-operator                                                        176d
cluster-admin                                          ClusterRole/cluster-admin                                                          176d
ingress-nginx                                          ClusterRole/ingress-nginx                                                          176d
jenkins-admin                                          ClusterRole/cluster-admin                                                          37d
kube-state-metrics                                     ClusterRole/kube-state-metrics                                                     5d18h
kubeadm:get-nodes                                      ClusterRole/kubeadm:get-nodes                                                      176d
kubeadm:kubelet-bootstrap                              ClusterRole/system:node-bootstrapper                                               176d
kubeadm:node-autoapprove-bootstrap                     ClusterRole/system:certificates.k8s.io:certificatesigningrequests:nodeclient       176d
kubeadm:node-autoapprove-certificate-rotation          ClusterRole/system:certificates.k8s.io:certificatesigningrequests:selfnodeclient   176d
kubernetes-dashboard                                   ClusterRole/kubernetes-dashboard                                                   176d
kubernetes-dashboard-view                              ClusterRole/kubernetes-dashboard-view                                              176d
kuboard-admin-crb                                      ClusterRole/cluster-admin                                                          153d
kuboard-viewer-crb                                     ClusterRole/view                                                                   153d
metrics-server:system:auth-delegator                   ClusterRole/system:auth-delegator                                                  176d
pod-impersonation-shell-6x2qv                          ClusterRole/pod-impersonation-shell-fhb5s                                          173d
prometheus                                             ClusterRole/cluster-admin                                                          5d18h
run-efk-nfs-storage-nfs-client-provisioner             ClusterRole/efk-nfs-storage-nfs-client-provisioner-runner                          103d

在之前的示例中,我们定义了一个名为podreader的普通角色,并以普通角色绑定的方式将其绑定到认证主体上,也可以使用集群角色 及绑定来实现同样的功能。具体模板的代码如下所示。

clusterpodreader.yml

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

---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: clusterpodreaderbinding
subjects:
    # 常规用户认证
  - kind: User
    name: exampleuser
    apiGroup: ""
    # ServiceAccount认证
  - kind: ServiceAccount
    name: exampleserviceaccount
    namespace: default
    apiGroup: ""
roleRef:
  kind: ClusterRole
  name: clusterpodreader
  apiGroup: ""

这段代码与之前的示例有几处区别。

其关键字分别为ClusterRole和ClusterRoleBinding,且没有指定命名空间。

由于ServiceAccount是某个命名空间下的资源,因此需要指明是对哪个命名空间下的ServiceAccount绑定集群角色的。

应用模板后,使用常规用户exampleuser以及ServiceAccount的exampleserviceaccount可以访问任何命名空间下的Pod资源,不再仅 限于default命名空间。

上述示例是将ClusterRole与ClusterRoleBinding关联在一起了, 在实际使用过程中也可以将ClusterRole与RoleBinding关联在一起。 因为ClusterRole是不限制命名空间的,所以如果想既给某个认证主体绑定 ClusterRole,又想限制它能够使用的命名空间, 就可以将它与 RoleBinding关联以达到限定效果。可以修改模板来实现该功能, 修改后的代码如下所示。

clusterpodreader-v2.yml

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

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: podreaderbinding
  namespace: default
subjects:
  - kind: User
    name: exampleuser
    apiGroup: ""
  - kind: ServiceAccount
    name: exampleserviceaccount
    namespace: default
    apiGroup: ""
roleRef:
  kind: ClusterRole
  name: clusterpodreader
  apiGroup: ""

这段代码与上一个示例有几处区别。

两个示例的关键字分别为ClusterRole和RoleBinding。ClusterRole没有指定命名空间,但RoleBinding指定命名空间为 default(如果没有指定命名空间,默认也为default)。

因为已经通过RoleBinding指定了命名空间,所以无须再给ServiceAccount指明命名空间。

应用模板后,使用常规用户的exampleuser以及ServiceAccount的exampleserviceaccount只能访问default命名空间下的Pod资源。