RBAC 是 Kubernetes 内置的授权机制,但很多集群的 RBAC 配置其实相当粗糙:要么把服务账号直接绑到 cluster-admin,要么干脆复制粘贴一段宽泛的 Role 定义。最小化权限原则要求每个主体只拥有完成其工作所必需的权限,不多一分。这篇文章围绕 Role、ClusterRole、RoleBinding、ClusterRoleBinding 四个核心对象,讲清楚如何一步步收敛权限边界。

一、先理解 RBAC 的四个对象与授权模型
Kubernetes 的 RBAC 模型由四类资源组成。Role 定义一组规则,描述可以對哪些资源执行哪些操作,作用范围限于某个命名空间;ClusterRole 与之类似,但作用域是整个集群,既能授予集群级资源(如 Node、PersistentVolume、Namespace)的访问能力,也能通过 RoleBinding 被绑定到某个命名空间内生效。
绑定关系由 RoleBinding 和 ClusterRoleBinding 承担。RoleBinding 把角色授予主体,主体可以是 User、Group 或 ServiceAccount,绑定后在指定命名空间内生效;ClusterRoleBinding 则让角色在全集群所有命名空间生效。一个常见误区是认为 ClusterRole 一定意味着集群级权限,实际上 ClusterRole 通过 RoleBinding 绑定时,权限会被限制在那一个命名空间里,这正是官方推荐的做法之一,可以让同一份角色定义在多个命名空间复用。
每条规则由 verbs、resources、apiGroups 三个维度组成。verbs 决定能执行的动作,如 get、list、watch、create、update、patch、delete;resources 决定作用的资源类型;apiGroups 指定 API 组。最小化权限的本质,就是在每个维度上都做精确裁剪,能用 get 就不给 list,能限制在单个资源就不放开整个资源类型。
二、如何裁剪出一套最小权限规则
裁剪权限的思路是先问一个问题:这个主体到底要访问哪些资源、执行哪些动作?以一个只需要读取配置的 CI 服务为例,它通常只需要 get、list、watch 三个动作,作用在 ConfigMap 和 Secret 上。下面是一个按需收敛后的 Role 定义:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: ci-config-reader namespace: build rules: - apiGroups: [""] resources: ["configmaps", "secrets"] verbs: ["get", "list", "watch"] resourceNames: ["ci-runner-config", "registry-auth"]
注意 resourceNames 字段,这是最容易被忽略的收敛手段。加上它之后,权限只对指定的两个资源对象生效,而不是该命名空间下所有的 ConfigMap 和 Secret。如果这个 CI 服务还需要监听 Pod 状态来上报构建结果,可以再追加一条规则,而不是直接放开 pods 的全部动作:
- apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["pods/log"] verbs: ["get"]
另一个常见需求是让某个控制器创建 Job。这时需要评估的不只是 job 资源本身,可能还包括创建 Pod 的权限、读取 ConfigMap 的权限,以及 watch 自己创建的 Job 状态。建议先用宽松角色在测试环境跑通,再通过审计日志反向提取实际用到的 verbs,逐步收敛。Kubectl 自带的 kubectl auth can-i --list --as=system:serviceaccount:build:ci-sa 命令可以列出某服务账号当前拥有的全部权限,是做收敛前后对照的好工具。
三、排查权限过大与权限不足
权限不足时排查相对简单,API Server 会明确返回 Forbidden,错误信息里包含被拒绝的用户、资源和动作。例如日志中出现 cannot list resource "secrets",说明缺少对应的 list 权限,补齐即可。比较麻烦的是权限过大,因为它不会报错,只会默默埋下隐患。
排查权限过大可以借助几个命令。先用 kubectl get clusterrolebindings -o yaml 检查是否有主体绑定了 cluster-admin 或 system: 开头的超级角色;再用 kubectl auth can-i --list 逐个检查应用账号。如果输出里出现了 secrets 的 get 权限但应用根本不需要读取 Secret,就应该移除。还可以开启 API Server 的审计日志,统计一段周期内每个主体实际调用的资源和方法,与声明的 RBAC 规则做差集,未被使用的权限就是裁剪对象。
有一个实践细节值得注意:尽量避免使用通配符。规则中 verbs 写成 ["*"] 或 resources 写成 ["*"] 会彻底失去控制边界,后续审计也无法判断风险范围。对于确实需要较大权限的平台组件,推荐使用聚合角色(aggregation 角色),通过 label 选择器组合多个 ClusterRole,每个子角色保持单一职责,比一个大而全的定义更容易维护和审查。
四、几条值得坚持的落地规范
第一,每个应用使用独立的 ServiceAccount,不要复用 default 账号,也不要多个应用共享一个账号。账号独立才能做到权限独立,出问题时也能快速定位责任主体。
第二,坚持命名空间级别的 RoleBinding 优先。只有在确实需要跨命名空间或访问集群级资源时才使用 ClusterRoleBinding,并且每次创建都要走评审。集群级绑定的影响面是全集群的,误配一个 ClusterRoleBinding 到宽泛角色上,等于把整个集群暴露给该主体。
第三,把 RBAC 定义纳入 Git 管理,通过 GitOps 流程下发。这样权限变更有记录、可回滚,也便于在代码评审环节发现权限过大的提交。配合 admission webhook 拒绝包含通配符或绑定 cluster-admin 的变更,可以把最小权限原则固化为系统约束,而不是依赖人的自觉。
Kubernetes RBAC最小权限原则ClusterRole修改时间:2026-09-08 20:56:56