协会地址:上海市长宁区古北路620号图书馆楼309-313室
Kubernetes v1.36:服务端分片列表与监听
原文链接:https://kubernetes.io/blog/2026/05/06/kubernetes-v1-36-server-side-sharded-list-and-watch/
随着 Kubernetes 集群增长到上万个节点,监视 Pod 等高基数资源的控制器会面临扩展瓶颈。水平扩展的每个控制器副本都会从 API 服务器接收完整的事件流,为反序列化所有数据付出 CPU、内存和网络开销,却只为了丢弃那些它不负责的对象。增加控制器副本并不能降低单个副本的代价,反而会成倍增加。
Kubernetes v1.36 引入了**服务端分片列表与监视(server-side sharded list and watch)**作为 alpha 特性(KEP-5866)。启用该特性后,API 服务器会在数据源头过滤事件,使每个控制器副本只收到它所属的那部分资源集合。
客户端分片的问题
某些控制器(例如 kube-state-metrics)已经支持水平分片(horizontal sharding)。每个副本被分配 keyspace 的一部分,并丢弃不属于它的对象。虽然这在功能上可行,但它并未减少从 API 服务器流出的数据量:
- N 个副本 × 完整事件流:每个副本都要反序列化并处理每个事件,然后丢弃不需要的部分。
- 网络带宽随副本数线性增长,而非随分片大小增长。
- 用于反序列化的 CPU 对丢弃的部分来说是被浪费的。
服务端分片列表与监视通过将过滤操作上移至 API 服务器来解决此问题。每个副本告诉 API 服务器它拥有哪个哈希范围,API 服务器只发送匹配的事件。
工作原理
该特性在 ListOptions 中新增了一个 shardSelector 字段。客户端使用 shardRange() 函数指定一个哈希范围:
shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000')
API 服务器会计算指定字段的确定性 64 位 FNV-1a 哈希值,并仅返回哈希值落在范围 [start, end) 内的对象。此逻辑同时适用于列表(list)响应和监听(watch)事件流。该哈希函数在所有 API 服务器实例上产生相同的结果,因此该特性可以在多个 API 服务器副本中安全使用。
当前支持的字段路径(field path)为 object.metadata.uid 和 object.metadata.namespace。
在控制器中使用分片监听
控制器通常使用 informer(通知器)来列出和监听资源。为了将工作负载分片(shard),每个副本通过 WithTweakListOptions 将 shardSelector 注入到其 informer 所使用的 ListOptions 中:
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/informers"
)
```go
shardSelector := "shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000')"
factory := informers.NewSharedInformerFactoryWithOptions(client, resyncPeriod,
informers.WithTweakListOptions(func(opts *metav1.ListOptions) {
opts.ShardSelector = shardSelector
}),
)
</code></pre>
<!-- /wp:code -->
<!-- wp:paragraph -->
<p>对于一个 2 副本(2-replica)部署,选择器将哈希空间一分为二:</p>
<!-- /wp:paragraph -->
<!-- wp:code -->
<pre class="wp-block-code"><code>// Replica 0: lower half of the hash space
"shardRange(object.metadata.uid, '0x0000000000000000', '0x8000000000000000')"
```markdown
// 副本1:哈希空间的上半部分
"shardRange(object.metadata.uid, '0x8000000000000000', '0x10000000000000000')"
单个副本也可以使用 || 覆盖非连续范围:
“shardRange(object.metadata.uid, ‘0x0000000000000000’, ‘0x4000000000000000’) || ” +”shardRange(object.metadata.uid, ‘0x8000000000000000’, ‘0xc000000000000000’)”
## 验证服务器支持
当 API 服务器支持分片选择器(shard selector)时,列表响应会在元数据中包含一个 `shardInfo` 字段,该字段会回显已应用的选择器:
{“kind”: “PodList”,”apiVersion”: “v1″,”metadata”: {“resourceVersion”: “10245”,”shardInfo”: {“selector”: “shardRange(object.metadata.uid, ‘0x0000000000000000’, ‘0x8000000000000000’)”}},”items”: […]}
如果`shardInfo`缺失,说明服务器未遵循分片选择器(shard selector),客户端接收到了完整且未经筛选的集合。在这种情况下,客户端应做好处理完整结果集的准备,例如通过应用客户端过滤机制来丢弃其分配分片范围之外的对象。
## 参与进来
该功能仍处于Alpha阶段,需要在API服务器上启用`ShardedListAndWatch`特性门控(feature gate)。我们期待来自控制器开发者以及运行大型集群的运维人员的反馈。
- [KEP-5866:服务端分片列表与监听(Server-Side Sharded List and Watch)](https://github.com/kubernetes/enhancements/issues/5866)
- [API概念:分片列表与监听(Sharded list and watch)](https://kubernetes.io/docs/reference/using-api/api-concepts/#sharded-list-and-watch)
- [SIG API Machinery](https://github.com/kubernetes/community/tree/master/sig-api-machinery)
如有疑问或反馈,请加入[Kubernetes Slack](https://slack.k8s.io/)的`#sig-api-machinery`频道。







