首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >一文带你搞定k8s的rbac鉴权

一文带你搞定k8s的rbac鉴权

原创
作者头像
聂伟星
发布于 2026-10-28 16:01:39
发布于 2026-10-28 16:01:39
960
举报

一文带你搞定k8s的rbac鉴权

k8s基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。

RBAC鉴权机制使用rbac.authorization.k8s.io API组来驱动鉴权决定,允许你通过Kubernetes API动态配置策略。

rbac的概念主要可以参考下图

upload-image
upload-image

概念介绍

  • Role: 用于定义某个命名空间的角色的权限。
  • ClusterRole: 用于定义整个集群的角色的权限。
  • RoleBinding: 将角色中定义的权限赋予一个或者一组用户,针对命名空间执行授权。
  • ClusterRoleBinding: 将角色中定义的权限赋予一个或者一组用户,针对集群范围内的命名空间执行授权。

k8s上主要是通过上面4个对象来实现对不同的用户来进行权限控制,下面我们来说说如何编写rbac的yaml来实现对子账号进行权限控制。

现在很多云厂商其实已经将k8s的rbac对接了自己cam鉴权系统,客户只需要编写role或者clusterrole来配置权限,然后绑定给云上的子账号,就可以对不同子账号设置对应的权限。

一般云厂商的托管k8s服务,都有提供常用的clusterrole,这里拿腾讯云为例,腾讯云默认就提供4种角色:

  • 管理员(tke:admin):对所有命名空间下资源的读写权限,具备集群节点、存储卷、命名空间、配额的读写权限,可配置子账号的读写权限。
  • 运维人员(tke:ops):对所有命名空间下控制台可见资源的读写权限,具备集群节点、存储卷、命名空间、配额的读写权限。
  • 开发人员(tke:dev):对所有命名空间下控制台可见资源的读写权限。
  • 受限人员(tke:ro):对所有命名空间下控制台可见资源的只读权限。

但是有时候我们对权限控制比较严格,只希望给某些资源的权限给子账号,上面的权限就无法满足了,这个时候就需要我们自己写role或者clusterrole来配置角色了。

如果对rbac不是很了解的话,通过写yaml自定义角色会比较困难,下面我来带你如何通过yaml配置自定义角色权限。

clusterrole字段说明

如果要熟练的编写clusterrole,需要熟悉下面几个字段配置才行,首先我们看一份集群的admin角色yaml,这里的*代表所有,后面再详细讲解字段说明

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - '*'
  resources:
  - '*'
  verbs:
  - '*'

apiGroups

为了更容易对API进行扩展,Kubernetes使用API Groups(API组)进行标识。API Groups以REST URL中的路径进行定义,当前支持两类 API groups。

  • Core Groups(核心组),也可以称之为Legacy Groups,作为 Kubernetes最核心的API,其特点是没有“组”的概念,例如“v1”,在资源对象的定义中表示为“apiVersion:v1”。
  • 具有分组信息的API,以/apis/$GROUP_NAME/$VERSION URL路径进行标识,在资源对象的定义中表示为“apiVersion: $GROUP_NAME/$VERSION”,例如:“apiVersion: batch/v1”,“apiVersion: extensions:v1beta1”,“apiVersion: apps/v1beta1”等

那么怎么查看资源是属于那个apiGroups呢,哪些资源是核心组的呢?

这里我们可以在集群内通过下面命令获取

代码语言:bash
复制
[root@VM-0-13-centos ~]# kubectl api-resources
NAME                                       SHORTNAMES         APIGROUP                           NAMESPACED   KIND
bindings                                                                                         true         Binding
componentstatuses                          cs                                                    false        ComponentStatus
configmaps                                 cm                                                    true         ConfigMap
endpoints                                  ep                                                    true         Endpoints
events                                     ev                                                    true         Event
limitranges                                limits                                                true         LimitRange
namespaces                                 ns                                                    false        Namespace
nodes                                      no                                                    false        Node
persistentvolumeclaims                     pvc                                                   true         PersistentVolumeClaim
persistentvolumes                          pv                                                    false        PersistentVolume
pods                                       po                                                    true         Pod
podtemplates                                                                                     true         PodTemplate
replicationcontrollers                     rc                                                    true         ReplicationController
resourcequotas                             quota                                                 true         ResourceQuota
secrets                                                                                          true         Secret
serviceaccounts                            sa                                                    true         ServiceAccount
services                                   svc                                                   true         Service
controllerrevisions                                           apps                               true         ControllerRevision
daemonsets                                 ds                 apps                               true         DaemonSet
deployments                                deploy             apps                               true         Deployment
replicasets                                rs                 apps                               true         ReplicaSet
statefulsets                               sts                apps                               true         StatefulSet
applications                               app,apps           argoproj.io                        true         Application
....

执行获取的结果中,如果资源对应的APIGROUP字段是空,则说明这个资源是属于core api,如果APIGROUP不是空,则说明资源属于对应的这个组,例如场景的控制器DaemonSet、Deployment、StatefulSet都是属于apps这个APIGROUP。

所以你在写yaml的时候,如果resource配置了这些控制器,就要在APIGROUP配置上apps这个。如果你配置了具有分组信息的API资源,但是没有配置上对应的APIGROUP,那么这个资源权限就不会生效。

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - ''
  resources:
  - 'Deployment'
  verbs:
  - '*'

将上面的ClusterRole绑定给子账号,子账号还是没有deployment的权限,因为这里没有指定apiGroups,这里就会把deployment当成核心api,这样是无法在apiserver校验通过。因此这里要想让子账号有deployment权限,在apiGroups加上apps即可。

但是有的同学就会问,如果我不知道资源的apiGroups是什么怎么办呢?这里可以配置成*,这里会自动匹配到资源所属的apiGroups

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - '*'
  resources:
  - 'Deployment'
  verbs:
  - '*'

因此上面这样配置子账号也是有deployment的权限的。如果需要配置多个资源的权限,将同一个apiGroups的配置成一条规则,就像下面一样

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - 'apps'
  resources:
  - 'Deployment'
  - 'statefulsets'
  verbs:
  - '*'
- apiGroups:
  - ''
  resources:
  - 'namespaces'
  - 'configmaps'
  verbs:
  - '*'

上面我们把核心api的都放到一个rule,然后apps这个api组的放到一个rule。

resources

上面我们说了资源对象的apiGroups,那么k8s中到底有哪些资源对象,如果我只希望给子账号部分的资源的权限,怎么获取这些资源对象呢?

其实可以通过下面命令获取集群中所有的资源对象

代码语言:bash
复制
[root@VM-0-13-centos ~]# kubectl api-resources
NAME                                       SHORTNAMES         APIGROUP                           NAMESPACED   KIND
bindings                                                                                         true         Binding
componentstatuses                          cs                                                    false        ComponentStatus
configmaps                                 cm                                                    true         ConfigMap
endpoints                                  ep                                                    true         Endpoints
events                                     ev                                                    true         Event
limitranges                                limits                                                true         LimitRange
namespaces                                 ns                                                    false        Namespace
nodes                                      no                                                    false        Node
persistentvolumeclaims                     pvc                                                   true         PersistentVolumeClaim
persistentvolumes                          pv                                                    false        PersistentVolume
pods                                       po                                                    true         Pod
podtemplates                                                                                     true         PodTemplate
replicationcontrollers                     rc                                                    true         ReplicationController
resourcequotas                             quota                                                 true         ResourceQuota
secrets                                                                                          true         Secret
serviceaccounts                            sa                                                    true         ServiceAccount
services                                   svc                                                   true         Service
controllerrevisions                                           apps                               true         ControllerRevision
daemonsets                                 ds                 apps                               true         DaemonSet
deployments                                deploy             apps                               true         Deployment
replicasets                                rs                 apps                               true         ReplicaSet
statefulsets                               sts                apps                               true         StatefulSet
applications                               app,apps           argoproj.io                        true         Application
.........

通过上面命令可以获取所有的api资源,name字段代表资源的名称。如果你需要给对应资源权限,只需要在role或者clusterrole里面的resources配置上资源的name即可

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - 'apps'
  resources:
  - 'Deployment'
  - 'statefulsets'
  - 'daemonsets'
  verbs:
  - '*'

上面实例,我们就给了子用户的基本控制器的权限。

其实k8s中我们还可以指定某一个或者某几个资源权限给子账号,我们可以在resourceNames字段配置具体某个资源的权限

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-grantor
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings"]
  verbs: ["create"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["clusterroles"]
  verbs: ["bind"]
  # 忽略 resourceNames 意味着允许绑定任何 ClusterRole
  resourceNames: ["admin","edit","view"]

上面的示例,说明这里只给了admin、edit、view这3个ClusterRole的bind权限。

resource这里其实还有一个Sub-resource的概念,就是单个资源下还可能会分为多个子资源,有时候我们为了更好权限,可能就只给子资源的权限,那么如何查看资源下有哪些子资源呢?

首先用命令查看api的版本

代码语言:bash
复制
[root@VM-0-13-centos ~]# kubectl api-versions
acme.cert-manager.io/v1
acme.cert-manager.io/v1alpha2
acme.cert-manager.io/v1alpha3
acme.cert-manager.io/v1beta1
admissionregistration.k8s.io/v1
admissionregistration.k8s.io/v1beta1
agent.k8s.elastic.co/v1alpha1
apiextensions.k8s.io/v1
apiextensions.k8s.io/v1beta1
apiregistration.k8s.io/v1
apiregistration.k8s.io/v1beta1
apisix.apache.org/v1
apisix.apache.org/v2alpha1
apisix.apache.org/v2beta1
apisix.apache.org/v2beta2
apisix.apache.org/v2beta3
apm.k8s.elastic.co/v1
apm.k8s.elastic.co/v1beta1
app.k8s.io/v1beta1
application.kubesphere.io/v1alpha1
apps/v1
.......

然后用下面命令查看这个apigroup的资源列表,里面会包含所有子资源

具体api地址可以用这个GET /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE,注意核心api组的api路径是/api,其他api组都是apis开头

代码语言:bash
复制
[root@VM-0-2-centos ~]# kubectl proxy &
[root@VM-0-2-centos ~]# curl http://localhost:8001/api/v1/ | jq .resources[].name
"bindings"
"componentstatuses"
"configmaps"
"endpoints"
"events"
"limitranges"
"namespaces"
"namespaces/finalize"
"namespaces/status"
"nodes"
"nodes/proxy"
"nodes/status"
"persistentvolumeclaims"
"persistentvolumeclaims/status"
"persistentvolumes"
"persistentvolumes/status"
"pods"
"pods/attach"
"pods/binding"
"pods/eviction"
"pods/exec"
"pods/log"
"pods/portforward"
"pods/proxy"
"pods/restart"
"pods/status"
"podtemplates"
"replicationcontrollers"
"replicationcontrollers/scale"
"replicationcontrollers/status"
"resourcequotas"
"resourcequotas/status"
"secrets"
"serviceaccounts"
"services"
"services/proxy"
"services/status"

[root@VM-0-2-centos ~]# curl http://localhost:8001/apis/apps/v1 | jq .resources[].name
"controllerrevisions"
"daemonsets"
"daemonsets/status"
"deployments"
"deployments/scale"
"deployments/status"
"replicasets"
"replicasets/scale"
"replicasets/status"
"statefulsets"
"statefulsets/scale"
"statefulsets/status"

上面的资源列表中,/后面的部分就是代表资源所有的子资源类型。比如statefulsets/status,指的是statefulsets的status子资源。

verbs

verbs字段的含义是指你能对资源做哪些操作,verbs存在以下几个操作:

  • delete
  • deletecollection
  • get
  • list
  • patch
  • create
  • update
  • watch

这些字段的定义在k8s的源码中也有定义,具体代码如下

代码语言:bash
复制
# kubernetes/staging/src/k8s.io/code-generator/cmd/client-gen/generators/util/tags.go

var SupportedVerbs = []string{
	"create",
	"update",
	"updateStatus",
	"delete",
	"deleteCollection",
	"get",
	"list",
	"watch",
	"patch",
	"apply",
	"applyStatus",
}

源码里面也有具体定义不同类型操作有哪些

代码语言:bash
复制
// ReadonlyVerbs represents a list of read-only verbs.
var ReadonlyVerbs = []string{
	"get",
	"list",
	"watch",
}

// unsupportedExtensionVerbs is a list of verbs we don't support generating
// extension client functions for.
var unsupportedExtensionVerbs = []string{
	"updateStatus",
	"deleteCollection",
	"watch",
	"delete",
}

// inputTypeSupportedVerbs is a list of verb types that supports overriding the
// input argument type.
var inputTypeSupportedVerbs = []string{
	"create",
	"update",
	"apply",
}

// resultTypeSupportedVerbs is a list of verb types that supports overriding the
// resulting type.
var resultTypeSupportedVerbs = []string{
	"create",
	"update",
	"get",
	"list",
	"patch",
	"apply",
}

如果你只希望子账号能查看资源,则只需要赋予查看的动作即可

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups:
  - 'apps'
  resources:
  - 'Deployment'
  - 'statefulsets'
  - 'daemonsets'
  verbs:
  - 'get'
  - 'list'
  - 'watch'

上面的示例说明只能查看基本控制器的资源,无法更新或者新建。

上面我们编写yaml,每个字段都是通过list的信息编写,其实还有另外一种写法,可以用中括号代表list,具体编写如下

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups: ["apps"]
  resources: ["Deployment", "statefulsets", "daemonsets"]
  verbs: ["get", "ist", "watch"]

其实除了编写yaml的方式创建role或者clusterrole,还可以通过命令创建

代码语言:bash
复制
kubectl create clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]

kubectl create clusterrole test2 --verb=list --resource=statefulsets

这里创建一个clusterrole,只给statefulsets的list权限,如果没有具体的statefulsets是哪个,resource-name字段可以忽略,apiGroup可以不要写,这里会自动匹配资源对应的apiGroup。

赋予子账号权限

上面我们已经说了如何编写role或者clusterrole,但是这里只是定义了角色有什么样的权限,实际上还没有给到具体的子账号,如果想让权限在子账号生效,那么还需要依赖于rolebinding和clusterrolebinding,因为这2个会实际将角色绑定到对应子账号上。

在k8s中,账号其实分为2种,Kubernetes管理的服务账号和普通用户

  • 服务账号:集群中的ServiceAccount(简称sa)
  • 普通用户:云厂商的用户

k8s的每个命名空间默认有一个default的sa,这个sa只有本命名空间的资源访问权限,如果你在工作负载没有指定特定的sa,就会默认绑定default。

这里我们会经常遇到一个问题,就是在a命名空间下创建了一个pod,但是pod内的进程需要访问集群的其他命名空间资源,会提示没权限,这是因为pod使用的默认default这个sa导致的,解决这个问题,可以将default绑定更高权限的clusterrole或者给pod绑定自定义有权限的sa。

普通用户一般就是云厂商的账号了,现在云厂商都将自己的cam鉴权和集群rbac进行了整合,云厂商的账号也就都接入了k8s,一般只需要给云上账号绑定role或者clusterrole,就能对云上账号进行权限限制。

如何给服务账号绑定权限,可以通过kubectl命令来绑定

代码语言:bash
复制
# 名为 view 的 ClusterRole 中定义的权限授予 "acme" 名字空间中 名为 "myapp" 的服务账户

kubectl create clusterrolebinding myapp-view-binding --clusterrole=view --serviceaccount=acme:myapp

给普通用户绑定用户,一般云厂商都有自己的可视化界面或者教程,可以参考具体的教程,这里我们以腾讯云的tke举例。

通常步骤是获取子账号的name,然后控制台或者yaml创建ClusterRoleBinding

代码语言:yaml
复制
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: 1000060xxxxx-ClusterRole
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: tke:admin
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: 1000060xxxxx-1606467779

yaml可以参考上面实例,tke中name的获取可以通过接口DescribeClusterCommonNames,具体参考文档https://cloud.tencent.com/document/api/457/55721

命令绑定的方式如下

代码语言:bash
复制
kubectl create clusterrolebinding 1000xxxxxx-ClusterRole --clusterrole=test2 --user=1000xxxxx-1612101921

这里需要注意的是rolebinding和clusterrolebinding都是不支持修改的,如果你想重新给用户绑定权限,需要删除之前旧的rolebinding或clusterrolebinding,然后再新建一个,想腾讯云上控制台支持更新权限操作,后端的逻辑也是先删除旧的,再新建新的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一文带你搞定k8s的rbac鉴权
    • 概念介绍
    • clusterrole字段说明
      • apiGroups
      • resources
      • verbs
    • 赋予子账号权限
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档