☰
Kubernetes RBAC 实战指南:四类对象一张决策表,5 分钟给集群装上门禁
2026/11/4 2:11:32 网站建设 项目流程

Kubernetes RBAC 实战指南:四类对象一张决策表,5 分钟给集群装上门禁

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

你在 kubernetes-handbook 仓库里翻到 concepts/rbac.md,想给新入职的同事讲清楚:集群里"谁、在哪个命名空间、能对什么资源做什么"到底怎么管起来?Kubernetes RBAC 就是回答这个问题的门禁系统。Role、ClusterRole、RoleBinding、ClusterRoleBinding四个对象,加上一组kubectl命令,就能把权限发到你想要的粒度。本文给决策表、速查规则和一条升级老集群的灰度路线。

先打开开关:为什么弃用 AlwaysAllow 和 ABAC

默认状态下 API Server 的AlwaysAllow模式对任何已认证用户放行所有请求,不少装机工具还默认这么开。仓库里的 guide/kubernetes-security-best-practice.md 给的修正姿势很直接:

--authorization-mode=RBAC --anonymous-auth=false

老一代方案 ABAC 的痛点在运维侧:策略是一份躺在 master 节点上的文件,改一条规则要 SSH 上去改文件,然后重启 API Server。RBAC 把策略变成了 Kubernetes 自己的 API 对象,用kubectl就能创建、修改、删除,不用碰节点文件系统。更妙的是递归性——RBAC 可以给某个用户授予"管理授权"的权限,等于把发卡台也开放了。仓库中 practice/rbac-support-in-kubernetes.md 用真实集群验证过这一点:系统角色覆盖足够,集群可以完全跑在 RBAC 管理之下。

旧清单里apiVersion多为rbac.authorization.k8s.io/v1beta1(本文基于 Kubernetes 1.6 时代资料),新版本改成rbac.authorization.k8s.io/v1即可,字段语义没变。

一个心智模型:授权三问

遇到任何授权需求,先问三个问题:

  1. 谁?——Subject,三种取值:User、Group、ServiceAccount。
  2. 能干什么?——权限规则,装进Role或ClusterRole。规则只累加,没有"否定"规则,写不了"允许除了 X 以外的一切"。
  3. 在哪干?——范围,由RoleBinding或ClusterRoleBinding决定。

类比:Role像门禁卡的样式——写清楚能刷开哪些门;Binding才是发卡的动作,把样式交给具体的人。ClusterRole则是公司级通行卡的样式:在总部定义一次,各楼层随时复用。

四类对象怎么选:一张决策表

对象一句话定位
Role只在单一命名空间内定义权限规则
ClusterRole集群级规则,覆盖集群范围资源(如 node)、非资源 endpoint(如/healthz)、跨命名空间查询
RoleBinding在自己所在命名空间内发卡,可引用同命名空间的Role或任意ClusterRole
ClusterRoleBinding全集群发卡,只能引用ClusterRole

最容易踩的坑是最后一行组合:RoleBinding引用ClusterRole时,权限范围被收窄到 Binding 所在的命名空间。角色说的是"能读 secret",Binding 说的是"只在 development 里"。

最短示例——给 default 命名空间的 jane 发一张只读 pod 的卡:

kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] # "" 代表 core API group resources: ["pods"] verbs: ["get", "list", "watch"]
kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: read-pods subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io

权限规则速查:rules 里每个字段怎么写

rules是权限的最小单位,一条规则四要素:

字段写法要点
apiGroups空字符串""= core 组;可列多个,如["extensions", "apps"]
resources资源名按 API URL 中的写法;子资源用斜线拼接
verbsgetlistwatchcreateupdatepatchdelete等
nonResourceURLs非资源 endpoint,*是后缀通配符,只能写在ClusterRole

子资源是新手最常忘的:看 pod 日志的 endpoint 是/pods/{name}/log,所以要写pods/log才算授权:

rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]

resourceNames把权限钉到具体实例上,但有个硬限制:设了resourceNames,动词只能是get、delete、update、patch。list、watch、create、deletecollection 的请求 URL 里根本不出现资源名,规则匹配不上。

rules: - apiGroups: [""] resources: ["configmaps"] resourceNames: ["my-configmap"] verbs: ["get", "update"]

其余常见写法:

# 跨两个组读写 deployments rules: - apiGroups: ["extensions", "apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# 非资源 endpoint(ClusterRole 专用,需配 ClusterRoleBinding) rules: - nonResourceURLs: ["/healthz", "/healthz/*"] verbs: ["get", "post"]

动手授权:kubectl 三种姿势

姿势一:一条命令发 namespace 内的卡

kubectl create rolebinding bob-admin-binding --clusterrole=admin --user=bob --namespace=acme

把--user换成--group或--serviceaccount=acme:myapp就是给组、给服务账户发卡。

姿势二:YAML 声明式

上一节的 Role + RoleBinding 示例落盘成两个文件,kubectl apply -f即可。适合进 Git 做版本管理。

姿势三:全集群发卡

kubectl create clusterrolebinding root-cluster-admin-binding --clusterrole=cluster-admin --user=root

⚠️cluster-admin是超级用户权限。给个人用户发全集群卡之前,先问自己三次是不是必须。

实战:devuser 只准进 dev 和 test 两个命名空间

仓库里 guide/kubectl-user-authentication-authorization.md 是完整链路:

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json \ -profile=kubernetes devuser-csr.json | cfssljson -bare devuser

生成devuser.pem/devuser-key.pem后,三步组装 kubeconfig:

kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/ssl/ca.pem \ --embed-certs=true --server=https://172.20.0.113:6443 --kubeconfig=devuser.kubeconfig
kubectl config set-credentials devuser --client-certificate=/etc/kubernetes/ssl/devuser.pem \ --client-key=/etc/kubernetes/ssl/devuser-key.pem --embed-certs=true --kubeconfig=devuser.kubeconfig
kubectl config set-context kubernetes --cluster=kubernetes --user=devuser \ --namespace=dev --kubeconfig=devuser.kubeconfig

授权两条命令:

kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=test

验证结果立竿见影——devuser 去 default 命名空间看 pod:

Error from server (Forbidden): User "devuser" cannot list pods in the namespace "default". (get pods)

dev 和 test 里畅通无阻,default 直接 403。admin角色"限定在 RoleBinding 所在命名空间内生效"的语义,到这里就闭环了。仓库的 tools/create-user/ 还带了个一键建用户脚本,可参考 说明。

内置角色速查卡:cluster-admin / admin / edit / view

API Server 启动时会自带一套角色。面向用户的四张"标准卡":

角色用在哪能力边界
cluster-adminClusterRoleBinding(或RoleBinding)超级用户全集群;用在RoleBinding时限该命名空间,含命名空间本身
adminRoleBinding命名空间内大部分资源读写不能写 resource quota 和 namespace 本身
editRoleBinding命名空间内大部分对象读写不能看角色和角色绑定
viewRoleBinding命名空间内大部分对象只读不能看角色、角色绑定,也不能看 secret

view读不了 secret 是刻意设计:secret 里存着服务账户 token,谁能读 secret,谁就能拿到 token 冒充服务账户。给view放行 secret 等于开了权限扩散的口子。

带system:前缀的资源是另一类:system:kube-scheduler、system:node、system:controller:*这些是控制面组件自用的,API Server 每次启动会自动补齐缺失的权限。别手改——system:node里写着 kubelet 能读所有 secret,改坏了节点直接不工作。想停掉自动修复,把注解rbac.authorization.kubernetes.io/autoupdate设为false,但通常没必要。

服务账户最小权限阶梯:5 档从安全到危险

先记住命名规则:服务账户认证时的用户名是system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT),同属system:serviceaccounts和system:serviceaccounts:(NAMESPACE)两个组。这就是--group能批量授权的底层逻辑(详见 guide/authentication.md)。

从最安全到最危险,五档如下:

第 1 档:专用服务账户 + 最小角色(推荐)

kubectl create rolebinding my-sa-view --clusterrole=view \ --serviceaccount=my-namespace:my-sa --namespace=my-namespace

风险:几乎没有。前提是你真的建了服务账户并让应用在 pod spec 里指定serviceAccountName。

第 2 档:给 default 服务账户发卡

kubectl create rolebinding default-view --clusterrole=view \ --serviceaccount=my-namespace:default --namespace=my-namespace

风险:命名空间内没写serviceAccountName的 pod 全都继承这份权限。仓库里 manifests/heapster/heapster-rbac.yaml 和 manifests/dashboard/dashboard-rbac.yaml 就是这档的老写法——给 kube-system 里的服务账户绑cluster-admin,能跑,但权限远超监控所需。

第 3 档:命名空间内全部服务账户

kubectl create rolebinding serviceaccounts-view --clusterrole=view \ --group=system:serviceaccounts:my-namespace --namespace=my-namespace

风险:新上线的应用自动拿到权限,回收时要记得清。

第 4 档:全集群服务账户只读(不鼓励)

kubectl create clusterrolebinding serviceaccounts-view --clusterrole=view \ --group=system:serviceaccounts

风险:管理成本换安全边界,一个命名空间的事会外溢到全集群。

第 5 档:全集群服务账户超级用户(强烈不推荐)

kubectl create clusterrolebinding serviceaccounts-cluster-admin --clusterrole=cluster-admin \ --group=system:serviceaccounts

风险:任何能读 secret 的人、任何能注入容器的人,都能借 token 拿到集群最高权限。

两道安全红线

红线一:API 层挡提权,连授权器没开都生效

RBAC API 内置一条约束:你手里没有的权限,写不进新角色和新绑定。user-1 读不了集群范围的 secret,他就创建不出"含读 secret 权限"的ClusterRole,也绑不了引用该角色的ClusterRoleBinding。检查在 API 层做,RBAC 授权器开着不开着都拦。

绑定权限可以显式授予,不要求本人拥有全部权限。给clusterroles资源加bind动词,再用resourceNames圈定范围:

kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: role-grantor-binding namespace: user-1-namespace subjects: - kind: User name: user-1 apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: role-grantor apiGroup: rbac.authorization.k8s.io
kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: name: role-grantor rules: - apiGroups: ["rbac.authorization.k8s.io"] resources: ["rolebindings"] verbs: ["create"] - apiGroups: ["rbac.authorization.k8s.io"] resources: ["clusterroles"] verbs: ["bind"] resourceNames: ["admin", "edit", "view"]

user-1 现在能把admin、edit、view绑定给他人,但绑不了cluster-admin。首次初始化第一个角色时,这个机制会形成死锁,解法是用system:masters组(默认绑定到cluster-admin)的凭证来落第一笔授权。

红线二:能读 secret,就能冒充服务账户

服务账户 token 就存在 secret 里,任何读到这个 secret 的主体都可以拿着 token 以该服务账户身份访问 API。所以两件事要同时做:给服务账户发权限时收敛动词和资源,给"读 secret"这个动作设更高的门槛。这也是view刻意屏蔽 secret 的原因。

老集群升级:ABAC 灰度切 RBAC

1.5 及更早的集群多半开着宽泛 ABAC 策略,直接换 RBAC 会把存量 workload 挡在门外。灰度路线:

  1. API Server 同时挂两个授权器,旧策略文件继续生效:
--authorization-mode=RBAC,ABAC --authorization-policy-file=mypolicy.jsonl
  1. 请求先问 RBAC,被拒再落 ABAC,等于"任一方放行即放行"。把日志开到--v=2,被 RBAC 拒掉的请求会打RBAC DENY:前缀,照着清单逐条补角色。

  2. 日志里不再出现拒绝记录,摘掉 ABAC。

⚠️ 并行期有个陷阱:当初 ABAC 放行的请求,摘掉 ABAC 后未必有对应角色兜底。建议先拿一个命名空间灰度验证,再全量切换。

如果实在等不起,还有一条宽泛过渡绑定(practice/rbac-support-in-kubernetes.md 中有记录):

kubectl create clusterrolebinding permissive-binding --clusterrole=cluster-admin \ --user=admin --user=kubelet --group=system:serviceaccounts

⚠️ 这条命令等于把集群钥匙发给所有服务账户:容器里的任何应用自动持有 SA 凭据,可读 secret、可改权限。只配当过渡期止血贴,别留到生产长期运行。

收尾自检清单

#检查项目标状态
1授权模式--authorization-mode=RBAC,无AlwaysAllow残留
2匿名认证--anonymous-auth=false
3应用身份每个应用专用 ServiceAccount,不裸奔在 default 上
4动词收敛读多写少的场景不给create/delete,从最小动词集起步
5secret 读权限只发给必须方;审计谁拿着 secrets 的get
6cluster-admin只给运维通道,不发全集群服务账户
7系统资源没手改system:前缀的 ClusterRole/Binding 和kubernetes.io/bootstrapping标记资源
8升级收尾ABAC 已摘除,RBAC DENY:日志清零

参考

  • concepts/rbac.md:RBAC 概念全量文档(本文骨架出处)
  • concepts/serviceaccount.md:服务账户机制
  • concepts/authentication-and-permission.md:认证与授权总览
  • guide/authentication.md:用户与身份认证授权
  • guide/kubectl-user-authentication-authorization.md:devuser 证书 + kubeconfig + 授权实战
  • guide/kubernetes-security-best-practice.md:集群安全配置最佳实践
  • guide/tls-bootstrapping.md:节点引导中的system:组用法
  • practice/rbac-support-in-kubernetes.md:真实集群 RBAC 落地记录
  • manifests/heapster/heapster-rbac.yaml、manifests/dashboard/dashboard-rbac.yaml:加载项绑定cluster-admin的真实清单
  • tools/create-user/:批量建用户与授权脚本

【免费下载链接】kubernetes-handbookKubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南项目地址: https://gitcode.com/gh_mirrors/ku/kubernetes-handbook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询