Kubernetes授权机制之RBAC


RBAC 介绍

在 Kubernetes 中,所有资源对象都是通过 API 进行操作,他们保存在 etcd 里。而对 etcd 的操作我们需要通过访问 kube-apiserver 来实现,上面的 Service Account 其实就是 APIServer 的认证过程,而授权的机制是通过 RBAC:基于角色的访问控制实现。

在 Kubernetes 的1.21.2版本上默认使用的是Node和RBAC。

# kubeadm部署的k8s可以在/etc/kubernetes/manifests下查看到静态pod的yaml文件
root@k8s-master01:/etc/kubernetes/manifests# grep authorization kube-apiserver.yaml
    - --authorization-mode=Node,RBAC

# Node是专用于向kubelet授权使用。
# RBAC是基于角色的范文控制

常用授权逻辑

  • DAC(自主访问控制)
  • MAC(强制访问控制)
  • RBAC(基于角色的访问控制)
  • ABAC(基于属性的访问控制)

RBAC

RBAC:Role-Based Access Control

RBAC

简单来说,就是通过将权限分配给➡角色,再将角色分配给➡用户,来实现对系统资源的访问控制。

在一个组织内把一个组织内应该具有的权限的集合定义成多个角色,然后设定某个用户可以扮演其中1到多个角色。从而让某个用户拥有在组织内的某个授权。

k8s的RBAC是一种许可授权,只允许用户做什么事情,默认拒绝所有。未显示指定授予的权限,默认都会被拒绝。

  Role --> Verbs  --> Objects
  ClusterRole --> Verbs  --> Objects
  Subject --> RoleBinding --> Roles
  Subject --> ClusterRoleBinding --> ClusterRoles
  Subject --> RoleBinding --> ClusterRoles

k8s 的 API-Server 是 RESTful 风格的 http/https 服务,其权限无非就是基于http协议所能支持的 GET, POST, PUT, DELETE, PATCH, ...等操作,在 API-Server 上 Object 指的是资源对象。

所谓的权限也就是,Action 能施加到哪些对象上;

RBAC四个资源类型

  • Role: 角色,名称空间级别;
  • ClusterRole:集群角色,全局级别;
  • RoleBinding:"角色绑定",指是将用户与角色关联起来,意味着,用户仅得到了特定名称空间下的Role的权限,作用范围也限于该名称空间;
  • ClusterRoleBinding:集群角色绑定,让用户扮演指定的集群角色;意味着,用户得到了是集群级别的权限,作用范围也是集群级别;

User --> Rolebindig --> ClusterRole:权限降级,ClusterRole,用户得到的权限仅是 ClusterRole 的权限在 Rolebinding 所属的名称空间上的一个子集;

系统上默认的ROLE

1.查看系统上默认的role

extension-apiserver-authentication-reader        2024-04-15T06:14:01Z
kube-proxy                                       2024-04-15T06:14:03Z
kubeadm:kubelet-config-1.21                      2024-04-15T06:14:01Z
kubeadm:nodes-kubeadm-config                     2024-04-15T06:14:01Z
system::leader-locking-kube-controller-manager   2024-04-15T06:14:01Z
system::leader-locking-kube-scheduler            2024-04-15T06:14:01Z
system:controller:bootstrap-signer               2024-04-15T06:14:01Z
system:controller:cloud-provider                 2024-04-15T06:14:01Z
system:controller:token-cleaner                  2024-04-15T06:14:01Z

2.查看kube-proxy的role中的内容

root@k8s-master01:~# kubectl get role kube-proxy -n kube-system -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  creationTimestamp: "2024-04-15T06:14:03Z"
  name: kube-proxy
  namespace: kube-system
  resourceVersion: "299"
  uid: b92871dd-4224-4f31-8fe2-0c4b89ca40ff
rules:
- apiGroups:
  - ""
  resourceNames:
  - kube-proxy
  resources:
  - configmaps
  verbs:
  - get

能接受施加Verb的目标有三类:

  • resources:资源类型,该类型下的所有对象都是目标, pods;
  • resourceNames:特定的对象个体,pods/mypod;
  • nonResourceURLs:非资源型的URL,/status.

能施加的Verb有以下:

  • create、get、list、delete、patch、update

RBAC示例

rbac资源清单创建示例

1.使用资源清单来创建role

root@k8s-master01:~/yaml/chapter09# vim pods-reader-rbac.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pods-reader
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods","services","pods/log"]
  verbs: ["get","list","watch"]

2.将其应用到集群上

root@k8s-master01:~/yaml/chapter09# kubectl apply -f pods-reader-rbac.yaml
role.rbac.authorization.k8s.io/pods-reader created

# 角色已经在default名称空间下生成
root@k8s-master01:~/yaml/chapter09# kubectl get role
NAME          CREATED AT
pods-reader   2021-08-02T06:44:03Z

3.角色需要将其绑定到用户上

root@k8s-master01:~/yaml/chapter09# vim darius-pods-reader.yaml
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: darius-pods-reader
  namespace: default
subjects:
- kind: User
  name: darius
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pods-reader
  apiGroup: rbac.authorization.k8s.io

4.应用绑定

root@k8s-master01:~/yaml/chapter09# kubectl apply -f darius-pods-reader.yaml
rolebinding.rbac.authorization.k8s.io/darius-pods-reader created

5.使用darius账号进行测试

root@k8s-master01:~/yaml/chapter09# kubectl get pods --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME                                             READY   STATUS      RESTARTS   AGE
configmaps-env-demo                              1/1     Running     0          17d
configmaps-volume-demo                           1/1     Running     0          17d
configmaps-volume-demo2                          2/2     Running     0          17d
configmaps-volume-demo3                          1/1     Running     0          16d
cronjob-demo-27131450-85h7z                      0/1     Completed   0          5m1s
cronjob-demo-27131452-xqqrk                      0/1     Completed   0          3m1s
cronjob-demo-27131454-fn7fp                      0/1     Completed   0          61s
daemonset-demo-6qqmt                             1/1     Running     0          11d
daemonset-demo-fvkhj                             1/1     Running     0          11d
daemonset-demo-pxmrd                             1/1     Running     0          11d
demodb-0                                         1/1     Running     0          6d5h
demodb-1                                         1/1     Running     0          6d5h
deployment-demo-77d46c4794-5whvx                 1/1     Running     0          11d

# 已经能正常获取pods资源。

集群管理角色

admin集群管理角色

在 k8s 系统上存在一个 admin 的 ClusterRole,其作用的范围为集群范围,其内部定义了核心资源类型当中的非集群级别资源的管理权限。此 admin 拥有除集群级别之外的所有管理权限。

root@k8s-master01:~/yaml/chapter09# kubectl get clusterrole admin
NAME    CREATED AT
admin   2024-04-15T06:13:59Z

如果我们使用 ClusterRolebinding 将某个用户绑定在 admin 这个 ClusterRole 上那么其将拥有除了集群级别管理权限之外的所有管理权限。

cluster-admin集群管理角色

cluster-admin 是集群管理员,其拥有k8s的一切管理权限。

root@k8s-master01:~/yaml/chapter09# kubectl get clusterrole cluster-admin
NAME            CREATED AT
cluster-admin   2024-04-15T06:13:59Z

如果将某个用户以 clusterRoleBinding 绑定在 cluster-admin 那其将拥有集群级别的一切操作管理权限。

rbac命令行创建示例

admin集群管理角色绑定示例:

此处为了不予刚才示例混淆,先将 darius 的 rolerolebinding 删除

root@k8s-master01:~/yaml/chapter09# kubectl delete rolebindings.rbac.authorization.k8s.io darius-pods-reader
rolebinding.rbac.authorization.k8s.io "darius-pods-reader" deleted

root@k8s-master01:~/yaml/chapter09# kubectl delete role pods-reader
role.rbac.authorization.k8s.io "pods-reader" deleted

1.将用户于admin的clusterRole进行绑定

root@k8s-master01:~/yaml/chapter09# kubectl create clusterrolebinding darius-admin --user=darius --clusterrole=admin
clusterrolebinding.rbac.authorization.k8s.io/darius-admin created

2.使用darius账号进行测试

root@k8s-master01:~/yaml/chapter09# kubectl get pods -n kube-system --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME                                   READY   STATUS    RESTARTS   AGE
coredns-6f6b8cc4f6-8wm8v               1/1     Running   0          18d
coredns-6f6b8cc4f6-tzmnm               1/1     Running   0          18d
etcd-k8s-master01                      1/1     Running   1          18d
kube-apiserver-k8s-master01            1/1     Running   1          18d
kube-controller-manager-k8s-master01   1/1     Running   1          18d
kube-flannel-ds-dl2rq                  1/1     Running   0          18d
kube-flannel-ds-fmml6                  1/1     Running   0          18d
kube-flannel-ds-rwh5f                  1/1     Running   0          18d
kube-flannel-ds-tqbbv                  1/1     Running   0          18d
kube-proxy-6qdpb                       1/1     Running   0          18d
kube-proxy-kp5ch                       1/1     Running   0          18d
kube-proxy-ntmzb                       1/1     Running   0          18d
kube-proxy-vwdm8                       1/1     Running   0          18d
kube-scheduler-k8s-master01            1/1     Running   1          18d

此时其能访问到 kube-system 的资源了。但是集群级别的操作依旧不能使用。

# 查看nodes相关资源
root@k8s-master01:~/yaml/chapter09# kubectl get nodes --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): nodes is forbidden: User "darius" cannot list resource "nodes" in API group "" at the cluster scope

# 权限被拒绝,因为admin的ClusterRole没有此授权。

cluster-admin集群管理角色绑定示例:

将此前创建的admin相关的 clusterrolebinding 进行删除,以免干扰

root@k8s-master01:~/yaml/chapter09# kubectl delete clusterrolebindings darius-admin
clusterrolebinding.rbac.authorization.k8s.io "darius-admin" deleted

3.将darius用户使用clusterRolebinding绑定到cluster-admin这个roles上

root@k8s-master01:~/yaml/chapter09# kubectl create clusterrolebinding darius-cluster-admin --user=darius --clusterrole=cluster-admin
clusterrolebinding.rbac.authorization.k8s.io/darius-cluster-admin created

4.再次测试其能否进行集群级别的操作

root@k8s-master01:~/yaml/chapter09# kubectl get nodes --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master01   Ready    control-plane,master   18d   v1.21.2
k8s-node01     Ready    <none>                 18d   v1.21.2
k8s-node02     Ready    <none>                 18d   v1.21.2
k8s-node03     Ready    <none>                 18d   v1.21.2

授权其他话题

组在k8s中的作用

在k8s中 cluster-admin 是将 system:masters 组绑定在 cluster-admin 之上的。那么组内的所有用户都将拥有此权限。

root@k8s-master01:~/yaml/chapter09# kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind   Name            Namespace
  ----   ----            ---------
  Group  system:masters

对于证书认证来说组信息在Subj中的O内存放,如果其O内存放的为 system:master 那么所创建的用户自动拥有管理员权限,无需再授权。

验证

# 生成私钥文件
root@k8s-master01:/etc/kubernetes/usercerts# (umask 077;openssl genrsa -out testadm.key 2048)                     
Generating RSA private key, 2048 bit long modulus (2 primes)
.....................................................................................................+++++
............+++++
e is 65537 (0x010001)

# 生成证书签署请求,此处subj中的O使用system:masters
root@k8s-master01:/etc/kubernetes/usercerts# openssl req -new -key testadm.key -out testadm.csr -subj "/CN=testadm/O=system:masters"

# 使用k8s集群的证书和私钥对证书签署请求进行签发
root@k8s-master01:/etc/kubernetes/usercerts# openssl x509 -req -days 3655 -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -in testadm.csr -out testadm.crt
Signature ok
subject=CN = testadm, O = system:masters
Getting CA Private Key

# 以下为制作kubeconfig文件
# 在kubeconfig文件中设定集群
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-cluster kubernetes --server=https://kube-api:6443 --embed-certs --certificate-authority=/etc/kubernetes/pki/ca.crt --kubeconfig=/tmp/testadmcfg
Cluster "kubernetes" set.

# 在kubeconfig文件中设定用户
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-credentials testadm --client-certificate=testadm.crt --client-key=testadm.key --embed-certs=true --kubeconfig=/tmp/testadmcfg
User "testadm" set.

# 在kubeconfig文件中设定用户和集群的关联关系
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config set-context 'testadm@kubernetes' --user=testadm --cluster=kubernetes --kubeconfig=/tmp/testadmcfg
Context "testadm@kubernetes" created.

# 在kubeconfig文件中设定当前使用的账号
root@k8s-master01:/etc/kubernetes/usercerts# kubectl config use-context testadm@kubernetes --kubeconfig=/tmp/testadmcfg
Switched to context "testadm@kubernetes".

# 当前账号没有进行授权,使用该账号获取集群信息。
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get nodes --kubeconfig=/tmp/testadmcfg
NAME           STATUS   ROLES                  AGE   VERSION
k8s-master01   Ready    control-plane,master   18d   v1.21.2
k8s-node01     Ready    <none>                 18d   v1.21.2
k8s-node02     Ready    <none>                 18d   v1.21.2
k8s-node03     Ready    <none>                 18d   v1.21.2

以上结果可以看出证书认证中 O 这一项如果为 system:masters 则无需再进行授权就能对集群进行操作。组这一项对k8s来说至关重要。

rolebinding来绑定ClusterRole

rolebinding 来绑定 ClusterRole 则以为着降级,其会将集群级别的操作限定在名称空间内。

验证

避免干扰先将此前创建的 clusterrolebinding 进行删除

root@k8s-master01:/etc/kubernetes/usercerts# kubectl delete clusterrolebindings darius-cluster-admin
clusterrolebinding.rbac.authorization.k8s.io "darius-cluster-admin" deleted

1.将darius用户使用 rolebinding 绑定到 cluster-admin 这个 ClusterRole

root@k8s-master01:/etc/kubernetes/usercerts# kubectl create rolebinding darius-admin --user=darius --clusterrole=cluster-admin
rolebinding.rbac.authorization.k8s.io/darius-admin created

# 注意此处rolebing时没有指定名称空间表示默认名称空间,darius用户的权限会限定在default名称空间下
# 如果指定了名称空间如"-n dev",darius用户则会被限定在dev名称空间下。

2.验证

# 测试访问默认名称空间内的资源
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP    PORT(S)          AGE
demoapp-svc   ClusterIP   10.102.254.190   <none>         80/TCP           11d
demodb        ClusterIP   None             <none>         9907/TCP         7d3h

# 访问其他名称空间内的资源
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc -n kube-system --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): services is forbidden: User "darius" cannot list resource "services" in API group "" in the namespace "kube-system"
root@k8s-master01:/etc/kubernetes/usercerts# kubectl get svc -n dev --kubeconfig=/tmp/newkubeconfig --context=darius@kubernetes
Error from server (Forbidden): services is forbidden: User "darius" cannot list resource "services" in API group "" in the namespace "dev"

rolebinding绑定ServiceAccount

创建一个 ServiceAccount,并将其使用 rolebinding 绑定到admin的 ClusterRole

# 创建ServiceAccount
root@k8s-master01:/etc/kubernetes/usercerts# kubectl create serviceaccount dev-admin
serviceaccount/dev-admin created

# 创建rolebinding将dev-admin的sa绑定到admin这个ClusterRole上
root@k8s-master01:~# kubectl create rolebinding dev-admin --clusterrole=admin --serviceaccount=dev:dev-admin -n dev
rolebinding.rbac.authorization.k8s.io/dev-admin created

# dev:dev-admin表示dev名称空间下的dev-admin的ServiceAccount

以上操作后,如果有pod的 ServiceAcountNamedev-admin 那么此pod将拥有该名称空间下的所有操作权限。