前言
集群一旦多人使用,“谁都能改一切"就是定时炸弹。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 → 排查泄密的关键证据
九、设计原则
- 最小权限:从只读开始,按报错逐步加(
can-i随手验证) - namespace 即边界:多团队 → 多 ns + 各自 Role
- 宁可 RoleBinding 也不 ClusterRoleBinding:全局权限是奢侈品
- 禁用通配:
resources: ["*"]/verbs: ["*"]出现就该被 review - SA 一应用一个,别共用 default
- 定期审计:
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 篇。