RBAC 权限控制流程
概述
RBAC (Role-Based Access Control) 是 Kubernetes 默认的授权模式,通过 Role 和 RoleBinding 来控制用户对资源的访问权限。
核心概念
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
| ┌─────────────────────────────────────────────────────────────────────────────┐ │ Role (角色) │ │ 定义一组权限规则 (PolicyRules),包含 verbs、resources、apiGroups │ │ pkg/apis/rbac/types.go │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ 绑定 ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ RoleBinding (角色绑定) │ │ 将 Role 绑定到 Subject (User/Group/ServiceAccount) │ │ 作用域: Namespace 内 │ └─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐ │ ClusterRole (集群角色) │ │ 集群级别的 Role,可访问集群范围资源 │ │ 可被 RoleBinding 引用 (跨命名空间授权) │ └─────────────────────────────────────────────────────────────────────────────┘ │ │ 绑定 ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ ClusterRoleBinding (集群角色绑定) │ │ 将 ClusterRole 绑定到 Subject,集群范围生效 │ └─────────────────────────────────────────────────────────────────────────────┘
|
核心数据结构
Role/ClusterRole
1 2 3 4 5 6 7 8 9 10 11 12
| type PolicyRule struct { Verbs []string APIGroups []string Resources []string ResourceNames []string NonResourceURLs []string }
type Role struct { Rules []PolicyRule }
|
RoleBinding
1 2 3 4 5 6 7 8 9 10
| type RoleBinding struct { Subjects []Subject RoleRef RoleRef }
type Subject struct { Kind string Name string Namespace string }
|
授权检查流程
主入口
- 文件:
plugin/pkg/auth/authorizer/rbac/rbac.go
- 函数:
RBACAuthorizer.Authorize()
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
| ┌──────────────────────────────────────────────────────────────────────────────┐ │ 授权请求 │ │ RBACAuthorizer.Authorize(ctx, attributes) │ └──────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────────────────┐ │ 遍历用户的权限规则 │ │ authorizationRuleResolver.VisitRulesFor(user, namespace, visitor) │ └──────────────────────────────────────────────────────────────────────────────┘ │ ▼ ┌──────────────────────────────────────────────────────────────────────────────┐ │ 检查规则是否匹配 │ │ RuleAllows(requestAttributes, rule) │ │ - 匹配 Verb │ │ - 匹配 APIGroup │ │ - 匹配 Resource │ │ - 匹配 ResourceName (如果指定) │ │ - 匹配 NonResourceURL (非资源请求) │ └──────────────────────────────────────────────────────────────────────────────┘ │ ┌───────────────┴───────────────┐ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────┐ │ 允许访问 │ │ 拒绝访问 │ │ DecisionAllow │ │ DecisionDeny │ └──────────────┘ └──────────────┘
|
规则解析器
- 文件:
pkg/registry/rbac/rest/mapping.go
- 作用: 解析用户绑定的所有 Role 和 ClusterRole
1 2 3 4 5 6 7 8 9 10 11 12 13
| 1. 获取用户信息 (User.Info) ├── 用户名 (GetName) ├── 用户组 (GetGroups) └── 额外信息 (GetExtra)
2. 查找绑定的 Role ├── RoleBindings (命名空间内) │ └── 匹配 Subject -> 获取 Role └── ClusterRoleBindings (集群范围) └── 匹配 Subject -> 获取 ClusterRole
3. 合并所有 PolicyRules └── 返回规则列表供授权检查
|
关键代码路径
1. RBAC 授权器
- 文件:
plugin/pkg/auth/authorizer/rbac/rbac.go
- 核心函数:
Authorize() - 授权检查入口 (第 75 行)
RuleAllows() - 规则匹配检查
2. 规则解析
- 文件:
pkg/registry/rbac/rest/mapping.go
- 接口:
RequestToRuleMapper
- 方法:
RulesFor() - 获取用户所有规则
VisitRulesFor() - 遍历用户规则
3. 规则匹配
- 文件:
pkg/apis/rbac/validation/rule.go
- 函数:
Covers() - 检查规则覆盖范围
4. Subject 匹配
- 文件:
pkg/registry/rbac/rest/mapping.go
- 函数:
subjectsMatch() - 检查用户是否匹配 Subject
权限检查示例
示例 1: 用户获取 Pod
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| User: "alice" Verb: "get" Resource: "pods" APIGroup: "" Namespace: "default" Name: "my-pod"
1. 查找 alice 的所有 RoleBinding 2. 获取对应的 Role/ClusterRole 3. 遍历 PolicyRules: - Rule: verbs=["get"], resources=["pods"], apiGroups=[""] - 匹配成功 ✓
|
示例 2: ServiceAccount 创建 Secret
1 2 3 4 5 6 7 8 9 10 11 12 13
| User: "system:serviceaccount:my-ns:my-sa" Verb: "create" Resource: "secrets" APIGroup: "" Namespace: "my-ns"
1. 查找 ServiceAccount 的 RoleBinding 2. 获取 Role 3. 遍历 PolicyRules: - Rule: verbs=["create"], resources=["secrets"] - 匹配成功 ✓
|
权限聚合规则
1. 多个 RoleBinding 聚合
用户的所有 RoleBinding 和 ClusterRoleBinding 的权限会累加:
- 有 get 权限 + 有 create 权限 = 有 get 和 create 权限
2. ClusterRole 的命名空间降级
ClusterRole 可以被 RoleBinding 引用,此时权限被限制在命名空间内:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| rules: - verbs: ["get"] resources: ["secrets"]
roleRef: kind: ClusterRole name: secret-reader subjects: - kind: User name: alice
|
常见权限配置
1. 只读权限
1 2 3 4 5 6 7 8
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: view rules: - apiGroups: [""] resources: ["pods", "services", "configmaps"] verbs: ["get", "list", "watch"]
|
2. 管理员权限
1 2 3 4 5 6 7 8
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: admin rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"]
|
3. 命名空间管理员
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: namespace-admin namespace: my-ns rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: admin-binding namespace: my-ns subjects: - kind: User name: alice roleRef: kind: Role name: namespace-admin
|
调试技巧
1. 检查用户权限
1 2 3 4 5
| kubectl auth can-i get pods --as=alice -n default
kubectl auth can-i create secrets --as=system:serviceaccount:my-ns:my-sa
|
2. 查看绑定的角色
1 2 3 4 5
| kubectl get rolebinding -n my-ns -o yaml
kubectl get clusterrolebinding -o yaml
|
3. 排查权限问题
1 2 3 4 5 6
| kube-apiserver --v=5
|
性能优化
1. 规则缓存
RBAC Authorizer 会缓存规则解析结果,减少 etcd 查询:
- 文件:
staging/src/k8s.io/apiserver/pkg/authorization/cel
2. 索引优化
RoleBinding 按 Subject 建立索引:
- 文件:
pkg/registry/rbac/rest/rest.go
相关文件清单
| 文件路径 |
说明 |
plugin/pkg/auth/authorizer/rbac/rbac.go |
RBAC 授权器实现 |
pkg/apis/rbac/types.go |
RBAC API 类型定义 |
pkg/registry/rbac/rest/mapping.go |
规则解析器 |
pkg/registry/rbac/rest/rest.go |
RBAC REST API |
pkg/apis/rbac/validation/rule.go |
规则验证 |
staging/src/k8s.io/apiserver/pkg/authorization/authorizer/ |
授权器接口 |
面试题
基础题
1. RBAC 的核心概念有哪些?
参考答案:
- Role:命名空间级别的权限规则集合
- ClusterRole:集群级别的权限规则集合
- RoleBinding:将 Role 绑定到 Subject(命名空间内)
- ClusterRoleBinding:将 ClusterRole 绑定到 Subject(集群范围)
- Subject:权限绑定的目标(User、Group、ServiceAccount)
2. Role 和 ClusterRole 有什么区别?
参考答案:
| 特性 |
Role |
ClusterRole |
| 作用范围 |
单个命名空间 |
整个集群 |
| 可访问资源 |
命名空间资源 |
命名空间资源 + 集群资源 |
| 可被引用 |
RoleBinding |
RoleBinding + ClusterRoleBinding |
| 典型场景 |
命名空间内权限 |
集群管理、跨命名空间权限 |
3. Subject 有哪几种类型?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| subjects:
- kind: User name: "alice@example.com" apiGroup: rbac.authorization.k8s.io
- kind: Group name: "system:authenticated" apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount name: my-sa namespace: default
|
中级题
4. PolicyRule 的核心字段有哪些?分别说明含义。
参考答案:
1 2 3 4 5 6
| rules: - verbs: ["get", "list", "watch"] apiGroups: ["", "apps"] resources: ["pods", "deployments"] resourceNames: ["my-pod"] nonResourceURLs: ["/healthz"]
|
说明:
verbs:允许的操作(get/list/watch/create/update/delete/patch/*)
apiGroups:API 组(* 表示所有组)
resources:资源类型(* 表示所有资源)
resourceNames:限制特定资源名称
nonResourceURLs:非资源路径(如 /healthz、/metrics)
5. RoleBinding 如何引用 ClusterRole?有什么应用场景?
参考答案:
配置示例:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: read-pods namespace: development subjects: - kind: User name: dev-user roleRef: kind: ClusterRole name: pod-reader apiGroup: rbac.authorization.k8s.io
|
应用场景:
- 复用权限定义:定义一次 ClusterRole,在多个命名空间复用
- 跨命名空间授权:给用户在特定命名空间的权限
- 权限降级:将集群级权限限制在命名空间内
注意:权限仍然只在该命名空间内生效!
6. 解释 RBAC 权限的聚合规则。
参考答案:
聚合规则:用户的多个 RoleBinding 的权限会累加。
1 2 3 4 5 6 7 8 9
| - verbs: ["get", "list"] resources: ["pods"]
- verbs: ["get", "list"] resources: ["services"]
|
重要特性:
- 权限是累加的,没有”拒绝”规则
- Deny 需要通过准入控制或其他机制实现
7. ClusterRole 的聚合(Aggregation)功能是什么?
参考答案:
ClusterRole 可以聚合其他 ClusterRole 的规则:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: monitoring aggregationRule: clusterRoleSelectors: - matchLabels: rbac.example.com/aggregate-to-monitoring: "true" rules: [] --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: pods-reader labels: rbac.example.com/aggregate-to-monitoring: "true" rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]
|
应用场景:动态组合权限,系统自动聚合匹配的 ClusterRole。
高级题
8. RBAC 授权检查的完整流程是怎样的?
参考答案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 1. 提取请求属性 ├── 用户信息 (User.Info) ├── 请求动词 (Verb) ├── 资源信息 (Resource, APIGroup, Subresource) ├── 命名空间 (Namespace) └── 资源名称 (Name)
2. 遍历权限规则 ├── 获取用户的所有 RoleBinding ├── 获取对应的 Role/ClusterRole └── 遍历 PolicyRules
3. 规则匹配 ├── 检查 Verb 匹配 ├── 检查 APIGroup 匹配 ├── 检查 Resource 匹配 └── 检查 ResourceName 匹配(如果指定)
4. 返回决策 └── DecisionAllow / DecisionNoOpinion
|
关键代码:
plugin/pkg/auth/authorizer/rbac/rbac.go:75 - Authorize()
pkg/registry/rbac/rest/mapping.go - VisitRulesFor()
9. 如何实现权限的”拒绝”功能?
参考答案:
RBAC 本身不支持 Deny 规则,但可以通过以下方式实现:
1. 准入控制 Webhook:
1 2 3 4 5 6 7
| func validate(request *admission.AdmissionRequest) bool { if isDenied(request) { return false } return true }
|
2. 准入控制插件:
PodSecurity - 拒绝不安全的 Pod
ResourceQuota - 拒绝超配额请求
3. OPA/Gatekeeper:
1 2 3 4 5 6 7 8 9 10
| apiVersion: templates.gatekeeper.sh/v1 kind: ConstraintTemplate spec: crd: spec: validation: openAPIV3Schema: properties: deniedNamespaces: type: array
|
10. ServiceAccount 的 RBAC 权限是如何工作的?
参考答案:
1. ServiceAccount 创建:
1 2 3 4 5
| apiVersion: v1 kind: ServiceAccount metadata: name: my-sa namespace: default
|
2. 自动创建 Secret(Token):
1 2 3 4 5 6 7
| apiVersion: v1 kind: Secret metadata: name: my-sa-token annotations: kubernetes.io/service-account.name: my-sa type: kubernetes.io/service-account-token
|
3. 绑定权限:
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: my-sa-binding subjects: - kind: ServiceAccount name: my-sa namespace: default roleRef: kind: Role name: pod-reader
|
4. Pod 使用:
1 2 3 4 5
| spec: serviceAccountName: my-sa containers: - name: app
|
11. 解释 system:authenticated 和 system:unauthenticated 组的作用。
参考答案:
| 组 |
说明 |
典型用途 |
system:authenticated |
所有已认证用户 |
给登录用户基本权限 |
system:unauthenticated |
所有未认证用户 |
限制匿名访问 |
system:serviceaccounts |
所有 ServiceAccount |
给 SA 基本权限 |
system:serviceaccounts:<ns> |
指定命名空间的 SA |
命名空间 SA 权限 |
示例:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: discovery subjects: - kind: Group name: system:authenticated apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: system:discovery
|
12. 如何调试 RBAC 权限问题?
参考答案:
1. 使用 auth can-i 命令:
1 2 3 4 5 6 7 8
| kubectl auth can-i get pods -n default
kubectl auth can-i get pods --as=alice -n default
kubectl auth can-i get secrets --as=system:serviceaccount:default:my-sa
|
2. 查看绑定:
1 2 3 4 5
| kubectl get rolebinding,clusterrolebinding -A
kubectl describe clusterrolebinding admin-binding
|
3. 检查 apiserver 日志:
1 2 3 4 5 6
| kube-apiserver --v=5
|
4. 使用 SubjectAccessReview API:
1 2 3 4 5 6 7 8
| apiVersion: authorization.k8s.io/v1 kind: SubjectAccessReview spec: resourceAttributes: namespace: default verb: get resource: pods user: alice
|
场景题
13. 如何设计一个多租户系统的 RBAC 方案?
参考答案:
1. 角色设计:
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
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: tenant-admin rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"] - apiGroups: [""] resources: ["namespaces", "nodes"] verbs: [] ---
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: tenant-developer rules: - apiGroups: ["", "apps", "batch"] resources: ["pods", "deployments", "jobs", "configmaps", "secrets"] verbs: ["get", "list", "watch", "create", "update", "delete"] - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"]
|
2. 自动化绑定:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tenant-admin-binding namespace: tenant-a subjects: - kind: Group name: tenant-a-admins roleRef: kind: ClusterRole name: tenant-admin
|
3. 隔离策略:
- 每个租户独立命名空间
- 使用 NetworkPolicy 隔离网络
- 使用 ResourceQuota 限制资源
14. 如何实现跨命名空间的只读权限?
参考答案:
方案 1:使用 ClusterRole + 多个 RoleBinding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cross-ns-reader rules: - apiGroups: ["", "apps"] resources: ["pods", "deployments", "services"] verbs: ["get", "list", "watch"] ---
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: reader namespace: ns-a subjects: - kind: User name: alice roleRef: kind: ClusterRole name: cross-ns-reader
|
方案 2:使用 ClusterRoleBinding(谨慎使用)
1 2 3 4 5 6 7 8 9 10
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: all-namespaces-reader subjects: - kind: User name: alice roleRef: kind: ClusterRole name: view
|
15. 如何限制用户只能访问特定名称的资源?
参考答案:
使用 resourceNames 字段:
1 2 3 4 5 6 7 8 9 10
| apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: config-reader namespace: default rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["app-config", "db-config"] verbs: ["get", "list"]
|
注意事项:
- 只适用于 get、update、delete 等操作单个资源的动词
- 不适用于 list、watch、create(无法预先知道名称)
- 可以与通配符
* 组合使用
16. 如何防止权限提升(Privilege Escalation)?
参考答案:
1. Kubernetes 内置保护:
- 用户不能创建/更新比自己权限更高的 Role/RoleBinding
- 由
authorization.go 中的 allowPrivilegeEscalation 检查
2. 最佳实践:
1 2 3 4 5 6 7 8 9 10
| apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: rolebinding-creator rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["rolebindings", "clusterrolebindings"] verbs: ["create", "update", "delete"]
|
3. 审计和监控:
1 2
| kubectl audit --filter "rbac.authorization.k8s.io"
|
4. 最小权限原则:
- 使用 view、edit 等内置角色
- 避免使用 cluster-admin
- 定期审查权限