Kubernetes 集群可扩展性实战指南:解读 SIG Scalability FAQ 中的 QPS、对象大小与客户端设计
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
导读
本指南基于 Kubernetes 官方社区仓库中 SIG Scalability 的 configs-and-limits/faq.md 整理而成,围绕集群运维者与开发者最常问的五个可扩展性问题展开:kube-apiserver 的 QPS 上限、API 对象理想大小、客户端应用的可扩展性编码方式、可扩展性测试集群的搭建方法,以及 HA 控制平面测试缺失的原因。读完本文,你将掌握判断集群负载是否健康的量化依据(如 20kB 对象大小规则、5000 节点测试基准),并能在自己的集群与客户端代码中落实这些经过官方测试验证的实践。文中还会结合仓库中的 thresholds.md、provider-configs.md 与 slos.md 等配套文档,给出更完整的规模阈值与控制面配置参考。
一、kube-apiserver 到底能扛多少 QPS?为什么官方没有标准答案
这是社区中最常被问到的问题,但 SIG Scalability 的结论非常明确:不存在单一答案。原因在于每个 Kubernetes 请求的"成本"可能差异巨大——同一个 kube-apiserver 在某种使用模式下能处理 N 个 QPS,换一种使用模式可能连 N/5 都处理不了。
1.1 请求类型带来的成本差异
差异在直观层面就非常明显:
- GET vs LIST:
GET my-pod(取单个对象)与LIST all pods(列出全部 Pod)的负载完全不同,LIST 需要遍历、序列化并返回大量对象。 - 只读 vs 变更:
GET my-pod与POST my-pod的成本也天差地别,变更请求涉及准入控制、存储写入与事件广播等多个环节。
1.2 即使同为写请求,成本也可能相差几个数量级
即便只聚焦单一请求类型(比如只有 POST 或只有 PUT),成本差异仍可达到数量级,主要来自两个因素:
- 对象大小(size of the object):一个约 300B 的小型 Lease 对象与一个 1MB 的大型自定义 CRD 对象,存储、序列化与校验成本完全不在一个量级。
- 扇出(fan-out):如果某个对象正被 N 个 watcher 监听,那么处理该对象任意一次变更请求的成本就要乘以 N。这个乘数效应作为单次 API 调用的发送方是无法完全控制的——你更新一个对象,却可能牵动数百个监听者。
正因如此,官方刻意不给出任何具体 QPS 数值:一个配置得当的集群可能轻松处理数千 QPS,而一个"看起来相同"的集群,若请求本身非常昂贵,可能连几十 QPS 都会吃力。判断负载能力必须结合具体请求画像,而不是套用一个神奇数字。
二、API 对象的理想大小:20kB 规则与 1.5MB 硬限制
2.1 唯一的硬限制:1.5MB
从技术上讲,Kubernetes 对单个对象大小的唯一硬性限制是1.5MB(这一限制同样记录在 thresholds.md 的内置资源阈值表中,Size per object 的 resource/cluster 级阈值均为 1.5MB)。但官方明确建议:除非绝对必要,否则不要逼近这个上限。
2.2 20kB:性能最优区间
在典型使用场景下,绝大多数对象的大小不会超过~20kB。这个区间是测试覆盖最充分、大量优化(基于现有测试所做的优化)默认假设的工作区间。也就是说,Kubernetes 的性能优化与规模承诺,本质上都是围绕"对象普遍小于 20kB"这一前提设计的。
2.3 反模式案例:用大对象聚合"子对象"
超过 20kB 的个体对象,绝大多数都来自同一种模式:把多个"子对象"塞进单个大对象。核心 Kubernetes 中最典型的例子是EndpointsAPI——它把一个 Service 背后的所有端点聚合进单一对象。这种模式被证明在多方面存在问题:
- 对象膨胀:对象变得很大,即使只改动一个子对象,从系统整体角度看也变得昂贵;
- 争用点:当不同 Agent 各自更新不同的子对象时,同一对象成为争用点(contention point);
- 浪费:由于只能 get/watch 完整对象,很多 Agent 其实并不需要所有子对象的信息,却被迫接收/传输整份数据。
为此,Kubernetes 引入了EndpointSliceAPI来取代Endpoints的大对象模式。如果你的用例面临单体对象过大问题,EndpointSlice正是官方推荐探索的方向。
2.4 规模/性能视角的黄金法则
综合以上分析,从可扩展性角度出发的规则总结为三条:
- 尽量把对象大小控制在~20kB以下;
- 如果确实需要更大,100kB 以内且对象不频繁变更是可以接受的;
- 如果无法把对象控制在 100kB 以下,请联系SIG Scalability讨论用例,共同寻找性能可行的方案。
三、客户端应用如何编码以提升可扩展性
如第一节所述,LIST 请求尤其昂贵。当要处理的对象数量达到"几千个小对象"或"几百个大对象"的量级时,客户端应用的编码方式将直接决定集群能否扩展。SIG Scalability 给出了 7 条明确指南:
3.1 定义新资源类型时先评估对象规模预期
在定义新的 CRD 时,要考虑未来将存在的 CR 对象数量级,参照官方针对 CRD 提出的 small / medium / large 规模目标指南来设计。这是一条前置设计约束,而非事后优化。
3.2 LIST 的负载取决于"存在多少对象",而非"返回多少对象"
进行 LIST 操作时,etcd 与 API Server 的负载主要取决于集群中实际存在的对象总数,而不是本次返回的结果数。这意味着:即使你通过 field selector 过滤后只取回少量结果,负载依旧按全量对象计算。(唯一的例外是通过metadata.name获取单个对象,该操作是快速的。)
3.3 优先使用 Informer,避免重复 LIST
如果代码需要在内存中维护对象的最新列表,应尽量避免反复发起 LIST 调用,改用大多数 Kubernetes 客户端库提供的Informer类。Informer 自动组合 LIST 与 WATCH 功能,以高效的方式维护内存集合,是官方最推荐的模式。
3.4 无法使用 Informer 时,考虑是否需要强一致性
如果 Informer 不适合你的场景,先自问:你真的需要强一致性吗?是否需要看到"查询发出那一瞬间"的最新数据?如果不需要,可以设置ResourceVersion=0,让请求由 API Server 的缓存(而非 etcd)直接服务。务必仔细阅读官方关于 Resource Versions 的 API 概念文档,理解这对数据新鲜度的影响,再做出权衡。
3.5 分块读取大结果集
若既无法用 Informer,也无法用 API Server 缓存,那么务必按块(chunk)读取大结果集,避免一次性把海量对象全部拉回内存。
3.6 控制 LIST 的频率
无法使用 Informer 时,还要审视应用 LIST 资源的频率:读完一个大 LIST 的最后一个对象后,不要立即重新查询同一列表,应等待一段时间。按需查询,绝不比实际需要更频繁地 LIST。
3.7 考虑客户端实例数量
最后,认真评估客户端应用的实例数量:单个 controller 列出对象,与每个节点上的 Pod(如 DaemonSet)都周期性列出同样的大对象,负载差异是巨大的。如果会有大量客户端实例周期性 LIST 大量对象,你的方案将无法扩展到大规模集群。
四、如何搭建可扩展性测试集群:100 节点与 5000 节点基准
4.1 双规模测试策略
SIG Scalability 在两个规模层级上测试 Kubernetes:100 节点与5000 节点。由于可扩展性是一个多维问题,测试还会尽量覆盖对象数量、变更频率等其他维度。所有可扩展性测试均运行在**单一大控制平面机器(VM)**上——所有控制平面组件都在这一台机器上运行,这台大机器足以支撑 5000 节点集群的负载测试。
4.2 5000 节点测试的控制平面规格
用于测试 5000 节点集群的控制平面 VM 规格为:
- 64 核 CPU
- 256 GB 内存
- 200 GB SSD 持久化磁盘
由于主流公有云通常提供更大规格的机型,作为用户你在硬件选择上仍有不少余量。
4.3 Kubemark:模拟节点的大规模测试
除了真实集群,SIG 还运行Kubemark 模拟集群:控制平面 VM 配置与常规集群一致,但大量"模拟节点"运行在同一台 VM 上。为模拟 5000 节点集群,Kubemark 约需80 台机器、每台运行约 60 个 hollow-node(空心节点)。目前这类模拟集群属于辅助手段,版本发布验证仍基于 GCE 云提供商上的真实集群。Kubemark 属于 SIG Scalability 的测试框架子项目之一,相关说明见 sig-scalability/README.md。
4.4 补充:各云提供商的控制平面机型参考
仓库中的 provider-configs.md 记录了不同基础设施提供商的候选机型,可作为搭建类似测试/生产控制平面的参考:
| Provider | Machine type | Cores | Memory | 备注 |
|---|---|---|---|---|
| n1-standard-64 | 64 | 240 | 用于 5000 节点测试结果 | |
| AWS | m4.16xlarge | 64 | 256 | 提议中(proposed) |
| Azure | standard-g5 | 32 | 448 | 提议中(proposed) |
| Packet | Type 2 | 24 | 256 | 裸金属,提议中(proposed) |
该文档还强调了两个影响大规模集群可扩展性的关键配置:
- 拆分 etcd:为"集群状态"与"事件处理"分别部署两个 etcd 集群,两者 I/O 特征不同,分开可保证 IOPS 的一致性与隔离性(这也是 GKE 生产环境的默认做法);
- 专用 IOPS:为每个控制面节点上的 etcd 集群提供独立 IOPS(裸金属环境下可表现为专用 SSD),并按提供商配置卷类型与大小(如 Google 为 256GB SSD 持久盘 × 2)。
此外,etcd 最低版本要求 3.1.8,API Server 需配置负载均衡,其他组件使用标准 leader election,运行时可优先选用 containerd 以获得更佳性能。
五、为什么官方不测试 HA(多控制平面实例)集群?
5.1 坦诚的现状:能力受限
SIG Scalability 坦承:他们也很想测试 HA 集群,但缺少相应能力。核心原因是集群搭建工具仍依赖 kube-up 及其一系列配置旋钮,而kube-up 并不真正支持 HA 集群;迁移到其他工具又是一项浩大工程,且需要与 GCE 上所有其他仍依赖 kube-up 的测试任务保持一致。
5.2 官方已知的测试缺口
SIG 清楚这是测试覆盖的缺口,原因包括:
- 大型生产集群通常运行至少 3 个控制平面实例以保证单实例故障容忍与零停机升级,测试应贴近用户的真实用法;
- etcd 基于RAFT,多实例 etcd 集群与单 etcd 服务器的性能特征存在差异;
- 分布式系统在组件跨网络分离时往往表现出不同的性能特征;
- 分布式系统可能受到缓存不一致的影响。
5.3 为什么记录这些差异很重要
明确不同配置之间的性能差异同样重要,因为它能揭示哪些优化方向具有最高的投资回报率(ROI)——例如,若测试发现 HA 与单控制面在特定负载下的差距显著,团队就能优先投入消除该瓶颈。
六、关联阅读:可扩展性阈值与 SLO 体系
FAQ 中的结论并非孤立的经验之谈,而是与 SIG Scalability 的整套规模定义体系相衔接:
6.1 可扩展性包络(Scalability Envelope)与阈值
thresholds.md 指出,Kubernetes 支持的配置构成了一个多维的Scalability Envelope——它不是立方体(维度间不独立)、不凸、沿某一维度深入时其他维度的截面会变小、有界、且可分解为更小的包络。这解释了 FAQ 中"没有单一 QPS 答案"背后的几何本质。
该文档给出了官方规模阈值(面向 Kubernetes head、OSS 发行版 + sharded etcd 配置,自 2025 年 12 月起官方发布阻塞可扩展性测试运行在 kops 之上),部分关键条目摘录如下:
内置资源类型(API Server / etcd 存储)
| 数量 | resource type 级阈值 | cluster 级阈值 |
|---|---|---|
| 对象数量(非 Event) | 150,000 | TBD |
| 对象数量(Event) | 1,000,000 | n/a |
| 单对象大小 | 1.5MB | 1.5MB |
| 总大小 | 1.5GB | TBD |
按资源类型的阈值
| 数量 | namespace 级阈值 | cluster 级阈值 |
|---|---|---|
| 节点数 | n/a | 5000 |
| 命名空间数 | n/a | 10000 |
| Pod 数 | 3000 | 150000 |
| 每节点 Pod 数 | min(110, 10×核数) | min(110, 10×核数) |
| Service 数 | 5000 | 10000 |
| 每 Service 端点数 | 250 | n/a |
| Deployment 数 | 2000 | TBD |
| AccessTokens | 2000 | 2000 |
| AccessTokens 验证 | 5000 QPS | 5000 QPS |
注意两个重要前提:多数阈值不是硬限制,越界通常表现为性能退化而非集群立即故障;并且集群级阈值针对最大规模集群给出,小集群应等比下调。这正是 FAQ 中对象大小建议(20kB/100kB)的制度化来源。
6.2 SLI/SLO:"你承诺,我们承诺"框架
slos.md 用"you promise, we promise"框架定义了可扩展性的含义:如果你承诺正确配置集群、合理使用扩展特性、把集群负载控制在推荐阈值内,那么 Kubernetes 承诺所有 SLO 均被满足。官方 SLO 示例包括:
- 单对象变更 API 调用(每个 resource/verb 对)99 分位 ≤ 1s;
- 非流式只读 API 调用:
scope=resource时 99 分位 ≤ 1s,scope=namespace/cluster时 ≤ 30s; - 可调度无状态 Pod 启动延迟(排除镜像拉取与 init 容器时间)99 分位 ≤ 5s。
更详细的指标定义见 api_call_latency.md 与 pod_startup_latency.md。理解这些 SLO 的前提条件(阈值必须被满足),才能正确解读 FAQ 中的各项建议:所有规模建议最终都是为了让你运行在一个 SLO 可被满足的负载区间内。
总结
SIG Scalability 的 FAQ 传达的核心思想可以浓缩为三点:请求成本因画像而异,不要迷信 QPS 数字;对象大小尽量低于 20kB,避免大对象聚合反模式;客户端优先使用 Informer、善用缓存与分块读取、控制 LIST 频率与实例数量。同时,5000 节点测试基准(64 核 / 256GB 控制平面)与 Kubemark 模拟方案,为搭建你自己的规模验证环境提供了可直接套用的参照。如果你想进一步深入,仓库中的 thresholds.md、provider-configs.md 与 slos 目录是继续研读官方规模定义的第一手资料。
【免费下载链接】communityKubernetes Community Documentation项目地址: https://gitcode.com/GitHub_Trending/com/community
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考