摘要:理解 Role、ClusterRole、RoleBinding 与 ClusterRoleBinding 的作用域和绑定关系,配置最小权限规则并使用 kubectl auth can-i 排查授权。
1. RBAC 的整体架构
RBAC 的四个核心对象:
| 对象 | 类型 | 主要作用 |
|---|---|---|
| Role | Namespace 级别 | 定义命名空间内的权限 |
| RoleBinding | Namespace 级别 | 将角色绑定给用户或其他主体 |
| ClusterRole | 集群级别定义 | 定义集群级权限或可复用权限 |
| ClusterRoleBinding | 集群级别 | 将 ClusterRole 授予主体 |
它们之间的关系:
flowchart TB
S["Subjects<br/>User / Group / ServiceAccount"]
B["RoleBinding<br/>Namespace 范围"]
C["ClusterRoleBinding<br/>集群范围"]
R["Role<br/>命名空间权限规则"]
CR["ClusterRole<br/>集群级或可复用规则"]
S -->|"作为 subjects"| B
S -->|"作为 subjects"| C
B -->|"roleRef:同 Namespace 的 Role"| R
B -->|"roleRef:可复用 ClusterRole"| CR
C -->|"roleRef:仅能引用 ClusterRole"| CR
需要特别注意:
RBAC 的核心逻辑是:
flowchart LR
S["主体 Subject"] --> B["绑定 Binding"] --> R["角色 Role"] --> P["权限规则 Rules"]
其中,Role 和 ClusterRole 定义权限,Binding 决定谁能够使用这些权限。
2. Role:命名空间权限规则
2.1 Role 的作用范围
Role 是 Namespace 级别的权限定义对象。
例如:
开发人员只需要管理 dev Namespace 中的 Pod,不应该拥有其他 Namespace 的权限。
可以创建一个 Role:
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-manager namespace: devrules: - apiGroups: [""] resources: - pods verbs: - get - list - watch - create - delete这段配置表示:
在 dev Namespace 中,允许主体对 Pod 执行:
- 查询单个 Pod。
- 列出 Pod。
- 监听 Pod 变化。
- 创建 Pod。
- 删除 Pod。
但是不能更新 Pod,因为没有授予 update 或 patch 权限。
2.2 apiGroups:资源所属 API 组
Kubernetes API 并不是所有资源都属于同一个 API 组。
可以通过以下命令查看:
kubectl api-resources输出示例:
NAME SHORTNAMES APIVERSIONpods po v1services svc v1deployments deploy apps/v1jobs batch/v1ingresses ing networking.k8s.io/v1注意,APIVERSION 和 RBAC 中的 apiGroups 并不完全相同。
例如:
| 资源 | APIVERSION | apiGroups |
|---|---|---|
| Pod | v1 | "" |
| Service | v1 | "" |
| Deployment | apps/v1 | apps |
| Job | batch/v1 | batch |
| Ingress | networking.k8s.io/v1 | networking.k8s.io |
| Role | rbac.authorization.k8s.io/v1 | rbac.authorization.k8s.io |
注意:核心 API 组使用空字符串,而不是 core。
因此,允许用户查看 Deployment:
rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch"]允许用户查看 Job:
rules: - apiGroups: ["batch"] resources: ["jobs"] verbs: ["get", "list", "watch"]一个 Role 可以包含多条 rules:
rules: - apiGroups: [""] resources: ["pods", "services"] verbs: ["get", "list", "watch"]
- apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch"]
- apiGroups: ["batch"] resources: ["jobs"] verbs: ["get", "list", "watch"]这样就可以在一个角色中定义多组不同 API 资源的访问权限。
2.3 resources:资源与子资源
resources 指定允许操作的 Kubernetes 资源。
例如:
resources: - pods - services - configmaps - secrets这里有一个重要知识点:Kubernetes 的子资源(Subresources)。
例如 Pod 不仅有自身资源,还有:
- pods/log
- pods/exec
- pods/status
- pods/portforward
它们代表不同的 API 操作入口。
假设用户只允许查看 Pod 日志:
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: pod-log-reader namespace: devrules: - apiGroups: [""] resources: ["pods/log"] verbs: ["get"]这个权限只允许读取 Pod 日志,并不自动授予读取 Pod 对象本身的权限。
如果还需要查询 Pod 信息,就要另外授权:
rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list"]
- apiGroups: [""] resources: ["pods/log"] verbs: ["get"]2.4 verbs:允许的操作
RBAC 常见 verbs:
| Verb | 含义 |
|---|---|
| get | 获取单个资源 |
| list | 列出资源集合 |
| watch | 监听资源变化 |
| create | 创建资源 |
| update | 更新整个资源 |
| patch | 部分更新资源 |
| delete | 删除资源 |
| deletecollection | 批量删除资源 |
注意几个容易混淆的地方:
get 和 list 不一样。
kubectl get pod nginx -n dev主要涉及 get 权限。
kubectl get pods -n dev主要涉及 list 权限。
update 和 patch 不一样。
- update:提交完整资源对象进行更新。
- patch:只修改资源的一部分。
如果希望用户既能更新也能部分修改 Deployment:
verbs: ["get", "list", "watch", "update", "patch"]不要为了方便直接使用:
verbs: ["*"]因为这会扩大权限范围。
3. ClusterRole:集群级与可复用规则
3.1 ClusterRole 与 Role 的区别
ClusterRole 与 Role 最大的区别是权限定义的适用范围。
Role 只能定义 Namespace 范围的资源权限。
ClusterRole 除了能够定义 Namespace 资源的权限,还能定义集群级资源的权限。
例如:
| 资源 | 资源类型 | 是否属于 Namespace |
|---|---|---|
| Pod | Namespaced | 是 |
| Service | Namespaced | 是 |
| Deployment | Namespaced | 是 |
| Secret | Namespaced | 是 |
| Node | Cluster-scoped | 否 |
| Namespace | Cluster-scoped | 否 |
| PersistentVolume | Cluster-scoped | 否 |
| StorageClass | Cluster-scoped | 否 |
查看资源作用范围:
kubectl api-resources重点看:
NAMESPACEDtrue 表示属于 Namespace,false 表示属于集群级别。
3.2 创建 ClusterRole
例如,我们希望创建一个集群监控角色,可以查看:
- Node
- Namespace
- PersistentVolume
配置:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: cluster-observerrules: - apiGroups: [""] resources: - nodes - namespaces - persistentvolumes verbs: - get - list - watch这个 ClusterRole 定义了集群级资源的只读权限。
注意:
ClusterRole 也可以定义 Pod、Service、Deployment 等 Namespace 资源的权限。
它并不意味着其中所有权限都一定是集群级别的,真正的使用范围还取决于 Binding 的类型。
4. RoleBinding 与 ClusterRoleBinding:角色绑定
前面已经知道 Role 和 ClusterRole 负责定义权限。
但是,定义了权限并不代表用户已经获得权限。
必须通过 Binding 将角色与主体关联起来。
4.1 RoleBinding
RoleBinding 的作用是:
将 Role 或 ClusterRole 授予某个用户、用户组或 ServiceAccount,但授权范围仅限于 RoleBinding 所在的 Namespace。
例如,将前面创建的 pod-manager 授予 Alice:
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: alice-pod-manager namespace: devsubjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.ioroleRef: kind: Role name: pod-manager apiGroup: rbac.authorization.k8s.io其中有两个关键字段。
subjects:授权对象
可以是三种类型:
subjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.io
- kind: Group name: developers apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount name: dev-sa namespace: dev注意:
- User:不需要填写 Namespace。
- Group:不需要填写 Namespace。
- ServiceAccount:必须指定 Namespace。
roleRef:引用的角色
roleRef: kind: Role name: pod-manager apiGroup: rbac.authorization.k8s.io这里引用的是 dev Namespace 中的 Role。
roleRef 一旦创建,不能直接修改其引用对象。需要更换角色时,通常删除并重新创建 Binding。
4.2 ClusterRoleBinding
ClusterRoleBinding 的作用是:
将 ClusterRole 授予某个主体,使其在整个集群范围内获得对应权限。
例如,允许 Alice 查看集群所有 Namespace 中的 Pod:
ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: pod-viewerrules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]ClusterRoleBinding:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata: name: alice-pod-viewersubjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole name: pod-viewer apiGroup: rbac.authorization.k8s.io这样 Alice 就可以查看所有 Namespace 中的 Pod。
4.3 最容易混淆的地方:ClusterRole + RoleBinding
这是 RBAC 中一个非常重要的知识点。
RoleBinding 不仅可以引用 Role,也可以引用 ClusterRole。
例如:
apiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: alice-pod-viewer namespace: devsubjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.ioroleRef: kind: ClusterRole name: pod-viewer apiGroup: rbac.authorization.k8s.io这里使用了:
- ClusterRole:定义权限。
- RoleBinding:限制授权范围。
结果是 Alice 只能在 dev Namespace 中查看 Pod。
用一张表总结:
| 组合 | 授权范围 |
|---|---|
| Role + RoleBinding | RoleBinding 所在 Namespace |
| ClusterRole + RoleBinding | RoleBinding 所在 Namespace |
| ClusterRole + ClusterRoleBinding | 整个集群 |
重点理解:角色定义与权限生效范围是两个维度。
flowchart LR
B["RoleBinding"] --> N["只能在绑定所在 Namespace 授权"]
C["ClusterRoleBinding"] --> G["在整个集群范围授权"]
RoleBinding 引用 ClusterRole 时,只授予该 Namespace 内的资源权限,不会授予 Node 等集群级资源的访问权限。
ClusterRole 可以复用权限规则,再通过不同的 RoleBinding 实现不同 Namespace 的权限隔离。
5. RBAC 的主体:User、Group、ServiceAccount
RBAC 不直接管理用户账户,而是根据认证阶段提供的身份信息进行授权。
5.1 User:普通用户
例如:
subjects: - kind: User name: alice apiGroup: rbac.authorization.k8s.io这里的 Alice 通常来自客户端证书的 CN 字段,或者 OIDC 等外部身份认证系统。
Kubernetes 不会因为你创建了一个叫 Alice 的 RoleBinding,就自动创建 Alice 这个用户。
5.2 Group:用户组
假设有一个开发团队:
flowchart TB
G["developers 用户组"] -->|"成员"| A["alice"]
G -->|"成员"| B["bob"]
G -->|"成员"| C["charlie"]
如果逐个授权:
subjects: - kind: User name: alice - kind: User name: bob - kind: User name: charlie会比较麻烦。
可以直接给 Group 授权:
subjects: - kind: Group name: developers apiGroup: rbac.authorization.k8s.io只要认证系统能够将这些用户识别为 developers 组成员,他们就可以继承该组对应的权限。
Kubernetes 常见的内置用户组包括:
| Group | 含义 |
|---|---|
| system | 已通过认证的用户 |
| system | 未认证请求 |
| system | 所有 ServiceAccount |
| system:serviceaccounts | dev Namespace 中的 ServiceAccount |
| system | 具有特殊集群管理权限的组 |
特别注意:
system:masters 是具有特殊权限含义的内置组,不能将它当作普通开发组使用。
5.3 ServiceAccount:应用程序身份
例如:
subjects: - kind: ServiceAccount name: prometheus namespace: monitoringServiceAccount 的完整身份格式:
system:serviceaccount:<namespace>:<name>例如:
system:serviceaccount:monitoring:prometheus它在 RBAC 中可以直接被授权,不需要创建普通 User。
5.4 一个主体可以同时拥有多个角色
假设 Alice 同时属于:
developerstesters那么她可能同时获得:
- developers 组的 Pod 创建权限。
- testers 组的 Pod 查看权限。
- 个人账户的日志查看权限。
RBAC 的权限是累加的。
也就是说:
多个 RoleBinding 和 ClusterRoleBinding 授予的权限会合并,而不是互相覆盖。
这意味着不能通过创建一个权限较低的 RoleBinding 来抵消另一个 Binding 已经授予的权限。
Kubernetes RBAC 本身没有显式的 Deny 规则。
6. RBAC 高级功能
这一部分开始进入更深入的权限控制。
6.1 通配符权限
RBAC 支持使用 * 通配符。
例如:
rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"]表示:
- 所有 API 组。
- 所有资源。
- 所有操作。
这类权限非常大,生产环境中应谨慎使用。
例如:
rules: - apiGroups: [""] resources: ["pods", "services"] verbs: ["get", "list", "watch"]比直接使用通配符更安全。
6.2 resourceNames:限制具体资源名称
假设一个用户只允许读取名为 app-config 的 ConfigMap,而不能读取其他 ConfigMap。
可以使用 resourceNames:
apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: config-reader namespace: devrules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["app-config"] verbs: ["get", "list", "watch"]这样就限制了允许访问的资源名称。
但需要注意一个重要限制:
如果希望限制 list 或 watch,请求通常还需要携带对应的 metadata.name 字段选择器,否则无法按预期获得授权。
例如:
kubectl get configmaps \ --field-selector metadata.name=app-config \ -n dev因此,不能简单认为配置了 resourceNames 就可以正常执行所有形式的 list 和 watch。
6.3 Role Aggregation:角色聚合
这是 ClusterRole 的一个高级特性。
假设一个集群中有多个角色:
- 查看 Pod 的角色。
- 查看 Deployment 的角色。
- 查看 Service 的角色。
如果每次都需要将它们分别绑定给用户,会比较麻烦。
Kubernetes 支持通过 aggregationRule 将多个 ClusterRole 聚合为一个 ClusterRole。
例如:
先创建 Pod 查看角色:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: pod-reader-custom labels: app: monitoringrules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]再创建 Deployment 查看角色:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: deployment-reader-custom labels: app: monitoringrules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch"]创建聚合角色:
apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: monitoring-readeraggregationRule: clusterRoleSelectors: - matchLabels: app: monitoringrules: []Kubernetes 的 ClusterRole Aggregation Controller 会根据标签选择器,将符合条件的 ClusterRole 权限聚合到 monitoring-reader 中。
查看:
kubectl describe clusterrole monitoring-reader原理:
flowchart TB
S["aggregationRule<br/>标签选择器 app: monitoring"]
P["pod-reader-custom<br/>读取 Pod"]
D["deployment-reader-custom<br/>读取 Deployment"]
M["monitoring-reader<br/>聚合角色"]
S -->|"匹配标签"| P
S -->|"匹配标签"| D
P -->|"控制器聚合权限"| M
D -->|"控制器聚合权限"| M
实际使用中,聚合角色的 rules 由控制器管理,不建议手动维护聚合后的规则。
Kubernetes 内置的 view、edit、admin 等 ClusterRole 也使用了角色聚合机制。
6.4 内置 ClusterRole
查看 Kubernetes 内置角色:
kubectl get clusterroles其中几个重要角色:
| ClusterRole | 作用 |
|---|---|
| cluster-admin | 集群管理员,拥有极高权限 |
| admin | Namespace 管理员 |
| edit | Namespace 内资源编辑权限 |
| view | Namespace 内资源只读权限 |
例如,将 view 角色授予某个用户:
kubectl create rolebinding alice-view \ --clusterrole=view \ --user=alice \ -n dev这里虽然引用的是 ClusterRole,但使用的是 RoleBinding。
因此 Alice 只能在 dev Namespace 使用 view 权限。
7. RBAC 的安全边界与权限提升风险
在生产环境中,RBAC 不仅要解决用户能做什么,还要防止用户通过间接方式获得更高权限。
7.1 为什么不能随便授予 edit?
Kubernetes 内置的 edit 角色允许用户在 Namespace 中管理大量资源。
但是,它并不等于只允许修改业务应用。
例如,用户可能具有创建 Pod 的权限。
如果这个用户能够创建任意 Pod,就可能创建一个挂载敏感 Secret 或使用高权限 ServiceAccount 的 Pod。
因此:
允许创建 Pod,不一定意味着用户只能操作普通业务资源。
例如:
spec: serviceAccountName: privileged-sa如果 privileged-sa 拥有读取 Secret 或管理 Deployment 的权限,那么能够使用它创建 Pod 的用户,可能间接获得这些权限。
这也是为什么生产环境需要结合以下机制:
- RBAC:限制 API 操作。
- Admission Control:限制不安全的资源配置。
- Pod Security Admission:限制 Pod 的安全配置。
- NetworkPolicy:限制网络通信。
- Secret 管理:保护敏感凭据。
7.2 RBAC 权限提升保护
Kubernetes 对 Role 和 ClusterRole 的创建、修改有特殊保护。
例如,普通用户不能随意创建一个比自己权限更大的角色,再把这个角色绑定给自己。
相关特殊权限:
| 权限 | 作用 |
|---|---|
| escalate | 允许创建或更新超出自身权限的 Role/ClusterRole |
| bind | 允许绑定自身无权使用的 Role/ClusterRole |
| impersonate | 允许模拟其他用户、用户组或 ServiceAccount |
例如:
rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"]这类授权具有较高风险。
另外,能够管理 RoleBinding 的用户也可能改变其他主体的权限,所以必须谨慎授权。
7.3 Impersonation:身份模拟
在 Kubernetes 中,管理员可以模拟其他用户,测试其权限。
例如:
kubectl auth can-i get pods --as=alice -n dev这里的 --as=alice 就涉及用户模拟。
如果想直接以模拟身份执行命令:
kubectl get pods \ -n dev \ --as=alice如果模拟用户组:
kubectl get pods \ -n dev \ --as=alice \ --as-group=developers注意:
执行身份模拟需要当前认证身份具有相应的 impersonate 权限。
8. RBAC 权限排查方法
实际生产中,经常会遇到:
Error from server (Forbidden):pods is forbidden:User "alice" cannot list resource "pods"in API group "" in the namespace "dev"遇到这种错误,不要马上修改 YAML。
应该先判断到底是哪一层出了问题。
8.1 第一步:确认当前身份
kubectl auth whoami查看当前 kubeconfig:
kubectl config current-contextkubectl config view8.2 第二步:检查权限
kubectl auth can-i list pods -n dev模拟 Alice:
kubectl auth can-i list pods \ --as=alice \ -n dev如果返回:
no说明当前授权配置没有允许该请求。
8.3 第三步:查看 Role
kubectl get role -n devkubectl describe role pod-manager -n dev重点检查:
- apiGroups 是否正确。
- resources 是否正确。
- verbs 是否包含当前操作。
- Role 是否位于正确 Namespace。
8.4 第四步:查看 RoleBinding
kubectl get rolebinding -n devkubectl describe rolebinding alice-pod-manager -n dev重点检查:
- subjects 是否正确。
- User、Group、ServiceAccount 类型是否正确。
- ServiceAccount Namespace 是否正确。
- roleRef 是否指向正确的角色。
8.5 第五步:检查是否存在其他授权
kubectl get clusterrolebindingskubectl get rolebindings -A因为 RBAC 权限是累加的,所以必须检查该主体是否通过其他绑定获得了额外权限。
8.6 一个常见排查误区
假设:
kubectl auth can-i get pods \ --as=alice \ -n dev返回:
yes但 Alice 实际访问仍然返回:
403 Forbidden这时需要检查:
- Alice 实际请求是否使用了预期身份。
- 请求的 Namespace 是否一致。
- 实际操作是
get还是list。 - 实际资源是否是
pods或pods/log。 - 请求是否访问了不同 API 组或子资源。
- 是否存在其他授权机制,例如 Webhook 或外部身份系统问题。
kubectl auth can-i 是非常有用的排查工具,但不能代替对真实请求上下文的检查。
9. RBAC 常用命令
9.1 创建 Role
kubectl create role pod-reader \ --verb=get,list,watch \ --resource=pods \ -n dev创建多个资源的权限:
kubectl create role app-reader \ --verb=get,list,watch \ --resource=pods,services,configmaps \ -n dev9.2 创建 RoleBinding
绑定 User:
kubectl create rolebinding alice-reader \ --role=pod-reader \ --user=alice \ -n dev绑定 Group:
kubectl create rolebinding dev-reader \ --role=pod-reader \ --group=developers \ -n dev绑定 ServiceAccount:
kubectl create rolebinding sa-reader \ --role=pod-reader \ --serviceaccount=dev:dev-sa \ -n dev9.3 创建 ClusterRole
kubectl create clusterrole node-reader \ --verb=get,list,watch \ --resource=nodes9.4 创建 ClusterRoleBinding
kubectl create clusterrolebinding alice-node-reader \ --clusterrole=node-reader \ --user=alice9.5 使用 ClusterRole 授予 Namespace 权限
kubectl create rolebinding alice-view \ --clusterrole=view \ --user=alice \ -n dev9.6 查看权限
kubectl auth can-i get pods --as=alice -n dev
kubectl auth can-i delete pods --as=alice -n dev
kubectl auth can-i --list --as=alice -n dev9.7 查看 RBAC 对象
kubectl get roles -A
kubectl get rolebindings -A
kubectl get clusterroles
kubectl get clusterrolebindings