1. 课程导入与Karpenter定位
在Kubernetes集群里,节点是承载Pod的物理或虚拟资源。当业务流量上涨、批处理任务集中提交、或某个可用区容量紧张时,集群会面临“Pod因资源不足而Pending”的问题;当流量回落、任务结束后,又会出现大量节点空转、成本浪费。弹性伸缩要解决的核心问题,就是让节点容量跟随工作负载需求动态变化。Karpenter正是这一环节中面向节点供给的自动化组件,它通过直接调用云厂商API创建和终止实例,把“节点从哪来、要多大、什么时候回收”变成可编程、可观测的决策过程。
理解Karpenter的定位,需要先看清Kubernetes弹性伸缩体系的分层。通常可以把弹性能力分为三层:第一层是工作负载副本伸缩,由HPA或KEDA根据CPU、内存、队列长度等指标调整Pod副本数;第二层是Pod调度与装箱,由kube-scheduler根据资源请求、亲和性、污点容忍等约束把Pod放到合适节点;第三层是节点容量伸缩,负责在Pod无法调度时补充节点,在节点长期空闲时回收节点。Karpenter工作在第三层,但它并不只是“补节点”的工具,而是把节点供给与调度约束、实例类型选择、成本优化、中断处理整合在一起。
与Cluster Autoscaler相比,Karpenter的差异首先体现在资源抽象上。Cluster Autoscaler依赖预先定义的节点组,例如云厂商的托管节点组或自建伸缩组,每个节点组绑定固定的实例类型、可用区、标签和启动模板。扩容时,CA从已有节点组中选择一个能容纳Pending Pod的组,再调整该组的期望容量。Karpenter则使用NodePool和EC2NodeClass等自定义资源描述“允许使用哪些实例族、容量类型、可用区、架构和价格上限”,不要求预先固定实例类型。当Pod处于Pending状态时,Karpenter的调度器会直接根据Pod的资源请求、拓扑约束和NodePool约束,计算出一批候选实例,并调用云API创建最合适的节点。
第二个差异是扩容速度与决策粒度。CA的扩容链路通常包含:检测Pending Pod、模拟节点组扩容、调用云厂商伸缩组API、等待实例加入集群、再等待节点就绪。Karpenter则绕过节点组这一层,直接创建实例,并且可以按Pod的实际资源请求选择实例规格,减少“节点组选大了浪费、选小了装不下”的问题。对于突发型工作负载,Karpenter通常能更快地提供节点,因为它不需要等待伸缩组冷却或组内实例模板匹配。
第三个差异是缩容与整合。CA的缩容通常基于节点利用率阈值和冷却时间,且受节点组最小、最大容量限制。Karpenter则持续评估集群中节点的可替代性:如果某个节点的Pod可以迁移到更便宜或更合适的节点上,Karpenter会通过drain、终止实例、重新调度来完成整合。它还可以处理Spot实例中断、实例回收、节点过期等事件,把“节点生命周期”纳入统一控制循环。
为了更直观地对比两者在扩容路径上的差异,下面用一张信号链与决策路径图展示从Pending Pod到节点就绪的关键环节。图中左侧是Cluster Autoscaler的节点组路径,右侧是Karpenter的直接供给路径,中间标出两者共同面对的输入与最终结果。
从图中可以看到,两条路径的起点相同,都是Pending Pod和调度约束;终点也相同,都是节点就绪、Pod重新调度。差异集中在中间环节:CA需要经过节点组和伸缩组两层抽象,Karpenter则把节点组抽象替换为NodePool约束,并直接调用云API创建实例。这个差异决定了Karpenter在实例选择灵活性和扩容速度上的优势,也决定了它在运维方式上更接近“声明式节点供给”,而不是“调整伸缩组容量”。
Karpenter适合哪些场景?第一类是工作负载形态多样、实例类型需求变化快的集群,例如同时运行Web服务、GPU推理、批处理任务,且不同任务对CPU、内存、GPU、架构的要求差异大。第二类是对成本敏感、希望充分利用Spot实例和按需实例混合的集群,Karpenter可以根据价格上限和容量类型自动选择更便宜的实例。第三类是需要快速应对突发流量的在线业务,Karpenter的按需创建和整合能力可以减少节点供给延迟。第四类是多可用区、多架构集群,Karpenter可以根据Pod的拓扑约束和节点池约束,把节点创建到合适的可用区和架构上。
但Karpenter并不是所有场景的默认答案。如果集群规模很小、实例类型固定、节点组数量少,CA的运维成本可能更低;如果云厂商不支持Karpenter所需的API,或者团队对节点组有强合规要求,CA仍然合适。选择时可以从四个维度判断:实例类型是否需要动态选择、扩容速度是否关键、成本优化是否需要细粒度、团队是否愿意接受新的CRD和控制器运维方式。
学习Karpenter的路径可以按“概念—配置—运行—治理”推进。第一步理解NodePool、EC2NodeClass、NodeClaim等核心资源,以及它们与Pod调度约束的关系。第二步掌握安装与基础配置,包括IAM权限、中断队列、控制器部署和节点池定义。第三步观察实际扩容与缩容过程,学会用kubectl查看NodeClaim状态、用事件和日志判断节点创建失败原因。第四步进入生产治理,包括多节点池划分、Spot中断处理、节点过期、成本监控和容量规划。本课程后续章节会沿着这条路径逐步展开,先建立整体认知,再进入可操作的配置与排障细节。
最后需要明确一个边界:Karpenter负责节点供给,不替代HPA的副本伸缩,也不替代调度器的Pod放置决策。它通过与调度器协作,把“Pod无法调度”转化为“创建合适节点”的动作。理解这一点,就能在后续实践中正确划分职责:副本数由HPA或KEDA决定,Pod放哪由调度器决定,节点从哪来、要多大、何时回收由Karpenter决定。三者配合,才构成完整的弹性资源生产体系。