前言

集群一旦多人使用,“谁都能改一切"就是定时炸弹。K8s 的 RBAC(基于角色的访问控制)决定谁能对什么资源做什么操作——这篇把模型讲透并落地一套多团队权限方案。

一、RBAC 四对象

                    ┌──────────────┐
      RoleBinding ──┤   Role       ├── 定义"能做什么"(一组规则)
      (谁↔角色)    │ (namespace级) │
                    └──────────────┘
                    ┌──────────────┐
 ClusterRoleBinding─┤ ClusterRole  ├── 同上, 但集群级
                    └──────────────┘

绑定关系: User/Group/ServiceAccount ──binding──► Role ──► [资源+动词]
对象 作用域 说明
Role 单 namespace 规则(能做什么)
ClusterRole 全集群 集群级资源/跨 ns 权限
RoleBinding 单 namespace 把角色绑给"人”(限本 ns)
ClusterRoleBinding 全集群 全局生效(慎用)

精妙之处:ClusterRole 可以通过 RoleBinding 绑定——规则定义一次,在某 ns 内生效(常用套路)。

二、规则:资源与动词

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: dev-deployer
rules:
- apiGroups: ["apps"]             # "" = core组(pod/svc/configmap...)
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch"]
- apiGroups: [""]
  resources: ["pods", "pods/log"]
  verbs: ["get", "list", "watch"]     # 开发只读 Pod 与日志
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]                    # 允许 exec 进容器调试

verbs 速查:

动词 对应操作
get / list / watch 查看单个/列出/监听
create / update / patch 创建/替换/部分更新
delete / deletecollection 删除
* 全部(Danger!)

特殊资源名(resourceNames 收窄到具体对象):

- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["app-conf"]        # 只能操作这一个 ConfigMap
  verbs: ["get", "update"]

三、主体:谁能被授权

User      外部认证的用户(证书/OIDC 对接公司账号体系)
Group     用户组(证书 O 字段/OIDC group)
ServiceAccount  集群内的"服务账号"(应用/CI 用)

四、实战一:给开发团队开权限

需求:dev 团队只能用 dev namespace,能部署应用、看日志、进容器,不能碰 secrets 和其他 ns。

apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: v1
kind: ServiceAccount
metadata:
  namespace: dev
  name: dev-team
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: dev-role
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "replicasets"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["services", "configmaps", "pods", "pods/log", "pods/exec"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# 注意: 刻意不含 secrets!
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: dev
  name: dev-team-binding
subjects:
- kind: ServiceAccount
  name: dev-team
  namespace: dev
roleRef:
  kind: Role
  name: dev-role
  apiGroup: rbac.authorization.k8s.io

验证权限:

kubectl auth can-i get pods -n dev --as=system:serviceaccount:dev:dev-team
# yes
kubectl auth can-i get secrets -n dev --as=system:serviceaccount:dev:dev-team
# no      ✅ 符合预期
kubectl auth can-i get pods -n prod --as=system:serviceaccount:dev:dev-team
# no      ✅ 越不过 namespace

# 一键看全部权限
kubectl auth can-i --list -n dev --as=system:serviceaccount:dev:dev-team

五、实战二:给 CI 机器人只读+部署权

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole        # 集群级定义
metadata:
  name: deployer
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "update", "patch"]   # set image 需要 patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding        # 但只绑到 ci 用的 ns → 权限被限制住
metadata:
  namespace: staging
  name: ci-deployer
subjects:
- kind: ServiceAccount
  name: gitlab-ci
  namespace: staging
roleRef:
  kind: ClusterRole
  name: deployer
  apiGroup: rbac.authorization.k8s.io

ClusterRole + RoleBinding = 复用规则又限制范围——权限设计的精髓。

六、常见内置 ClusterRole

角色 内容
view 全集群只读
edit 读写常规资源(不能改权限/namespace)
admin ns 内几乎全部(含 quota)
cluster-admin 超级管理员(等于 root,只有平台组该有)
# 给值班同学 ns 级 admin(而非集群级!)
kubectl create rolebinding oncall-admin -n prod \
  --clusterrole=admin --user=zy@corp

七、Pod 使用 ServiceAccount

spec:
  serviceAccountName: app-sa       # 默认是 default(能读本ns部分信息)
  automountServiceAccountToken: false   # 不需要调 API 的应用关掉挂载(收缩面)
# Pod 内拿 token 调 API(应用自发现的场景)
kubectl exec -it pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token

安全提醒:default SA 在老版本默认可读 ns 内全部 Secret 的能力面(实际 API 探测);业务 Pod 一律显式 SA + 关闭 automount。

八、排查与审计

# 我能干嘛
kubectl auth can-i delete pods -n prod
kubectl auth can-i '*' '*'                       # 是不是管理员

# 为什么他有这个权限(绑定溯源)
kubectl get rolebindings,clusterrolebindings -A -o wide | grep <user>

# 看规则明细
kubectl describe clusterrole view | head -30

# 开审计日志(API Server 参数 或 /etc/kubernetes/audit-policy.yaml)
audit.k8s.io 提到:
  - level: Metadata    # 记录谁在何时对什么对象做了什么
  # 谁读了 secrets → 排查泄密的关键证据

九、设计原则

  1. 最小权限:从只读开始,按报错逐步加(can-i 随手验证)
  2. namespace 即边界:多团队 → 多 ns + 各自 Role
  3. 宁可 RoleBinding 也不 ClusterRoleBinding:全局权限是奢侈品
  4. 禁用通配:resources: ["*"] / verbs: ["*"] 出现就该被 review
  5. SA 一应用一个,别共用 default
  6. 定期审计:clusterrolebindings 全量 review(每季度)

十、常见坑

现象 原因
403 but 我明明绑了 binding 的 ns 不对;SA 引用要带 ns
RoleBinding 绑 ClusterRole 不生效 检查 rule 的资源本身是否集群级(nodes 等必须 ClusterRoleBinding)
can-i 有但 kubectl 报错 细分到子资源(pods/log vs pods)
升级后 token 失效 bound token 有过期时间;重新拿
exec 被拒 pods/exec 需要单独授权且动词是 create

小结

组件 一句话
Role/ClusterRole 规则:资源 × 动词
Binding 把规则绑给用户/组/SA
can-i 权限自测第一命令
套路 ClusterRole 定义 + RoleBinding 限定范围
红线 最小权限、拒绝 *、SA 专号专用

本文是「云原生」系列第 17 篇。