协会地址:上海市长宁区古北路620号图书馆楼309-313室
Kubernetes v1.36:细粒度 Kubelet API 授权晋升为 GA
原文链接:https://kubernetes.io/blog/2026/04/24/kubernetes-v1-36-fine-grained-kubelet-authorization-ga/
代表 Kubernetes SIG Auth 和 SIG Node,我们很高兴地宣布:细粒度的 kubelet API 授权在 Kubernetes v1.36 中正式毕业为通用可用性(GA)!
KubeletFineGrainedAuthz 特性门控最初在 Kubernetes v1.32 作为可选的 Alpha 特性引入,随后在 v1.33 升级为 Beta(默认启用)。现在,该特性已正式可用,特性门控被锁定为启用状态。该特性实现了对 kubelet HTTPS API 更精确、最小权限的访问控制,取代了为常见监控和可观测性场景授予过于宽泛的 nodes/proxy 权限的需求。
动机:nodes/proxy 问题
kubelet 暴露了一个 HTTPS 端点,其中包含多个 API,可访问不同敏感程度的数据,包括 Pod 列表、节点指标、容器日志,以及关键的在运行容器中执行命令的能力。
在此特性之前,kubelet 授权采用粗粒度模型。当启用 Webhook 授权时,几乎所有 kubelet API 路径都被映射到单一的 nodes/proxy 子资源。这意味着任何需要从 kubelet 读取指标或健康状态的工作负载都必须拥有 nodes/proxy 权限,而同样的权限也允许在节点上运行的任何容器中执行任意命令。
这有什么问题?
将 nodes/proxy 授予监控代理、日志收集器或健康检查工具违反了最小权限原则。如果这些工作负载中的任何一个被攻破,攻击者将能够在节点上的每个容器中执行命令。nodes/proxy 权限实际上是一种节点级超级用户能力,广泛授予它会极大地扩大安全事件的爆炸半径。
社区多年来一直清楚理解这个问题(参见 kubernetes/kubernetes#83465),这也是此增强功能 KEP-2862 背后的主要驱动力。
nodes/proxy GET WebSocket RCE 风险
实际情况比表面看起来更严重。安全研究人员在 2026 年初 证明,仅凭 nodes/proxy GET(通常授予监控工具的最小只读权限)就可以被滥用来在可达节点上的任何 Pod 中执行命令。
根本原因是 WebSocket 连接的工作方式与 kubelet 将 HTTP 方法映射到 RBAC 动词的方式之间存在不匹配。WebSocket 协议 (RFC 6455) 要求初始连接握手使用 HTTP GET 请求。kubelet 将此 GET 映射到 RBAC get 动词并授权该请求,而没有进行二次检查以确认后续写操作也具备 CREATE 权限。使用像 websocat 这样的 WebSocket 客户端,攻击者可以直接访问 kubelet 在端口 10250 上的 /exec 端点并执行任意命令。
websocat --insecure \
--header "Authorization: Bearer $TOKEN" \
--protocol v4.channel.k8s.io \
"wss://$NODE_IP:10250/exec/default/nginx/nginx?output=1&error=1&command=id"
```bash
uid=0(root) gid=0(root) groups=0(root)
细粒度 kubelet 授权:工作原理
启用 KubeletFineGrainedAuthz 后,kubelet 现在会在回退到 nodes/proxy 子资源之前,执行一次额外的、更具体的授权检查。几个常用的 kubelet API 路径被映射到它们各自的专用子资源:
kubelet API | 资源(Resource) | 子资源(Subresource) |
|---|---|---|
/stats/* | nodes | stats |
/metrics/* | nodes | metrics |
/logs/* | nodes | log |
/pods | nodes | pods, proxy |
/runningPods/ | nodes | pods, proxy |
/healthz | nodes | healthz, proxy |
/configz | nodes | configz, proxy |
/spec/* | nodes | spec |
/checkpoint/* | nodes | checkpoint |
| 所有其他路径 | nodes | proxy |
对于现在拥有细粒度子资源的端点(/pods、/runningPods/、/healthz、/configz),kubelet 首先针对特定子资源发送一个 SubjectAccessReview。如果该检查成功,则请求被授权。如果失败,kubelet 会使用粗粒度的 nodes/proxy 子资源重试,以实现向后兼容。
这种双重检查方法确保了平滑的迁移路径。拥有 nodes/proxy 权限的现有工作负载可以继续工作,而新部署可以从一开始就采用最小权限访问。
实际意义
考虑一个需要从 kubelet 抓取 /metrics 的 Prometheus 节点导出器(node exporter)或监控 DaemonSet。以前,你需要一个类似这样的 RBAC ClusterRole:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus-node-exporter
rules:
- apiGroups: [""]
resources: ["nodes/proxy"]
verbs: ["get"]
# Old approach: overly broad
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-agent
rules:
- apiGroups: [""]
resources: ["nodes/proxy"]
verbs: ["get"]
这赋予了监控代理(monitoring agent)远超其所需的访问权限。通过细粒度授权(fine-grained authorization),现在可以精确地限定权限范围:
# New approach: least privilege
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: monitoring-agent
rules:
- apiGroups: [""]
resources: ["nodes/metrics", "nodes/stats"]
verbs: ["get"]
监控代理现在可以从 kubelet 读取指标(metrics)和统计信息(stats),而无需具备在容器中执行命令的能力。
更新后的 system:kubelet-api-admin ClusterRole
当启用 RBAC 授权时,内置的 system:kubelet-api-adminClusterRole 会自动更新,包含所有新的细粒度子资源(fine-grained subresources)的权限。这确保了已经使用此角色的集群管理员(包括 API 服务器的 kubelet 客户端)无需任何手动配置更改即可继续拥有完全访问权限。
该角色现在包含以下权限:
nodes/proxynodes/statsnodes/metricsnodes/lognodes/specnodes/checkpointnodes/configznodes/healthznodes/pods
升级注意事项
由于 kubelet 执行双重授权检查(先检查细粒度权限,然后回退到 nodes/proxy),升级到 v1.36 对大多数集群来说应该是无缝的:
- 现有工作负载 拥有
nodes/proxy权限的无需更改即可继续工作。回退到nodes/proxy确保了向后兼容性。 - API 服务器 始终通过
system:kubelet-api-admin拥有nodes/proxy权限,因此无论特性门控(feature gate)状态如何,kube-apiserver到kubelet的通信都不受影响。 - 混合版本集群 能够优雅处理。如果
kubelet支持细粒度授权但 API 服务器不支持(反之亦然),nodes/proxy权限将作为回退。
验证特性已启用
你可以通过检查 kubelet 指标端点(metrics endpoint)来确认该特性在给定节点上是否已激活。由于端口 10250 上的指标端点需要授权,你首先需要为发起请求的 Pod 或 ServiceAccount 创建适当的 RBAC 绑定。
步骤 1:创建 ServiceAccount 和 ClusterRole
apiVersion: v1
kind: ServiceAccount
metadata:
name: kubelet-metrics-checker
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: kubelet-metrics-reader
rules:
- apiGroups: [""]
resources: ["nodes/metrics"]
verbs: ["get"]
步骤 2:将 ClusterRole(集群角色)绑定到 ServiceAccount(服务账户)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubelet-metrics-checker
subjects:
- kind: ServiceAccount
name: kubelet-metrics-checker
namespace: default
roleRef:
kind: ClusterRole
name: kubelet-metrics-reader
apiGroup: rbac.authorization.k8s.io
应用两个清单(manifests):
kubectl apply -f serviceaccount.yaml
kubectl apply -f clusterrole.yaml
kubectl apply -f clusterrolebinding.yaml
步骤 3:使用 ServiceAccount(服务账户)运行一个 Pod(容器组)并检查功能标志
kubectl run kubelet-check \
--image=curlimages/curl \
--serviceaccount=kubelet-metrics-checker \
--restart=Never \
--rm -it \
-- sh
然后,在 pod(容器组)内部,获取节点 IP(节点 IP 地址)并查询 metrics 端点(指标端点):
# Get the token
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# 查询 kubelet 指标并过滤特性门控
curl -sk \
--header "Authorization: Bearer $TOKEN" \
https://$NODE_IP:10250/metrics \
| grep kubernetes_feature_enabled \
| grep KubeletFineGrainedAuthz
如果该特性已启用,你应该会看到类似如下的输出:
kubernetes_feature_enabled{name="KubeletFineGrainedAuthz",stage="GA"} 1
注意: 将
$NODE_IP替换为你想要检查的节点 IP 地址。你可以通过kubectl get nodes -o wide获取节点 IP。
从 Alpha 到 GA 的历程
| 发布版本 | 阶段 | 详情 |
|---|---|---|
| v1.32 | Alpha | 引入特性门控 KubeletFineGrainedAuthz,默认禁用 |
| v1.33 | Beta | 默认启用;对 /pods、/runningPods/、/healthz、/configz 进行细粒度检查 |
| v1.36 | GA | 特性门控锁定为启用;细粒度 kubelet 授权始终生效 |
下一步计划?
随着细粒度 kubelet 授权进入 GA 阶段,Kubernetes 社区可以开始推荐并最终强制要求使用特定子资源(subresource)替代 nodes/proxy 来执行监控和可观测性工作负载。这一迁移的紧迫性源于研究表明 nodes/proxy GET 可能通过 WebSocket 协议被滥用,导致未记录日志的远程代码执行。该风险存在于数十个广泛部署的 Helm Chart 的默认 RBAC 配置中。随着时间的推移,我们预计:
- 生态系统采用: Prometheus、Datadog 代理等监控工具以及其他
DaemonSet可以更新其默认 RBAC 配置,使用nodes/metrics、nodes/stats和nodes/pods替代nodes/proxy。这将直接消除这些工作负载的 WebSocket RCE 攻击面。 - 策略执行: 准入控制器(Admission Controller)和策略引擎(Policy Engine)可以在存在细粒度替代方案时标记或拒绝授予
nodes/proxy的 RBAC 绑定,帮助组织大规模采用最小权限访问。 - 弃用路径: 随着采用率的增长,
nodes/proxy最终可能会在监控场景中被弃用,从而进一步减少 Kubernetes 集群的攻击面。
参与贡献
这一增强功能由 SIG Auth 和 SIG Node 推动。如果你有兴趣为 Kubernetes 的安全和授权功能做出贡献,请加入我们:
- SIG Auth
- SIG Node
- Slack:
#sig-auth和#sig-node - KEP-2862:细粒度 Kubelet API 授权
我们期待听到你对这一功能的反馈和使用体验!







