4 RBAC授权

4.1 什么是RBAC

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

RBAC(Role Base Access Control)基于角色的访问控制,其实就是将资源的操作权限授予给指定的角色,而后将用户加入该角色,那么该用户则拥有了对应角色的权限。

RBAC有四个资源对象,分别是 Role、ClusterRole、RoleBinding、ClusterRoleBinding。

RBAC授权_Group

举例: 希望qingchen用户能够获取所有Pod的列表

1、首先定义角色,然后定义角色权限规则,资源: POd,操作权限: get,list

2、然后定义角色绑定,将qingchen绑定至该角色,然后qingchen就拥有了该角色的权限,进而就能获取Pod信息

RBAC授权_命名空间_02

4.2 RBAC角色与集群角色

Kubernetes系统的RBAC授权插件将角色分为了Role和ClusterRole两类:

Role: 进作用于名称空间级别,用于承载名称空间级别内的资源权限集合

ClusterRole: 作用于集群乏味,能够同时承载名称空间和集群级别的资源权限集合

Kubernetes利用Role和ClusterRole两类角色来赋予对应的权限,同时也需要用到另外两类资源Rolebinding和ClusterRolebinding来完成用户与角色之间的绑定关系。

RBAC授权_命名空间_03

注意: RoleBinding除了可以绑定Role以外,还可以绑定ClusterRole,但它的权限还是限制在名称空间级别;

这种方式有着特定的应用场景:

比如: 希望在三个名称空间中都创建一个管理员身份,那么我们就需要创建3个role和3个rolebinding

但是: 我们可以定义一个clusterrole,然后通过rolebinding绑定就完成了,,也就不需要重复创建很多的role

RBAC授权_名称空间_04

4.3Role:角色

一组权限的集合,在一个命名空间中,可以用其来定义一个角色,只能对命名空间内的资源进行授权。如果是集群级别的资源,则需要使用ClusterRole。例如:定义一个角色用来读取 Pod 的权限

apiVersion: rbac.authorization.k8s.io/v1
kind: Role 
metadata: namespace: rbac name: pod-read 
rules: 
- apiGroups: [""] resources: ["pods"] resourceNames: [] verbs: ["get","watch","list"]rules 中的参数说明: 
1、apiGroups:支持的API组列表,例如:"apiVersion: batch/v1"等 
2、resources:支持的资源对象列表,例如pods、deplayments、jobs等 
3、resourceNames: 指定resource的名称 
4、verbs:对资源对象的操作方法列表。
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

4.4ClusterRole:集群角色

具有和角色一致的命名空间资源的管理能力,还可用于以下特殊元素的授权

1、集群范围的资源,例如Node

2、非资源型的路径,例如:/healthz

3、包含全部命名空间的资源,例如Pods

例如:定义一个集群角色可让用户访问任意

apiVersion: rbac.authorization.k8s.io/v1 
kind: ClusterRole 
metadata: name: secrets-clusterrole 
rules: 
- apiGroups: [""] resources: ["secrets"] verbs: ["get","watch","list"]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

4.5RoleBinding:角色绑定、ClusterRolebinding:集群角色绑定 

角色绑定和集群角色绑定用于把一个角色绑定在一个目标上,可以是 User,Group,Service Account,使用RoleBinding为某个命名空间授权,使用ClusterRoleBinding为集群范围内授权。

例如:将在 rbac 命名空间中把 pod-read 角色授予用户 es

apiVersion: rbac.authorization.k8s.io/v1 
kind: RoleBinding 
metadata: name: pod-read-bind namespace: rbac 
subjects: 
- kind: User name: es apiGroup: rbac.authorization.k8s.io 
roleRef: kind: Role name: pod-read apiGroup: rbac.authorizatioin.k8s.io
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

RoleBinding也可以引用ClusterRole,对属于同一命名空间内的ClusterRole定义的资源主体进行授权, 例如:es 能获取到集群中所有的资源信息

apiVersion: rbac.authorization.k8s.io/v1 
kind: RoleBinding 
metadata: name: es-allresource namespace: rbac 
subjects: 
- kind: User name: es apiGroup: rbac.authorization.k8s.io 
roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

集群角色绑定的角色只能是集群角色,用于进行集群级别或对所有命名空间都生效的授权

例如:允许manager组的用户读取所有namaspace的secrets

apiVersion: rabc.authorization.k8s.io/v1
kind: ClusterRoleBinding 
metadata: name: read-secret-global 
subjects: 
- kind: Group name: manager apiGroup: rabc.authorization.k8s.io 
ruleRef: kind: ClusterRole name: secret-read apiGroup: rabc.authorization.k8s.io
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

4.6 资源的引用方式

多数资源可以用其名称的字符串表示,也就是Endpoint中的URL相对路径,例如pod中的日志是GET /api/v1/namaspaces/{namespace}/pods/{podname}/log

如果需要在一个RBAC对象中体现上下级资源,就需要使用“/”分割资源和下级资源。

例如:若想授权让某个主体同时能够读取Pod和Pod log,则可以配置 resources 为一个数组

apiVersion: rabc.authorization.k8s.io/v1 
kind: Role 
metadata: name: logs-reader namespace: default 
rules: 
- apiGroups: [""] resources: ["pods","pods/log"] verbs: ["get","list"]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

资源还可以通过名称(ResourceName)进行引用,在指定ResourceName后,使用get、 delete、update、patch请求,就会被限制在这个资源实例范围内

例如,下面的声明让一个主体只能对名为my-configmap的Configmap进行get和update操作:

apiVersion: rabc.authorization.k8s.io/v1 
kind: Role 
metadata: namaspace: default name: configmap-update 
rules: 
- apiGroups: [""] resources: ["configmap"] resourceNames: ["my-configmap"] verbs: ["get","update"]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

4.7RBAC场景实践

4.7.1 kubectl命令行工具创建资源对象

(1)在命名空间rbac中为用户es授权admin ClusterRole:

kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=es --namespace=rbac

(2)在命名空间rbac中为名为myapp的Service Account授予 view ClusterRole:

kubctl create rolebinding myapp-role-binding --clusterrole=view --serviceaccount=rbac:myapp --namespace=rbac

(3)在全集群范围内为用户root授予cluster-admin ClusterRole:

kubectl create clusterrolebinding cluster-binding --clusterrole=cluster-admin --user=root

(4)在全集群范围内为名为myapp 的 Service Account 授予 view ClusterRole:

kubectl create clusterrolebinding service-account-binding --clusterrole=view --serviceaccount=myapp

yaml 文件进行 rbac 授权:https://kubernetes.io/zh/docs/reference/access-authnauthz/rbac/

4.7.2实践场景-1

场景说明: 赋予qingchen用户对default名称空间拥有Pod的读取权限

1、创建role角色,设定对应的规则

#命令方式
kubectl create role default-pod-reader \
--resource=pod \
--verb=get,list,watch \
--namespace=default#yaml方式
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:name: default-pod-readernamespace: default
rules:
- apiGroups:- ""resources:- podsverbs:- get- list- watch
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.

2、创建rolebinding角色绑定,将qingchen绑定至对应的role上

#命令方式
kubectl create rolebinding qingchen-default-pod-reader \
--role=default-pod-reader \
--user=qingchen \
--namespace=default#yaml方式
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:name: qingchen-default-pod-readernamespace: default
roleRef:apiGroup: rbac.authorization.k8s.iokind: Rolename: default-pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.iokind: Username: qingchen
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

3、使用qingchen用户验证权限

RBAC授权_Group_05

#非default名称空间,访问会报错

4.7.3实践场景-2

场景说明: 赋予qingchen用户对所有名称空间拥有Pod的读写权限(ClusterRole、ClusterRoleBinding)

1、创建clusterrole

#命令方式
kubectl create clusterrole cluster-pod-reader \
--resource=pod \
--verb=get,list,watch#yaml方式
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:name: cluster-pod-reader
rules:
- apiGroups:- ""resources:- podsverbs:- get- list- watch
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

2、创建clusterrolebinding,并绑定qingchen用于至对应的clusterrole

#命令方式
kubectl create clusterrolebinding cluster-pod-reader-qingchen \
--clusterrole=cluster-pod-reader \
--user=qingchen#yaml方式
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: cluster-pod-reader-qingchen
roleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: cluster-pod-reader
subjects:
- apiGroup: rbac.authorization.k8s.iokind: Username: qingchen
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

3、使用qingchen用户验证权限

kubectl get pod --context="qingchen@kubernetes"

kubectl get pod -n kube-system --context="qingchen@kubernetes"

RBAC授权_名称空间_06

#任何名称空间都可以查看,但没有删除权限

RBAC授权_命名空间_07

4.7.4实践场景-3

场景说明: 赋予qingchen用户对default名称空间拥有管理员权限

系统内置了一个ClusterRole:admin的集群管理员,我们可以通过rolebinding引用Cluster:admin集群角色,该引用会造成用户仅对rolebinding所在的名称空间有管理员权限(因为rolebinding仅能作用在名称空间)。

1、删除此前的绑定,避免权限受到干扰

kubectl delete clusterrolebinding cluster-pod-reader-qingchen

2、创建RoleBinding引用Cluster-role

kubectl create rolebinding default-admin-qingchen \
--clusterrole=admin \
--user=qingchen \
--namespace=default
  • 1.
  • 2.
  • 3.
  • 4.

3、验证qingchen用户权限

RBAC授权_Group_08

#能对default名称空间进行增删改查,对其他名称空间毫无权限

RBAC授权_命名空间_09

4.8内置的ClusterRole

Kubernetes系统内置了一组默认的ClusterRole和ClusterRoleBinding资源预留给系统使用,其中大多数以system:为前缀。还有一些不以system:为前缀的

ClusterRole是面向用户设计的,比如: 集群管理员角色cluster-admin、admin、edit、view,掌握这些默认的内置角色资源有助于按需创建用户并分配相应的权限。

RBAC授权_Group_10

4.8.1 Cluster-admin分析

内置的cluster-admin资源拥有管理集群所有资源的权限,而内置的cluster-admin将该角色分配给了system:master组,这意味着所有加入该组的用户都将自动具有集群的超级管理员权限。

在使用kubeadm安装集群时,它自动创建配置文件/etc/kubernetes/admin.conf中定义的用户为kubernetes-admin,而该用户使用数字证书,Subject属性值为/O=system:masters。所以APIServer会在成功验证该用户的身份之后将其识别为system:masters用户组的成员。

RBAC授权_命名空间_11

分析过程如下:

1、查看cluster-admin角色绑定关系,可以看到cluster-admin这个角色绑定的system.masters

RBAC授权_Group_12

2、system:masters这个组名称并非人为定义,而是证书生成的

openssl x509 -in /etc/kubernetes/pki/apiserver-kubelet-client.crt -text -noout

RBAC授权_名称空间_13

注意: 在创建证书时,可以将用户绑定到system:masters、组,用户会自动继承组的权限

4.8.2 Cluster-admin实践

创建一个k8s-dream用户,然后将该用户加入到system:masters组中,验证是否拥有集群管理员权限

1、创建证书私钥文件

mkdir /root/k8scerts -p
umask 077
openssl genrsa -out /root/k8scerts/k8s-dream.key 2048
  • 1.
  • 2.
  • 3.

2、创建证书签署请求文件,CN为指定的用户名,O为指定的组名称

openssl req -new \
-key /root/k8scerts/k8s-dream.key \
-out /root/k8scerts/k8s-dream.csr \
-subj "/CN=k8s-dream/O=system:masters"
  • 1.
  • 2.
  • 3.
  • 4.

3、使用kubernetes-ca的身份对文件进行签署

openssl x509 -req -days 3650 \
-in /root/k8scerts/k8s-dream.csr \
-CA /etc/kubernetes/pki/ca.crt \
-CAkey /etc/kubernetes/pki/ca.key \
-CAcreateserial \
-out /root/k8scerts/k8s-dream.crt
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

4、根据x509数字证书及私钥创建身份凭据

kubectl config set-credentials k8s-dream \
--client-certificate=/root/k8scerts/k8s-dream.crt \
--client-key=/root/k8scerts/k8s-dream.key \
--embed-certs=true
  • 1.
  • 2.
  • 3.
  • 4.

5、配置context上下文,以k8s-dream身份凭据访问已定义的Kubernetes集群,context名称为k8s-dream@kubernetes

kubectl config set-context k8s-dream@kubernetes \
--cluster=kubernetes \
--user=k8s-dream
  • 1.
  • 2.
  • 3.

6、测试k8s-dream是否具备超级管理员权限

kubectl get nodes --context="k8s-dream@kubernetes"

kubectl get pod -A --context="k8s-dream@kubernetes"

RBAC授权_名称空间_14

4.9 常见角色示例

(1)允许读取核心 API 组的 Pod 资源 
rules: 
- apiGroups: [""] resources: ["pods"] verbs: ["get","list","watch"] (2)允许读写 extensions 和 apps 两个 API 组中的 deployment 资源 
rules: 
- apiGroups: ["extensions","apps"] resources: ["deployments"] verbs: ["get","list","watch","create","update","patch","delete"] (3)允许读取 Pod 以及读写 job 信息 
rules: 
- apiGroups: [""] resources: ["pods"] verbs: ["get","list","watch"]、 
- apiVersion: ["batch","extensions"] resources: ["jobs"] verbs: ["get","list","watch","create","update","patch","delete"] (4)允许读取一个名为 my-config 的 ConfigMap(必须绑定到一个 RoleBinding 来限制到一个Namespace下的 ConfigMap): 
rules: 
- apiGroups: [""] resources: ["configmap"] resourceNames: ["my-configmap"] verbs: ["get"] (5)读取核心组的 Node 资源(Node 属于集群级的资源,所以必须存在于 ClusterRole 中,并使用 ClusterRoleBinding 进行绑定): 
rules: 
- apiGroups: [""] resources: ["nodes"] verbs: ["get","list","watch"] (6)允许对非资源端点“/healthz”及其所有子路径进行 GET 和 POST 操作(必须使用ClusterRole 和 ClusterRoleBinding):
rules: 
- nonResourceURLs: ["/healthz","/healthz/*"] verbs: ["get","post"]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.

4.10 常见角色绑定示例

(1)用户名 alice 
subjects: 
- kind: User name: alice apiGroup: rbac.authorization.k8s.io (2)组名 alice 
subjects: 
- kind: Group name: alice apiGroup: rbac.authorization.k8s.io (3)kube-system 命名空间中默认 Service Account 
subjects: 
- kind: ServiceAccount name: default namespace: kube-system (4)qa 命名空间中的所有 Service Account: 
subjects: 
- kind: Group name: system:serviceaccounts:qa apiGroup: rbac.authorization.k8s.io (5)所有 Service Account 
subjects: 
- kind: Group name: system:serviceaccounts apiGroup: rbac.authorization.k8s.io (6)所有认证用户
subjects: 
- kind: Groupname: system:authenticated apiGroup: rbac.authorization.k8s.io (7)所有未认证用户
subjects: 
- kind: Group name: system:unauthenticated apiGroup: rbac.authorization.k8s.io (8)全部用户
subjects: 
- kind: Group name: system:authenticated apiGroup: rbac.authorization.k8s.io 
- kind: Group name: system:unauthenticated apiGroup: rbac.authorization.k8s.io
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.

4.11 限制不同的用户操作k8s集群

ssl 认证 
生成一个证书
(1)生成一个私钥
cd /etc/kubernetes/pki/ 
(umask 077; openssl genrsa -out lucky.key 2048) 
(2)生成一个证书请求
openssl req -new -key lucky.key -out lucky.csr -subj "/CN=lucky" 
(3)生成一个证书
openssl x509 -req -in lucky.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out lucky.crt -days 3650 在 kubeconfig 下新增加一个 lucky 这个用户 
(1)把 lucky 这个用户添加到 kubernetes 集群中,可以用来认证 apiserver 的连接 
kubectl config set-credentials lucky --client-certificate=./lucky.crt --client-key=./lucky.key --embed-certs=true 
(2)在 kubeconfig 下新增加一个 lucky 这个账号 
kubectl config set-context lucky@kubernetes --cluster=kubernetes --user=lucky 
(3)切换账号到 lucky,默认没有任何权限 
kubectl config use-context lucky@kubernetes 
kubectl config use-context kubernetes-admin@kubernetes 这个是集群用户,有任何权限 把user这个用户通过rolebinding绑定到clusterrole上,授予权限,权限只是在lucky这个名称空间有效 
(1)把 lucky 这个用户通过 rolebinding 绑定到 clusterrole 上 
kubectl create ns lucky 
kubectl create rolebinding lucky -n lucky --clusterrole=cluster-admin --user=lucky 
(2)切换到 lucky 这个用户 
kubectl config use-context lucky@kubernetes 
(3)测试是否有权限
kubectl get pods -n lucky 
有权限操作这个名称空间
kubectl get pods 
没有权限操作其他名称空间添加一个 lucky 的普通用户 
useradd lucky 
cp -ar /root/.kube/ /home/lucky/ 
chown -R lucky.lucky /home/lucky/ 
su - lucky 
kubectl get pods -n lucky
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.