1. 简介与核心作用
RBAC(Role-Based Access Control)是 K8S 控制谁能对哪些资源执行什么操作的核心授权机制。
K8S 访问控制链路
plaintext
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes API Server │
├─────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────────┐ ┌─────────────┐ │
│ │ Request │───▶│ Authentication│───▶│ RBAC │ │
│ │(User/SA) │ │ 身份认证 │ │ 授权检查 │ │
│ └──────────┘ └──────────────┘ └──────┬──────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ Admission │ │
│ │ Controllers │ │
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────────┘
RBAC vs ABAC
表格
| 特性 | RBAC | ABAC |
|---|---|---|
| 配置复杂度 | 低 | 高 |
| 权限粒度 | 角色+规则 | 属性+策略 |
| K8S 推荐度 | ✅ 生产首选 | 仅特殊场景 |
2. 核心资源对象详解
2.1 Role / ClusterRole
简介
- Role:命名空间级权限
- ClusterRole:集群级或所有命名空间权限
权限 verbs 分类
表格
| 类型 | verbs |
|---|---|
| READ | get, list, watch |
| WRITE | create, update, patch, delete |
| SPECIAL | escalate, bind, impersonate |
YAML 示例
Role - 命名空间级只读
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
ClusterRole - 集群级只读
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-reader
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps"]
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics", "/healthz"]
verbs: ["get"]
常用命令
bash
kubectl get clusterroles
kubectl get role pod-reader -n default -o yaml
kubectl describe role pod-reader -n default
2.2 RoleBinding / ClusterRoleBinding
简介
- RoleBinding:将 Role/ClusterRole 绑定到用户/组/SA,作用于单个命名空间
- ClusterRoleBinding:绑定到用户/组/SA,作用于整个集群
工作原理
plaintext
┌─────────────────────────────────────────────────────────────┐
│ RoleBinding │
├─────────────────────────────────────────────────────────────┤
│ subjects: roleRef: │
│ - kind: User - kind: Role │
│ name: john name: pod-reader │
│ - kind: ServiceAccount ────────────────────────▶ grants
│ name: my-sa permissions
└─────────────────────────────────────────────────────────────┘
YAML 示例
RoleBinding - 绑定用户到 Role
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: john-pod-reader
namespace: default
subjects:
- kind: User
name: john
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
ClusterRoleBinding - 绑定多个主体到 ClusterRole
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: cluster-admin-binding
subjects:
- kind: User
name: admin@example.com
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: devops-team
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: ci-deployer
namespace: ci-cd
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
常用命令
bash
kubectl get rolebindings -n default
kubectl get rolebinding john-pod-reader -n default -o yaml
kubectl auth can-i --list --as=john
kubectl auth can-i get pods --as=john -n default
2.3 ServiceAccount
简介
ServiceAccount 是 Pod 的身份标识,用于 Pod 访问 API Server。
工作原理
plaintext
┌──────────────────────────────────────────────────────────────────┐
│ ServiceAccount 认证流程 │
├──────────────────────────────────────────────────────────────────┤
│ ┌─────────┐ ┌─────────────┐ ┌───────────────┐ │
│ │ Pod │───────▶│ ServiceAcct │───────▶│ API Server │ │
│ │ │ 挂载 │ Token │ 持有 │ RBAC Check │ │
│ └─────────┘ Token └─────────────┘ └───────────────┘ │
│ │ │
│ ▼ /var/run/secrets/kubernetes.io/serviceaccount/ │
│ ├── token # JWT Token │
│ ├── namespace # 命名空间名称 │
│ └── ca.crt # API Server CA │
└──────────────────────────────────────────────────────────────────┘
YAML 示例
创建 ServiceAccount
yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-app-sa
namespace: production
automountToken: false # 禁用自动挂载
Pod 使用 ServiceAccount
yaml
apiVersion: v1
kind: Pod
metadata:
name: my-app
namespace: production
spec:
serviceAccountName: my-app-sa
containers:
- name: app
image: my-app:latest
常用命令
bash
kubectl get serviceaccounts -n production
kubectl get sa my-app-sa -n production -o yaml
# 获取 SA 的 JWT Token
kubectl get secret $(kubectl get sa my-app-sa -n production \
-o jsonpath='{.secrets[0].name}') -n production \
-o jsonpath='{.data.token}' | base64 -d
3. 工作原理与请求链路
完整请求流程
plaintext
┌────────────────────────────────────────────────────────────────────────────┐
│ RBAC 授权流程 │
├────────────────────────────────────────────────────────────────────────────┤
│ 1. Request ──▶ GET /api/v1/namespaces/default/pods │
│ Authorization: Bearer xxx │
│ │ │
│ ▼ │
│ 2. Authentication ──▶ 验证证书/Token ──▶ 提取: username, uid, groups │
│ │ │
│ ▼ │
│ 3. RBAC Authorization │
│ ① 收集所有 RoleBinding/ClusterRoleBinding (含该用户) │
│ ② 获取关联的 Role/ClusterRole │
│ ③ 检查 verbs 是否匹配 requested verb │
│ ④ 检查 resources/apiGroups 是否匹配 │
│ ⑤ 检查 namespace 范围 │
│ │ │
│ ▼ │
│ 4. 决策结果 │
│ ✓ 匹配到规则 ──▶ 允许访问 (200) │
│ ✗ 无匹配规则 ──▶ 拒绝访问 (403 Forbidden) │
└────────────────────────────────────────────────────────────────────────────┘
4. 实战 YAML 配置
场景 1:最小权限只读用户
yaml
---
# 定义只读 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: readonly-all-namespaces
rules:
- apiGroups: [""]
resources: ["pods", "services"]
verbs: ["get", "list", "watch"]
---
# 绑定到用户
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: readonly-user-binding
subjects:
- kind: User
name: readonly-user
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: readonly-all-namespaces
apiGroup: rbac.authorization.k8s.io
场景 2:开发者命名空间权限
yaml
---
# 命名空间读写权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: dev
name: developer-role
rules:
- apiGroups: [""]
resources: ["*"]
verbs: ["*"]
- apiGroups: ["apps"]
resources: ["deployments", "statefulsets"]
verbs: ["*"]
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["*"]
---
# 绑定到用户组
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dev-team-binding
namespace: dev
subjects:
- kind: Group
name: dev-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: developer-role
apiGroup: rbac.authorization.k8s.io
---
# 其他命名空间只读
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: dev-team-readonly
subjects:
- kind: Group
name: dev-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
场景 3:Pod 访问 API 的 ServiceAccount
yaml
---
# 创建 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: monitoring
---
# 创建 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-metrics-reader
rules:
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
- apiGroups: [""]
resources: ["nodes/metrics", "nodes/proxy"]
verbs: ["get"]
---
# 绑定 SA 到 ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus-metrics-binding
subjects:
- kind: ServiceAccount
name: prometheus
namespace: monitoring
roleRef:
kind: ClusterRole
name: prometheus-metrics-reader
apiGroup: rbac.authorization.k8s.io
---
# Deployment 使用 SA
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:latest
场景 4:ClusterRole 聚合
yaml
---
# 定义聚合角色
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: base-read
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.example.com/aggregate-to-base-read: "true"
rules: [] # 由聚合自动填充
---
# 实现层:Pods 只读
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: base-read-pods
labels:
rbac.example.com/aggregate-to-base-read: "true"
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
---
# 实现层:日志读取
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: base-read-logs
labels:
rbac.example.com/aggregate-to-base-read: "true"
rules:
- apiGroups: [""]
resources: ["pods/log"]
verbs: ["get"]
场景 5:常用内置 ClusterRole
表格
| ClusterRole | 说明 | 使用场景 |
|---|---|---|
cluster-admin |
完全控制 | 管理员 |
admin |
命名空间全部权限 | 命名空间所有者 |
edit |
命名空间读写 | 开发者 |
view |
命名空间只读 | 观察者 |
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: developer-edit
namespace: dev
subjects:
- kind: User
name: developer@example.com
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: edit
apiGroup: rbac.authorization.k8s.io
场景 6:跨命名空间 ServiceAccount
需求 :ci-cd 命名空间的 CI Deployer 需要操作 production 的 Deployment
yaml
---
# 创建 CI CD ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: ci-deployer
namespace: ci-cd
---
# 定义权限(在 production 命名空间)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: ci-deployer-role
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
# 跨命名空间绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: ci-deployer-binding
namespace: production
subjects:
- kind: ServiceAccount
name: ci-deployer
namespace: ci-cd # 从 ci-cd 引用
roleRef:
kind: Role
name: ci-deployer-role
apiGroup: rbac.authorization.k8s.io
5. 常用操作命令
权限查看与测试
bash
# 权限测试
kubectl auth can-i get pods
kubectl auth can-i create pods -n dev
kubectl auth can-i delete deployments -n prod
# 模拟其他用户
kubectl auth can-i get pods --as=john -n default
kubectl auth can-i --list --as=john
# 模拟 SA
kubectl auth can-i --list --as=system:serviceaccount:monitoring:prometheus
# 查看用户身份
kubectl auth whoami
资源查询
bash
kubectl get clusterroles
kubectl get clusterrole admin -o yaml
kubectl get rolebindings --all-namespaces -o wide
6. 常见问题与排查
问题 1:权限不足 403
症状:
plaintext
Error from server (Forbidden): pods is forbidden: User "john"
cannot list resource "pods" in API group "" in the namespace "default"
排查步骤:
bash
# 1. 确认用户身份
kubectl auth whoami
# 2. 测试权限
kubectl auth can-i get pods --as=john -n default
kubectl auth can-i list pods --as=john -n default
# 3. 检查绑定
kubectl get rolebindings -n default --as=john
kubectl describe rolebinding -n default | grep -A5 "john"
# 4. 检查 Role 定义
kubectl get role <role-name> -n default -o yaml
# 5. 确认 apiGroup
# 错误: apps 组资源使用 apiGroups: [""]
# 正确: Deployment 使用 apiGroups: ["apps"]
问题 2:ServiceAccount Token 不可用
症状:Pod 内 token 调用 API 失败
bash
# 1. 检查 SA 存在
kubectl get sa -n production | grep my-app
# 2. 验证 token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
curl -k -H "Authorization: Bearer $TOKEN" \
https://kubernetes.default.svc/api/v1/namespaces/production/pods
# 3. 检查 token 过期
kubectl get secret <secret-name> -n production \
-o jsonpath='{.data.token}' | base64 -d | cut -d. -f2 | base64 -d
解决方案:删除 SA 自动重建
bash
kubectl delete sa my-app-sa -n production
问题 3:RoleBinding 绑错命名空间
排查:
bash
# 查看各命名空间权限
for ns in $(kubectl get ns -o name | cut -d/ -f2); do
echo "=== $ns ==="
kubectl auth can-i get pods --as=john -n $ns
done
# 检查绑定关系
kubectl get rolebindings --all-namespaces -o wide | grep john
解决方案:使用 ClusterRoleBinding 作用于所有命名空间
7. 最佳实践
安全配置
- 最小权限原则 :避免
*通配符,只授予必需权限 - 区分用户类型:Human → User/Group,Pod → ServiceAccount
- 禁用匿名访问 :
--anonymous-auth=false - 禁用 SA 自动挂载 :设置
automountToken: false
权限设计
plaintext
ClusterRoleBinding ──▶ ClusterRole ──▶ 集群级/所有NS
│
└── RoleBinding ──▶ Role ──▶ 单NS资源
- 使用 Role + RoleBinding 管理 NS 级权限
- ClusterRole + RoleBinding 授予集群范围只读
- ClusterRoleBinding 仅用于管理员和特殊权限
操作规范
- 权限变更需审批:通过 GitOps/CD 管理 RBAC 资源
- 定期审计 :使用
kubectl auth can-i --list审计权限 - 命名规范 :Role
<用途>-role,RoleBinding<主体>-<角色>-binding
故障排查清单
- ✅
kubectl auth whoami确认身份 - ✅
kubectl auth can-i <verb> <resource>测试权限 - ✅ 检查 RoleBinding subjects + roleRef
- ✅ 验证 apiGroups / resources / verbs 匹配
- ✅ 确认 namespace 作用范围
附录
表格
| 资源 | 作用域 | 用途 |
|---|---|---|
| Role | 单 NS | 定义 NS 内权限 |
| ClusterRole | 集群/所有 NS | 集群级权限或聚合 |
| RoleBinding | 单 NS | 绑定 Role 到主体 |
| ClusterRoleBinding | 集群 | 绑定 ClusterRole 到主体 |
表格
| verbs | 含义 |
|---|---|
| get/list/watch | 只读 |
| create/update/patch | 写入 |
| delete | 删除 |
| escalate/bind/impersonate | 特权(需显式授予) |
SA Token 路径 :/var/run/secrets/kubernetes.io/serviceaccount/
token:JWT Tokennamespace:命名空间名ca.crt:API Server CA 证书