Lesson 14:RBAC 权限模型与多租户隔离

admin 发布于 8 天前 8 次阅读


学习目标

  • 理解 K8s 的认证→授权→准入控制三步链
  • 掌握 RBAC 四要素:Role / ClusterRole / RoleBinding / ClusterRoleBinding
  • 实现基于 Namespace 的多租户权限隔离
  • 理解 ServiceAccount 的作用

1. 认证→授权→准入控制

每个请求到达 API Server 后经过三道关卡:

阶段问题机制
认证(Authentication)你是谁?客户端证书 / Bearer Token / ServiceAccount
授权(Authorization)你有权限吗?RBAC / ABAC / Webhook
准入控制(Admission)你的操作合规吗?Webhook / PSA / ResourceQuota

设计意图:三道关卡是串行执行的。只有通过了认证,才会进入授权检查;只有通过了授权,才会进入准入控制。任何一步失败,请求都会被拒绝。这种纵深防御(Defense in Depth)是企业级安全架构的标准实践。


2. RBAC 四要素

Role / ClusterRole —— 定义权限

yaml# Role:限定在某个 Namespace 内的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: pod-reader
rules:
- apiGroups: [""]           # "" 代表核心 API 组(Pod、Service、ConfigMap 等)
  resources: ["pods"]       # 资源类型
  verbs: ["get", "list", "watch"]  # 允许的操作

参数解读

  • apiGroups: [""]:空字符串代表核心 API 组(core group),包含 Pod、Service、ConfigMap、Secret 等基础资源。其他资源组如 apps(Deployment)、networking.k8s.io(NetworkPolicy)
  • resources: ["pods"]:限定操作的资源类型。可以是 podsservicesconfigmapssecretsdeployments 等
  • verbs:允许的操作动词。常用动词:get(查看单个)、list(列出所有)、watch(监听变化)、create(创建)、update(更新)、delete(删除)、patch(部分修改)
yaml# ClusterRole:全集群范围的权限(不限定 Namespace)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-viewer
rules:
- apiGroups: [""]
  resources: ["nodes"]      # nodes 是集群级资源,只能用 ClusterRole
  verbs: ["get", "list"]

Role vs ClusterRoleRole 只能管控某个特定 Namespace 内的资源权限。ClusterRole 可以管控全集群的资源,包括 nodesnamespaces 这类不属于任何 Namespace 的集群级资源。

RoleBinding / ClusterRoleBinding —— 绑定权限到用户

yaml# 将 pod-reader 权限绑定给用户 "developer"
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-binding
  namespace: dev
subjects:                   # 谁(权限的接收方)
- kind: User
  name: developer
  apiGroup: rbac.authorization.k8s.io
roleRef:                    # 什么权限(引用的 Role 或 ClusterRole)
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

参数解读

  • subjects:定义权限的接收方。kind 可以是 User(用户)、Group(用户组)或 ServiceAccount(服务账号)
  • roleRef:引用具体的 Role 或 ClusterRole。RoleBinding 绑定的权限只在其所属 Namespace 内生效

3. ServiceAccount

Pod 内的应用程序如果需要调用 K8s API(如查询 ConfigMap、监听 Pod 状态变化),需要通过 ServiceAccount 进行身份认证。每个 Namespace 都有一个默认的 default ServiceAccount。

yamlapiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: production

设计意图:ServiceAccount 是 Pod 在集群内的"身份证"。通过给不同的 ServiceAccount 绑定不同的 Role,可以实现最小权限原则——每个应用只拥有它完成工作所需的最少权限。


动手实验

实验 14.1:创建受限用户并验证权限隔离

bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# 创建 Namespace(模拟一个开发团队的独立空间)
kubectl create namespace dev-team

预期输出

bashnamespace/dev-team created
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# 创建 Role(只允许查看 Pod,禁止其他一切操作)
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev-team
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
EOF

预期输出

bashrole.rbac.authorization.k8s.io/pod-reader created
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# 创建 ServiceAccount 并绑定角色
kubectl create serviceaccount dev-user -n dev-team
kubectl create rolebinding dev-pod-reader --role=pod-reader --serviceaccount=dev-team:dev-user -n dev-team

预期输出

bashserviceaccount/dev-user created
rolebinding.rbac.authorization.k8s.io/dev-pod-reader created

命令解读

  • --serviceaccount=dev-team:dev-user:格式为 <namespace>:<serviceaccount-name>,指定权限绑定给哪个 ServiceAccount
  • --role=pod-reader:引用刚才创建的 Role

现在用 kubectl auth can-i 命令模拟该 ServiceAccount 的身份来验证权限:

bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# ✅ 可以查看 dev-team 命名空间内的 Pod
kubectl auth can-i get pods -n dev-team --as=system:serviceaccount:dev-team:dev-user

预期输出

bashyes
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# ❌ 不能查看 Secret(没有授权)
kubectl auth can-i get secrets -n dev-team --as=system:serviceaccount:dev-team:dev-user

预期输出

bashno
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# ❌ 不能删除 Pod(只有 get/list/watch 权限,没有 delete)
kubectl auth can-i delete pods -n dev-team --as=system:serviceaccount:dev-team:dev-user

预期输出

bashno
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# ❌ 不能跨命名空间访问(Role 只在 dev-team 内有效)
kubectl auth can-i get pods -n default --as=system:serviceaccount:dev-team:dev-user

预期输出

bashno
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# ❌ 不能查看集群级资源(Role 无法授权 nodes 等集群资源)
kubectl auth can-i get nodes --as=system:serviceaccount:dev-team:dev-user

预期输出

bashWarning: resource 'nodes' is not namespace scoped

no

输出解读:K8s 还贴心地给出了警告——nodes 不是 Namespace 级别的资源,所以 Namespace 级别的 Role 无论如何也无法授权对它的访问。如果需要查看节点信息,必须使用 ClusterRole + ClusterRoleBinding。

核心认知:通过这 5 个测试,我们验证了 RBAC 的三层隔离效果:

  1. 资源类型隔离:只授权了 pods,访问 secrets 被拒
  2. 操作动词隔离:只授权了 get/list/watch,delete 被拒
  3. 命名空间隔离:Role 只在 dev-team 内生效,跨 Namespace 被拒
bash# === 在 Master 节点 (172.16.11.104) 上执行 ===

# 清理
kubectl delete namespace dev-team

预期输出

bashnamespace "dev-team" deleted

提示:删除 Namespace 会自动删除其中的所有资源(包括 Role、RoleBinding、ServiceAccount、Pod 等)。


检查点

  •  能画出认证→授权→准入控制的三步流程
  •  能编写 Role 和 RoleBinding 实现权限隔离
  •  能用 kubectl auth can-i 验证权限
  •  理解 Role(Namespace级) 与 ClusterRole(集群级) 的区别

此作者没有提供个人介绍。
最后更新于 2026-04-28