学习目标
- 理解 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"]:限定操作的资源类型。可以是pods、services、configmaps、secrets、deployments等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 ClusterRole:
Role只能管控某个特定 Namespace 内的资源权限。ClusterRole可以管控全集群的资源,包括nodes、namespaces这类不属于任何 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 的三层隔离效果:
- 资源类型隔离:只授权了 pods,访问 secrets 被拒
- 操作动词隔离:只授权了 get/list/watch,delete 被拒
- 命名空间隔离: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(集群级) 的区别
Comments NOTHING