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
最佳实践提示: 优先使用 Role 进行租户隔离。仅在需要访问集群范围资源(如查看所有 Namespace 的 Pod)或定义公共权限模板时,才使用 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 授予集群管理员用户
关键区别: 使用 RoleBinding 绑定一个 ClusterRole 时,权限会被“裁剪”到该 RoleBinding 所在的命名空间。这是实现“跨命名空间公共权限模板”的常用技巧,但不会授予集群范围资源的访问权限。

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 实施步骤

  1. 识别角色与职责: 明确每个租户团队或组件的具体职责(如只读查看、应用部署、日志采集)。
  2. 从零开始构建: 不要从 cluster-admin 或宽泛的权限开始裁剪,而是从空权限开始,逐步添加必要的规则。
  3. 细化资源与动词: 精确指定允许操作的资源(如 pods、deployments)和动词(如 get、list、create、update)。避免使用通配符 *。
  4. 限制非资源端点: 对于 API 的非资源端点(如 /healthz、/api),使用 ClusterRole 的 nonResourceURLs 字段进行精确控制。
  5. 定期审计与回收: 使用 kubectl auth can-i --list 或审计日志定期检查权限使用情况,及时回收不再需要的权限。
声明式管理优势: 将 RBAC 配置以 YAML 形式存储在 Git 仓库中,通过 GitOps 流程进行版本控制和变更审批,确保权限变更可追溯、可回滚。

3.4 租户隔离架构图

下图展示了基于 RBAC 的多租户隔离架构,其中每个租户拥有独立的命名空间,并通过 RoleBinding 绑定到特定的 Role,实现权限隔离。

基于 RBAC 的多租户隔离架构 基于 RBAC 的多租户隔离架构 Kubernetes 集群 Namespace: tenant-alpha Pod Service Deployment ConfigMap ServiceAccount: sa-app-alpha RoleBinding: read-pods Role: pod-reader Namespace: tenant-beta Pod Service Deployment Secret ServiceAccount: sa-app-beta RoleBinding: manage-apps Role: app-manager 每个租户拥有独立的 Namespace,通过 RoleBinding 将 ServiceAccount 绑定到特定 Role,实现权限隔离

3.5 权限检查流程

当用户或服务账户发起 API 请求时,Kubernetes API Server 会按照以下流程进行权限检查:

  1. 身份认证: 验证请求者的身份(用户、组或服务账户)。
  2. 请求解析: 提取请求的 Verb(如 get、create)、资源类型(如 pods)、命名空间(如有)和资源名称。
  3. 策略匹配: 遍历所有与该请求者相关的 RoleBinding 和 ClusterRoleBinding,收集绑定的 Role 和 ClusterRole 中的规则。
  4. 规则评估: 检查是否有任何规则明确允许该请求(Verb + 资源 + 命名空间)。如果找到匹配的允许规则,则请求通过;否则拒绝。
  5. 拒绝响应: 如果没有任何规则允许该请求,API Server 返回 HTTP 403 Forbidden。
声明式管理要点: 所有 RBAC 配置都应作为 YAML 文件存储在 Git 仓库中。使用 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 流程。

3.7 本章小结