3. 基于 RBAC 的租户权限隔离:Role 与 ClusterRole、RoleBinding 与 ClusterBinding、最小权限原则
在多租户 Kubernetes 集群中,RBAC(基于角色的访问控制)是声明式权限隔离的核心机制。它通过定义“谁(Subject)”能对“哪些资源(Resource)”执行“什么操作(Verb)”,实现细粒度的租户隔离。本章将深入剖析 RBAC 的四大核心对象及其在最小权限原则下的最佳实践。
3.1 核心概念:Role 与 ClusterRole
Role 和 ClusterRole 是权限定义的“模板”,它们包含一组规则(rules),每个规则指定了允许的操作(verbs)和资源(resources)。两者的核心区别在于作用域:
| 特性 | Role | ClusterRole |
|---|---|---|
| 作用域 | 命名空间级别(Namespace-scoped) | 集群级别(Cluster-scoped) |
| 适用资源 | 命名空间内资源(如 Pod、Service、Deployment) | 集群范围资源(如 Node、PersistentVolume、Namespace)以及跨命名空间资源 |
| 典型用途 | 租户应用团队对其命名空间的管理 | 集群管理员、监控组件、跨命名空间资源访问 |
| YAML 示例 | kind: Role |
kind: ClusterRole |
3.1.1 Role 声明式定义示例
以下 YAML 定义了一个名为 pod-reader 的 Role,允许对命名空间 tenant-alpha 中的 Pod 执行 get、list 和 watch 操作:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: tenant-alpha
name: pod-reader
rules:
- apiGroups: [""] # 核心 API 组
resources: ["pods"]
verbs: ["get", "list", "watch"]
3.1.2 ClusterRole 声明式定义示例
以下 ClusterRole 允许对集群级别的 Node 资源执行 get 和 list 操作:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-viewer
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
3.2 绑定机制:RoleBinding 与 ClusterRoleBinding
定义好权限模板后,需要通过绑定(Binding)将角色赋予具体的用户、组或服务账户。绑定决定了权限的生效范围。
| 绑定类型 | 绑定的角色类型 | 生效范围 | 典型场景 |
|---|---|---|---|
| RoleBinding | Role 或 ClusterRole | 仅限绑定时指定的命名空间 | 将 pod-reader Role 授予 tenant-alpha 命名空间中的服务账户 |
| ClusterRoleBinding | 仅限 ClusterRole | 整个集群所有命名空间 | 将 cluster-admin ClusterRole 授予集群管理员用户 |
3.2.1 RoleBinding 声明式定义示例
以下 RoleBinding 将 pod-reader Role 绑定到 tenant-alpha 命名空间中的服务账户 sa-app-alpha:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: tenant-alpha
subjects:
- kind: ServiceAccount
name: sa-app-alpha
namespace: tenant-alpha
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
3.2.2 ClusterRoleBinding 声明式定义示例
以下 ClusterRoleBinding 将 node-viewer ClusterRole 绑定到用户 ops-admin,使其能查看所有 Node:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: view-nodes
subjects:
- kind: User
name: ops-admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: node-viewer
apiGroup: rbac.authorization.k8s.io
3.3 最小权限原则(Principle of Least Privilege)
在多租户环境中,最小权限原则是安全隔离的基石。其核心思想是:每个主体(用户、服务账户)只应被授予完成其任务所必需的最小权限集合。
3.3.1 实施步骤
- 识别角色与职责: 明确每个租户团队或组件的具体职责(如只读查看、应用部署、日志采集)。
- 从零开始构建: 不要从
cluster-admin或宽泛的权限开始裁剪,而是从空权限开始,逐步添加必要的规则。 - 细化资源与动词: 精确指定允许操作的资源(如
pods、deployments)和动词(如get、list、create、update)。避免使用通配符*。 - 限制非资源端点: 对于 API 的非资源端点(如
/healthz、/api),使用 ClusterRole 的nonResourceURLs字段进行精确控制。 - 定期审计与回收: 使用
kubectl auth can-i --list或审计日志定期检查权限使用情况,及时回收不再需要的权限。
3.4 租户隔离架构图
下图展示了基于 RBAC 的多租户隔离架构,其中每个租户拥有独立的命名空间,并通过 RoleBinding 绑定到特定的 Role,实现权限隔离。
3.5 权限检查流程
当用户或服务账户发起 API 请求时,Kubernetes API Server 会按照以下流程进行权限检查:
- 身份认证: 验证请求者的身份(用户、组或服务账户)。
- 请求解析: 提取请求的 Verb(如 get、create)、资源类型(如 pods)、命名空间(如有)和资源名称。
- 策略匹配: 遍历所有与该请求者相关的 RoleBinding 和 ClusterRoleBinding,收集绑定的 Role 和 ClusterRole 中的规则。
- 规则评估: 检查是否有任何规则明确允许该请求(Verb + 资源 + 命名空间)。如果找到匹配的允许规则,则请求通过;否则拒绝。
- 拒绝响应: 如果没有任何规则允许该请求,API Server 返回 HTTP 403 Forbidden。
kubectl apply -f 应用变更,并通过 kubectl auth reconcile 确保集群状态与声明式配置一致。
3.6 常见陷阱与避坑指南
- 陷阱 1:过度使用 ClusterRoleBinding —— 将 ClusterRole 通过 ClusterRoleBinding 绑定会授予跨所有命名空间的权限,极易造成权限泄露。应优先使用 RoleBinding 将 ClusterRole 限制在特定命名空间。
- 陷阱 2:使用通配符 Verbs 或 Resources —— 避免使用
verbs: ["*"]或resources: ["*"]。应精确列出所需操作和资源,例如verbs: ["get", "list"]。 - 陷阱 3:忽略 Aggregated ClusterRole —— 当需要组合多个 ClusterRole 时,使用
aggregationRule而非手动合并规则,以保持声明式管理的清晰性。 - 陷阱 4:服务账户权限未随应用更新 —— 当应用功能变更时,忘记同步更新其绑定的 Role,导致应用因权限不足而失败。应将 RBAC 变更纳入 CI/CD 流程。