本节摘要:RBAC 用三种对象表达"谁能对什么做什么":Role 定义一田之内的一组权限,RoleBinding 把角色授予用户组或 ServiceAccount,ClusterRole 与 ClusterBinding 负责跨田权限。程序以 ServiceAccount 为身份进田,最小权限是总原则。本节给书屋的值班同事发一张"只读巡田卡",给备份程序发一张"恰好够用"的身份卡。
到此为止书屋所有人共用一个管理员身份——谁都能删苗、改闸、开农药柜。团队来了新同事小周,要求只有两条:能看田里的状况,绝不能误伤生产。口头约定挡不住手指,**RBAC(基于角色的访问控制)**把权限变成台账里的机制。它的模型只需要回答三个问题:
三个问题组合成三件套:Role(在指定田内的一组"能对什么做什么")、RoleBinding(把角色发给谁)、需要跨田时用 ClusterRole(不带田界的角色)配 ClusterRoleBinding。授权的粒度可以精确到"生产田里的 Pod 只读"这种程度。
# 巡田卡:生产田的只读角色 apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: field-viewer namespace: greenlib-prod rules: - apiGroups: [""] # 核心组:pods services 等 resources: ["pods", "pods/log", "services", "deployments"] verbs: ["get", "list", "watch"] # 只许看 不许动 - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list"] --- # 发卡:把角色绑给小周所在的组 apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: viewer-zhou namespace: greenlib-prod subjects: - kind: Group name: greenlib-oncall # 值班组:成员由登录系统维护 roleRef: kind: Role name: field-viewer apiGroup: rbac.authorization.k8s.io
kubectl apply -f viewer-rbac.yaml # role.rbac.authorization.k8s.io/field-viewer created # rolebinding.rbac.authorization.k8s.io/viewer-zhou created # 用小周的身份验证:看 得 行 改 不行 kubectl auth can-i list pods -n greenlib-prod --as-group=greenlib-oncall # yes kubectl auth can-i delete pods -n greenlib-prod --as-group=greenlib-oncall # no # auth can-i 是权限的自检台 干净利落
kubectl auth can-i 值得单独表扬:不用真刀真枪试,就能回答"某人能不能做某事",发卡前先自检一遍是的好习惯。
人不该拿管理员钥匙,程序更不该。第六章种下的备份 CronJob 当时偷偷用了管理凭据,现在补一张恰好够用的身份卡:ServiceAccount 就是程序版的门禁卡。
# 备份程序的身份卡 apiVersion: v1 kind: ServiceAccount metadata: name: backup-agent namespace: greenlib-prod --- # 这个身份能做什么:创建备份产物记录(这里给个最小示意:读配置与建任务) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: backup-role namespace: greenlib-prod rules: - apiGroups: ["batch"] resources: ["jobs"] verbs: ["create", "get", "list"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: backup-binding namespace: greenlib-prod subjects: - kind: ServiceAccount # 发给程序身份 而不是人 name: backup-agent roleRef: kind: Role name: backup-role apiGroup: rbac.authorization.k8s.io
# CronJob 模板里挂上这张卡(节选) jobTemplate: spec: template: spec: serviceAccountName: backup-agent # 声明身份 containers: - name: backup image: greenlib/db-tools:1.2
kubectl auth can-i create jobs -n greenlib-prod --as=system:serviceaccount:greenlib-prod:backup-agent # yes kubectl auth can-i delete deployments -n greenlib-prod --as=system:serviceaccount:greenlib-prod:backup-agent # no # 备份程序能干活 但拿它的身份也删不了任何苗
这就是最小权限的完整闭环:程序被攻破时,攻击者拿到的只是一张"能建备份任务"的卡,而不是整片田的地契。第五章那句"农药柜要配更严的读权限"在此兑现——Secret 的读取本身也是一项 verbs,可以只发给需要的身份。
| 对象 | 作用域 | 典型用法 |
|---|---|---|
| Role 加 RoleBinding | 限一块田 | 部门级、环境级授权(本节主力) |
| ClusterRole 加 RoleBinding | 角色全局定义 授权限一块田 | 复用"只读"这类通用角色到多块田 |
| ClusterRole 加 ClusterRoleBinding | 全集群 | 节点组件、集群管理员(慎发) |
经验法:先 Role 后 Cluster。多数权限需求其实只关乎一两块责任田;全局权限像 master 钥匙,发出去容易收回来难。系统自带几个现成 ClusterRole(view、edit、admin)可作起步模板,自建细粒度角色时照抄它们的 rules 结构最省事。
⚠️ 常见坑两枚。其一,RoleBinding 里 roleRef 写错 apiGroup 或 kind,apply 时报错找不到角色——rbac 打头的 apiGroup 全名是 rbac.authorization.k8s.io,照抄本节清单别手打。其二,默认 ServiceAccount 没配卡也能跑苗(多数集群默认无权限),于是有人图省事给默认身份绑 ClusterAdmin——这等于给全田的苗发了万能钥匙,一次镜像投毒就全盘皆输。程序身份一律单独建卡。