K8s RBAC 进阶避坑指南(下集)

上集搞懂了四个核心概念,中集手把手搭建了开发组 + 运维组权限体系。这一集收尾:进阶要点、6 条排坑经验、落地清单——把 RBAC 的最后一公里走完。


一、进阶要点

1. 最小权限原则:从 deny 到 allow

K8s RBAC 是白名单模式——默认拒绝一切,只有显式授权才能操作。这意味着你不需要写"拒绝规则",只需要写"允许规则"。

正确做法

# ✅ 精确指定 apiGroups、resources、verbs
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get"]
  resourceNames: ["app-config"]   # 甚至精确到某个 ConfigMap!

错误做法

# ❌ 通配符——等于没做权限管控
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

2. 聚合 ClusterRole:自动继承

2.1 先认识四个内置 ClusterRole

K8s 装好就自带四个 ClusterRole,生产环境直接引用,不用自己写:

角色 权限范围 不能做 典型用途
view 只读(get/list/watch),不含 Secret create/update/delete、读 Secret 开发人员日常查看
edit 读写,但不能改 RBAC、不能读 Secret 修改 Role/RoleBinding/Secret 开发人员日常部署
admin 命名空间内完全控制(含 RBAC Binding) 跨命名空间操作 命名空间管理员
cluster-admin 全集群超级权限 平台运维团队

注意viewedit不能读 Secret,这是刻意的——防止开发人员通过只读权限拿到数据库密码、API Key 等敏感信息。

view 能访问的核心资源(只读):

✅ Pods、Deployments、Services、ConfigMaps
   ReplicaSets、DaemonSets、StatefulSets
   Ingress、PVC、Nodes(只读)
   Events、Endpoints、ServiceAccounts(只读)
❌ Secrets(即使是只读也不行)
❌ 任何资源的 create/update/delete

验证某个角色包含什么权限:

kubectl describe clusterrole view      # 查看 view 的所有 rules
kubectl describe clusterrole edit      # 查看 edit 的所有 rules

2.2 聚合机制:给内置角色"追加"权限

场景:公司部署了一个 CRD 叫 myresources,所有开发人员(已绑定 view)也应该能 get/list 它。但开发人员有几十个,不可能每人都加一条 Binding。

解决方法:创建一个带聚合标签的 ClusterRole,K8s 自动把它的 rules 合并进目标角色:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: myresources-view
  labels:
    rbac.authorization.k8s.io/aggregate-to-view: "true"  # ← 这个标签是关键
rules:
- apiGroups: ["example.com"]
  resources: ["myresources"]
  verbs: ["get", "list", "watch"]

kubectl apply 之后,所有已经绑定了 view 的用户,不需要任何 Binding 变更,立刻自动获得 myresources 的只读权限。

三个支持聚合的内置角色,对应标签如下:

目标角色 聚合标签
view aggregate-to-view: "true"
edit aggregate-to-edit: "true"
admin aggregate-to-admin: "true"

什么时候用:部署了 CRD(Operator、自定义资源)之后,用聚合 ClusterRole 统一给现有角色补权限,比批量修改 Binding 效率高得多。


2.3 ⚠️ ClusterRole ≠ 全集群权限

很多人以为 ClusterRole 一定能访问全集群,这是错的。ClusterRole 只是「权限规则的定义」,实际范围由 Binding 决定

绑定方式 效果
ClusterRoleBinding + ClusterRole ✅ 全集群生效
RoleBinding(某命名空间)+ ClusterRole 只在这一个命名空间生效
# 场景:zhangsan 只能在 dev 命名空间只读
# 用的是 ClusterRole view,但绑定方式是 RoleBinding(只在 dev)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding          # ← RoleBinding,不是 ClusterRoleBinding
metadata:
  name: zhangsan-view
  namespace: dev           # ← 只在 dev 这个命名空间
subjects:
- kind: User
  name: zhangsan
roleRef:
  kind: ClusterRole
  name: view               # ← 引用 ClusterRole,但范围被 RoleBinding 限制住了

为什么这么设计:ClusterRole 的规则写一次,可以在多个命名空间复用。比如 devstaging 都要开发组只读,写一个 ClusterRole,然后在两个命名空间各建一个 RoleBinding 引用它,规则不用维护两份。

3. 安全审计:定期巡检 + 权限验证

RBAC 不是配完就不管了——权限会随着人员流动、项目变更逐渐腐化。养成定期审计的习惯:

# === 巡检 1:找出所有 cluster-admin 绑定的用户 ===
kubectl get clusterrolebinding -o json | \
  jq '.items[] | select(.roleRef.name=="cluster-admin") | .subjects[]'

# === 巡检 2:检查谁有 delete 权限(高风险管理) ===
kubectl get clusterroles --all-namespaces -o json | \
  jq '.items[] | select(.rules[].verbs[] | contains("delete")) | .metadata.name'

# === 巡检 3:验证某个用户的真实权限 ===
kubectl auth can-i delete pods --as=lisi -n default
kubectl auth can-i create namespaces --as=lisi

# === 巡检 4:列出某个 ClusterRole 的完整规则 ===
kubectl describe clusterrole system:aggregate-to-admin

# === 巡检 5:删除高风险绑定(如意外公开的只读绑定) ===
kubectl delete clusterrolebinding dangerous-public-binding

建议:把巡检命令写成 CronJob 或用 kubectl-who-can 这类工具自动扫描,发现异常权限绑定发告警。

4. apiGroups 填错导致权限无效

这是最常见的排错场景——权限配了但不生效,99% 是因为 apiGroups 写错了:

注意:resources 字段必须写资源的全称,不能用缩写。比如 deployments 不能写成 deployservices 不能写成 svc

资源类型 正确的 apiGroup
Pod、Service、ConfigMap、Secret ""(核心组,空字符串)
Deployment、StatefulSet、DaemonSet apps
Ingress networking.k8s.io
HPA autoscaling
RBAC 自身(Role、RoleBinding) rbac.authorization.k8s.io
CRD 自定义资源 看 CRD 定义里的 spec.group
# 不知道一个资源的 apiGroup?用这个查
kubectl api-resources | grep -i deployment
# deployments  apps/v1  true  Deployment
#              ↑ 这就是 apiGroup

二、RBAC 排坑指南

1. 配了权限不生效?先查这三项

# 1. 检查 Binding 是否正确绑定
kubectl get rolebinding -n prod log-collector -o yaml

# 2. 检查 Role 规则是否正确
kubectl describe role log-reader -n prod

# 3. 用 can-i 模拟验证
kubectl auth can-i get pods -n prod \
  --as system:serviceaccount:prod:log-collector
kubectl auth can-i create pods -n prod \
  --as system:serviceaccount:prod:log-collector

2. ServiceAccount 的 namespace 要跟 Binding 一致

# ❌ 错误:SA 在 prod,Binding 在 staging
subjects:
- kind: ServiceAccount
  name: log-collector
  namespace: prod      # ← SA 所在 namespace

# RoleBinding 在 staging namespace → 这个 SA 读不到 staging 的资源

规则:ServiceAccount 只能通过自己 namespace 下的 RoleBinding 获取权限。如果你要跨 namespace 授权,用 ClusterRole + ClusterRoleBinding。

3. 忘记给 list 但给了 watch

kubectl get pods 同时需要 list + watch 权限——很多 Controller 只给了 watch 忘了 list,导致启动失败。

4. kubectl 子命令的权限要求

# kubectl exec → 需要 pods/exec 子资源权限
rules:
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

# kubectl logs → 需要 pods/log 子资源权限
rules:
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get"]

5. --as 不携带 Group,验证 Group 权限要用 KUBECONFIG

# ❌ 错误——只模拟了 User "lisi",没带上证书里的 Group "ops-team"
kubectl auth can-i get pods -n prod --as lisi        # → no

# ✅ 正确——用 lisi 自己的 kubeconfig(CN + O 都在)
KUBECONFIG=lisi.kubeconfig kubectl auth can-i get pods -n prod  # → yes

# ✅ 或者显式指定 --as-group
kubectl auth can-i get pods -n prod --as lisi --as-group ops-team  # → yes

6. 用 describe 而不是 get 排查 RBAC

# kubectl describe 会自动展示 RBAC 的绑定关系和规则
kubectl describe clusterrole read-only

三、总结

1. RBAC三元组

RBAC 的核心就一个三元组:身份(谁)× 权限(能做什么)× 绑定(怎么关联)

需要做的事 用什么 示例
给人(开发)分配权限 User + RoleBinding + Role 开发在 dev ns 只读
给 Pod 分配权限 ServiceAccount + RoleBinding + Role CI/CD 部署更新 Deployment
给 Pod 全集群权限 ServiceAccount + ClusterRoleBinding + ClusterRole 日志采集读全集群 Pod
给一组人统一权限 Group + RoleBinding + Role dev-team 组在 staging ns 只读
复用权限规则到多个 ns RoleBinding + ClusterRole 只读规则复用到 dev/staging/prod
限制单个资源 resourceNames 字段 只允许读 app-config 这个 ConfigMap

2. 落地清单:

  • 所有 Namespace 禁用 default ServiceAccount(或不给它任何权限)
  • CI/CD 用的 ServiceAccount 只给必要的 verbs(不给 * / delete 除非确实需要)
  • 开发人员通过 Group 分配权限,不要逐个 User 绑定
  • apiGroups 填对——核心资源 "",apps 组 apps
  • resources 写全称不能缩写——deployments 不是 deployservices 不是 svc
  • 上线前用 kubectl auth can-i --list 验证 SA 权限
  • 不要创建 subjects: [{kind: ServiceAccount, name: default}] — 这是给所有 Pod 的
  • kubectl describe role/clusterrole 排查,比 get -o yaml 直观得多
  • 定期安全巡检:扫描 cluster-admin 绑定、delete 权限、异常公开绑定

记住这个等式:RBAC = Subject(谁)+ Role(能做啥)+ Binding(绑在一起)。搞混四个概念就回来看上集那张图。

更多推荐