企业出海多云 K8s 节点弹性伸缩实战:Karpenter、Cluster Autoscaler 与虚拟节点怎么选(2026 最新版)
Meta Description: 出海企业多云 Kubernetes 节点弹性伸缩完整指南:Karpenter 与 Cluster Autoscaler、虚拟节点(Serverless 容器)的本质区别,NodePool/NodeClass 与 Consolidation 原理,AWS EC2NodeClass 完整配置与 Spot 分层做法,阿里云与腾讯云官方 Karpenter Provider 现状与限制,中断预算与 PDB 治理,节点层成本模型与新加坡参考价格表、90 天落地路线与 8 条 FAQ,一篇讲透。
> 关键词: Kubernetes 节点弹性伸缩、Karpenter、Cluster Autoscaler、虚拟节点、Serverless 容器、多云 K8s、Spot 实例、节点成本优化
---
前言:先给结论
如果你的集群还在用"固定实例规格的节点组 + Cluster Autoscaler",那么弹性伸缩的上限已经被节点组的形状锁死了:扩容只能把某个节点组的期望容量调大,缩容只能整台整台地删,中间那批"半满"的节点永远没人管。 这就是 Karpenter 要解决的问题——它把节点从"预先定义的资源池"变成"按 Pod 需求即时采购的产物",伸缩动作从"调容量"升级为"做采购 + 做合并"。AWS 官方文档里 Karpenter 的介绍只有一句话就说清了这件事:A single Karpenter NodePool is capable of handling many different pod shapes… Karpenter eliminates the need to manage many different node groups.
但 Karpenter 不是银弹,三个前提必须先说清楚:
1. 它只负责"节点怎么来、怎么走",不负责"节点上跑什么"。HPA/KEDA 管 Pod 数量,Karpenter 管承载 Pod 的节点,两层不能互相替代;
2. 它对中断敏感型负载并不友好。Consolidation 的本质是"删掉并替换节点",长连接、有状态、需要保序的任务必须靠中断预算和安全网兜住,否则省钱省出故障;
3. 多云支持还在早期。Kubernetes 官方的 Karpenter 核心是成熟项目(核实当日 releases/latest = v1.14.1),AWS Provider 与之同版本迭代,但阿里云、腾讯云的官方 Provider 仍处于 v0.x 阶段,能力与 AWS 侧有明显差距(下文第五节给出实测结论与硬限制)。
所以本文要回答的不是"用不用 Karpenter",而是:在节点这一层,Karpenter、Cluster Autoscaler、虚拟节点(Serverless 容器)各自的天花板在哪里,怎么组合着用,以及怎么算清它的成本账。
与本站既有文章的边界
站点里已有多篇与"弹性"相邻的文章,先把边界划清楚,避免混读:
| 既有主题 | 它解决的问题 | 与本文的关系 |
|---|---|---|
| 成本优化组合策略:预留 + Spot + 自动伸缩(2026-08-08-multicloud-cost-optimization-reserved-spot-autoscaling) | VM 层:包年包月/RI 打底、Spot 扩峰、ASG/ESS 混合实例策略的比例设计 | 本文的计费底座。折扣数学、混合比例公式不再重复,本文只讲 K8s 节点层怎么调用这些计费模式 |
| AWS 五大核心服务系列(07 月多篇) | AWS 单云服务能力与避坑 | 本文只使用其 API 与计费口径,不复述产品介绍 |
| 容器运行时安全加固(2026-08-19-container-runtime-security-hardening) | 节点上进程行为层的安全(seccomp/gVisor/运行时检测) | 本文只管节点的供给与回收,安全面只提"节点生命周期带来的镜像与凭据漂移"这一条 |
| 多云容器镜像分发(2026-09-15-multicloud-container-image-distribution-cross-cloud-sync) | 镜像怎么可靠、快速地到达节点 | 本文假设镜像已就绪,只关心节点拉起速度会不会被镜像拖慢 |
| 多云可观测与告警治理(2026-08-16-multicloud-observability-alert-governance) | 指标/日志/链路的统一采集与告警出口 | 本文复用其告警通道,不重复建设 |
| 多云管理平台 CMP(2026-09-18-multicloud-management-platform-cmp-self-service-catalog) | 资源纳管、自助交付、成本分账 | 节点伸缩是 CMP 的执行末端,本文只讲执行层 |
本文只讲一件事:Kubernetes 节点层的弹性供给、合并与成本。
一、K8s 伸缩有三个层,别把三层混成一件事
运维里最常见的误判,是把"扩容慢"当成"K8s 不行"。实际上从 Pod 到物理机有三层完全独立的伸缩机制,每一层的触发条件、时间尺度和失败表现都不一样:
| 层 | 代表组件 | 触发信号 | 时间尺度 | 失败表现 |
|---|---|---|---|---|
| Pod 层 | HPA / KEDA / VPA | CPU/内存/QPS/队列长度等指标 | 秒级~分钟级 | Pod 数不涨,或涨了但 Pending |
| 节点层 | Cluster Autoscaler / Karpenter / 虚拟节点 | 出现无法调度的 Pod(Pending) | 十秒级(Karpenter)~分钟级(CA) | Pod 长期 Pending,FailedScheduling 事件刷屏 |
| VM 层 | ASG / ESS / 预留实例 / Spot | 容量目标(desired capacity) | 分钟级 | 扩容成功但账单暴涨,或 Spot 被回收后无节点可拉 |
关键认知一:Pod 层扩容之后一定会有节点层需求。 HPA 把副本从 10 拉到 100,如果没有节点层接住,结果是 90 个 Pending 的 Pod 加上一条长长的 FailedScheduling 事件流。很多"扩容不生效"的排查最后都落在节点层,而不是 HPA 配置。
关键认知二:VM 层的折扣策略和节点层的伸缩策略必须对齐。 08-08 那篇讲的是怎么用"预留打底 + Spot 扩峰"把 VM 账单砍 40%~60%;而节点层的任务,是让每一个新采购的节点落在正确的计费类别里——稳定基线落在预留/包年上,弹性增量优先落在 Spot 上。节点层选错工具,VM 层的省钱策略会被自动伸缩反向吃掉。
关键认知三:Agent 式 Provider 和 CA 是两套哲学,不是两个版本。 Cluster Autoscaler 是"改数字"(把节点组的期望容量改大改小),Karpenter 是"下订单"(直接向云 API 申请一台符合 Pod 需求的机器)。这个差异决定了后面所有能力差距。
二、Karpenter 到底做了什么:NodePool + NodeClass + Consolidation
Karpenter 的模型只有两个 CRD 加一个后台循环,理解了这三样,它 90% 的行为都能推导出来。
- NodePool:描述"允许供给什么形状的节点",以及伸缩的行为约束。核心字段包括 spec.template.spec.requirements(约束实例族、架构、计费类型、可用区等)、spec.limits(该池的总量上限,如 cpu: 1000)、spec.weight(多个池同时匹配时的优先级)、spec.disruption.consolidationPolicy 与 consolidateAfter、以及 spec.template.spec.expireAfter(节点最长寿命,默认 720h,即 30 天)。
- NodeClass:描述"用什么云资源来起这台机器"。AWS 侧是 EC2NodeClass(subnetSelectorTerms 选子网、securityGroupSelectorTerms 选安全组、role 或 instanceProfile 提供节点身份、amiSelectorTerms 选镜像、metadataOptions 与块存储映射);阿里云侧对应 ECSNodeClass(vSwitchSelectorTerms / securityGroupSelectorTerms / imageSelectorTerms / systemDisk / dataDisk,且必须指定 clusterID);腾讯云侧对应 TKEMachineNodeClass。
- 后台循环:Karpenter 持续监听调度失败的 Pod,按 Pod 的 requests、nodeSelector、affinity、拓扑约束反推"最便宜且能满足它的实例",直接向云 API 下单,再通过临时凭据把节点注册进集群。这条链路不需要预先存在的节点组。
自动供给链路
`mermaid
graph TD
A[Pod 提交, 资源不足] --> B[Pod 进入 Pending]
B --> C{Karpenter Provisioner}
C -->|读取 requests/affinity/拓扑| D[筛选可用 NodePool]
D -->|最高 weight 优先| E[按 NodeClass 计算候选机型]
E --> F[向云 API 下单创建实例]
F --> G[节点注册进集群]
G --> H[Pod 调度完成, 创建 NodeClaim 记录]
H --> I{Disruption 循环}
I -->|先 Drift| J[配置漂移节点被替换]
I -->|再 Consolidation| K[空节点/低利用节点被删除或换小]
`
三张网:Pending、Drift、Consolidation 的关系
`text
┌──────────────────────────────────────────────────────────────┐
│ 触发方向(按 Pod 需求往上采购) │
│ │
│ Pending Pod ──► 反推机型 ──► 云 API 下单 ──► 节点 Ready │
│ │
│ 触发方向(按成本与配置往下收缩) │
│ │
│ Drift 配置变了(NodePool/NodeClass 改动、镜像更新) │
│ │ │
│ ▼ │
│ Consolidation ① 空节点删除(WhenEmpty) │
│ ② 低利用节点替换为更小/更便宜机器 │
│ ③ 把多个半满节点上的 Pod 打包到一台(对账式收敛) │
│ │
│ 两者的执行速率都由 NodePool Disruption Budgets 限流 │
│ 默认预算:一个预算,nodes: 10%(即最多 10% 节点在中断中) │
└──────────────────────────────────────────────────────────────┘
`
三个必须记住的细节:
1. 默认的 Consolidation 策略是 WhenEmptyOrUnderutilized,但 AWS 的入门示例把 consolidateAfter 写成 1m。 在真实生产里,1 分钟太激进——Pod 刚被调度走就触发合并,会造成持续抖动。生产建议从 Balanced 或 5m 起步(要 5m 记得把 consolidateAfter 一起改)。
2. expireAfter 默认 720h,意味着节点最长活 30 天就会被强制轮换。这对"AMi 补丁合规"是好事,但如果你的节点上跑了需要长生命周期的本地缓存(镜像层、模型权重、数据集),必须给它单独的 NodePool 并显式设 expireAfter: Never,否则每周都在重拉数据。
3. Drift 是"配置一致性"能力,不是"故障恢复"能力。 Karpenter 会给 NodePool/NodeClass 的模板算一个哈希,节点对不上就标记 Drifted 并替换;但被标记为"行为类字段"的设置(如 disruption 相关配置)不参与 Drift 判断。所以"改了 disruption 预算发现存量节点没动"是预期行为,不是 bug。
三、三方案对比:Karpenter vs Cluster Autoscaler vs 虚拟节点
| 维度 | Cluster Autoscaler | Karpenter | 虚拟节点 / Serverless 容器 |
|---|---|---|---|
| 伸缩单元 | 节点组(ASG/ESS/节点池) | 单个实例(即时下单) | 单个 Pod |
| 是否需预定义实例规格 | 必须(节点组的启动配置锁死) | 不需要,按 Pod 反推 | 不需要 |
| 混合 Pod 形状 | 一种形状一个节点组,池数量爆炸 | 一个 NodePool 覆盖多种形状 | 由平台规格档位决定 |
| 缩容逻辑 | 按利用率阈值 + 冷却时间删整台 | Consolidation:删空节点 + 用更小机器替换低利用节点 + 打包 Pod | 无节点可缩,Pod 结束即停 |
| Spot 利用方式 | 靠节点组绑定(MixedInstancesPolicy 静态列表) | 靠 karpenter.sh/capacity-type 需求 + 成本择优,候选机型广 | 通常不支持 Spot |
| 配置/Drift 治理 | 无(靠外部工具巡检) | 内置 Drift,模板变更自动替换节点 | 平台托管,用户无节点可见 |
| DaemonSet / 特权容器 | 支持 | 支持 | 普遍受限或不可用 |
| GPU / 大内存规格 | 支持(受节点组配置约束) | 支持(受实例族 availability 约束) | 多为通用规格,GPU 支持有限 |
| 计费特征 | 节点按时长计费 | 节点按时长计费(可混合 Spot/预留) | 按 Pod 用量计费,单价更高 |
| 适合场景 | 存量集群、形状单一的负载 | 形状混合、弹性频繁、追求成本 | 短任务、事件驱动、免运维后台任务 |
三条选型结论:
1. 形状单一的集群,不要为了 Karpenter 而迁移。 如果全站只有"2 核 4G Web"和"4 核 8G Worker"两种形状,CA 已经够用,迁移的收益抵不上学习与调参成本; 2. 形状混合 + 弹性频繁的集群,Karpenter 的收益最大。 它的省钱不是来自"折扣",而是来自把一堆半满节点合并成少量满节点——这部分浪费在 CA 体系里根本不出现,因为 CA 没有"替换更小机器"这个动作; 3. 虚拟节点用来兜住"不该占用节点"的负载。 定时任务、Webhook 回调、低频批处理、CI Runner 这类负载放进虚拟节点,可以让节点池的基线容量小一圈;但长连接、需要 DaemonSet、需要 GPU 的负载不要往里塞。
四、AWS 落地:从安装到双池分层
Karpenter 通过 Helm 安装,AWS 侧使用 OCI 仓库的 chart。版本不要写死在文章里——上游迭代很快,用 GitHub API 现取当前最新版,避免文章发布几个月后照着跑 404:
`bash
// 现取当前最新版本号, 不要硬编码
KARPENTER_VERSION=$(curl -s https://api.github.com/repos/kubernetes-sigs/karpenter/releases/latest | grep -oP '"tag_name":\s*"\K[^"]+')
echo "本次安装版本: ${KARPENTER_VERSION}"
export KARPENTER_NAMESPACE=karpenter
// Spot 需要一次性创建服务关联角色(每个账号一次) aws iam create-service-linked-role --aws-service-name spot.amazonaws.com || true
// OCI chart 安装
helm registry logout public.ecr.aws
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter \
--version "${KARPENTER_VERSION}" \
--namespace "${KARPENTER_NAMESPACE}" --create-namespace \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.interruptionQueue=${CLUSTER_NAME}" \
--wait
`
安装完成后先建 EC2NodeClass,它声明"用哪些云资源起机器"。注意:YAML 里的注释在博客渲染时会变成标题,所以下面的清单刻意不带注释,说明全部写在正文里。
`yaml
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
role: "KarpenterNodeRole-REPLACE_WITH_CLUSTER_NAME"
amiSelectorTerms:
- alias: al2023@latest
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "REPLACE_WITH_CLUSTER_NAME"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "REPLACE_WITH_CLUSTER_NAME"
metadataOptions:
httpEndpoint: enabled
httpTokens: required
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 100Gi
volumeType: gp3
encrypted: true
`
字段解释与两条纪律:amiSelectorTerms.alias 用 al2023@latest 会自动跟随 EKS 优化 AMI 的最新版;要可复现就改成日期版别名(形如 al2023@v2024xxxx),否则今天建的节点和下周建的节点镜像可能不是同一个。role 与 instanceProfile 二选一必填,缺了 Karpenter 不会启动任何节点。盘默认 20Gi 对容器节点通常偏小,镜像层加本地缓存很容易打满,建议起步 100Gi gp3 并设 encrypted: true。httpTokens: required 强制 IMDSv2,是节点侧最便宜的一条加固。
接下来是双池分层:一个 Spot 池承接弹性增量,一个按量池兜底。这里有个常被写错的地方——weight 只决定"多个 NodePool 同时匹配一个 Pod 时优先用哪个",它不改变"NodePool 的 requirements 必须真的能满足这个 Pod"这个前提。
`yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: spot-first
spec:
weight: 50
limits:
cpu: 2000
template:
metadata:
labels:
capacity: spot
spec:
expireAfter: 336h
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["c", "m", "r"]
- key: karpenter.k8s.aws/instance-generation
operator: Gt
values: ["5"]
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 5m
budgets:
- nodes: "10%"
`
`yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: ondemand-baseline
spec:
weight: 10
limits:
cpu: 500
template:
spec:
expireAfter: 720h
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: default
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: karpenter.k8s.aws/instance-category
operator: In
values: ["m"]
disruption:
consolidationPolicy: Balanced
consolidateAfter: 30m
budgets:
- nodes: "5%"
`
这套双池设计的三个要点:
1. instance-category 给足宽度才叫 Spot 多样化。 只写 ["m"] 一种族,Spot 池的容量与回收率都会明显变差;写成 ["c","m","r"] 并配 instance-generation Gt 5,Karpenter 就有几十种候选机型可以挑,回收风险被摊薄。
2. 两个池的 consolidation 策略刻意不同。 Spot 池用 WhenEmpty(只在空节点上收缩,避免为了小钱把跑着业务的 Spot 节点合并掉,再叠加回收就变成双重中断);按量池用 Balanced(只在"省下的钱明显大于中断代价"时才动)。
3. limits 不是装饰品。 它既是防爆预算,也是"这朵云最多花多少算力"的硬边界。写 cpu: 2000 意味着这个池最多供给 2000 核;忘记设限是"一晚上账单翻十倍"最常见的成因。
验证与排障命令(nodeclaim 是 Karpenter 为每个节点建的记录对象,看它比看节点本身信息更全):
`bash
kubectl get nodepools
kubectl get nodeclaims -o wide
kubectl describe nodeclaim NODECLAIM_NAME
kubectl get events --field-selector reason=FailedScheduling --sort-by=.lastTimestamp | tail -20
`
五、多云落地现状:AWS 成熟,阿里云与腾讯云属早期
这一节写的是核实当日(2026-09-21)的实测结论,不是宣传口径。三个云厂商在节点弹性这一层的成熟度差距非常大,选型前必须知道。
5.1 AWS:Provider 成熟,且已有托管形态
- 开源 Provider:kubernetes-sigs/karpenter 与 aws/karpenter-provider-aws 同版本迭代,核实当日最新 release 均为 v1.14.1;
- EKS Auto Mode = AWS 托管的 Karpenter。官方文档明确写明其自动伸缩"Relying on Karpenter",并且把计算、网络(Pod IP、网络策略、本地 DNS)、负载均衡、块存储、GPU 插件都收进了核心组件,不再作为 add-on 维护。托管节点使用 Bottlerocket 变体镜像,根文件系统只读、默认关闭 SSH 与 SSM 直连通道;新托管实例自 2026-04-22 起默认在 EC2 控制台与 API 列表操作中隐藏。
- 但要算清 Auto Mode 的账:EKS Auto Mode 收取"按实例类型浮动的管理费",官方口径是这笔费用在 EC2 实例价之外,且与 EC2 的购买方式无关——也就是说,即使你用了预留实例或 Savings Plans 覆盖了机器本身,这笔管理费照收;计费按秒、每分钟起算。另外官方提示:组织内 Auto Mode 节点超过 150 台需联系账户团队,节点存在 21 天的最大寿命上限。
- 顺带记住 EKS 的控制面口径:标准支持期内 $0.10/集群/小时,Kubernetes 版本进入扩展支持后升至 $0.60/小时(官方算例:同一集群跑 26 个月,平均约 $0.33/小时)。"忘记升级 K8s 版本"是容器平台最贵的一类疏忽。
5.2 阿里云:官方 Provider 可用,但有一条硬限制
- 官方 Provider 仓库为 AliyunContainerService/karpenter-provider-alibabacloud,仓库活跃(近期仍有提交)且有正式 release(核实当日最新 tag 为 v0.2.5);CRD 为 NodePool + ECSNodeClass,NodeClass 支持 clusterID、vSwitchSelectorTerms(id/tag)、securityGroupSelectorTerms(id/tag)、imageSelectorTerms(id/imageFamily)、systemDisk、dataDisk;NodePool 侧支持多实例规格与多可用区。
- 🔴 硬限制:官方 README 的能力表里,karpenter.sh/capacity-type 一项写的是"仅支持按量付费"。 这意味着在 ACK 上通过这个官方 Provider 暂时拿不到抢占式实例的自动供给——如果你的省钱策略依赖"节点层直接采购 Spot",阿里云侧必须回退到"节点池 + ACK 的伸缩组件"这条路,或者自己给 Provider 扩展。 这一条是选型时的关键差别,网上的"Karpenter 多云通吃"说法在这里不成立。
- ACK 另有虚拟节点形态(底层是弹性容器实例 ECI),适合把短任务移出节点池;它与 Karpenter 不是替代关系,而是"节点池之外的第二条供给通道"。
5.3 腾讯云:官方 Provider 存在,但仍在早期
- 官方 Provider 仓库为 tencentcloud/karpenter-provider-tke(仓库存在且近期有更新),CRD 为 NodePool + TKEMachineNodeClass(API 组 karpenter.k8s.tke)。注意:仓库目前没有正式 release——这不代表项目不存在,"没有 release"只说明还没有打 tag,安装需按 README 使用 chart 包。
- 安装有两个 TKE 特有步骤:先把 CAM 的 secretID/secretKey 建成集群内 Secret,再用 --set settings.clusterID=cls-xxxx 与 --set settings.region=ap-singapore 指定目标集群与地域;README 还提示从 0.1.6 以下版本升级时必须先单独应用 CRD(NodePool / NodeClaim / NodeClass 三个 yaml),否则升级会失败。
- 虚拟节点侧,TKE 提供超级节点(Super Node)形态(官方文档有独立的购买与 API 页面),用于承接无需管理节点的负载。
5.4 多云收敛建议
| 场景 | 建议路径 | 理由 | |---|---|---| | 单云(AWS) | 自管 Karpenter 或直接上 EKS Auto Mode | Provider 成熟,托管形态省人力,代价是管理费 | | 单云(阿里云 / 腾讯云) | 官方 Provider 起步,保留节点池作为 Spot 承载面 | 阿里云侧 Spot 能力缺失、腾讯云侧无正式 release | | 多云统一 | 一套 Karpenter 部署在管控集群,各云独立 NodeClass + NodePool | 治理模型统一,但要接受各云能力不对等,不要让同一份 NodePool 语义跨云复用 | | 短任务 / 事件驱动 | 虚拟节点(ECI / Super Node) | 免节点、按用量计费,不与节点池争容量 |
六、中断治理:三层安全网,缺一层都会出事
Karpenter 省钱的机制本身就是"制造受控中断"(删节点、换小机器、打包 Pod)。所以用 Karpenter 的正确姿势不是关掉 Consolidation,而是给它装上三层安全网:
| 层 | 机制 | 管住什么 | 管不住什么 |
|---|---|---|---|
| 应用层 | PodDisruptionBudget(PDB) | 保证最少可用副本数,驱逐被限速 | 管不住"节点是否会被合并"这件事本身 |
| 节点池层 | NodePool Disruption Budgets | 同时处于中断中的节点比例上限 | 强制性的 Expiration 不受预算约束(超期节点照删) |
| Pod 层 | karpenter.sh/do-not-disrupt 注解 | 该 Pod 所在节点被排除在 Consolidation 之外 | 若所属 NodeClaim 配了 terminationGracePeriod,该节点仍可被 Drift 中断 |
三个必须记住的行为细节:
1. 预算的计算公式是"向上取整减已删除减未就绪":百分比预算下 allowed = roundup(池内总节点数 × 百分比) - 正在删除的 - NotReady 的。13 个节点的池配 20% 预算,就是 roundup(2.6) = 3 台。多个预算同时存在时,取最严格的那个。
2. 未配置预算时默认是 nodes: 10% 的单条预算。 也就是说开箱状态下,Karpenter 随时可能同时中断 10% 的节点——对无状态服务无感,对有状态或需要人工介入的负载就偏激进。
3. 执行顺序是固定的:先 Drift,后 Consolidation。 Karpenter 同一时刻只执行一种自动中断方法,不会一边迁移配置一边合并节点。
一个可直接抄的"三层预算"写法。同样提醒:YAML 里不能写注释(渲染会串成标题),解释放在正文。
`yaml
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: production
spec:
disruption:
consolidationPolicy: Balanced
consolidateAfter: 5m
budgets:
- nodes: "20%"
reasons: ["Drifted", "Empty"]
- nodes: "5"
- nodes: "0"
schedule: "@daily"
duration: 10m
reasons: ["Underutilized"]
`
这三条预算的含义分别是:配置漂移或空节点最多同时动 20% 的节点;整体中断台数不超过 5 台(给第一条件加一个绝对上限,避免池子变大后 20% 变成几十台);每天前 10 分钟不允许做"低利用合并"——这一条是给日报、签到、结算类定时任务留的窗口,它们是"每天同一分钟把集群压满"的典型负载,恰好也是 Consolidation 最爱下手的目标。
实践顺序建议:先只上 PDB 和"conservative 策略(WhenEmpty)"跑两周,观察中断次数与 P99 延迟;确认无异常后再切 Balanced,最后才考虑 WhenEmptyOrUnderutilized。这个灰度顺序和站内其他文章的做法一致——能力先按可逆动作上线,再逐步放宽。
七、成本账怎么算:三笔钱,别只算节点单价
节点层的成本不是"节点单价 × 节点数"这么简单,至少三笔钱要一起算:
第一笔:控制面费(固定 + 版本风险)。 AWS 的 EKS 控制面标准支持期 $0.10/集群/小时(约 $73/月),Kubernetes 版本超过标准支持期后跳升至 $0.60/小时——这是唯一一笔"什么都不做也会涨 6 倍"的费用。阿里云 ACK 与腾讯云 TKE 按集群版本/类型计费,口径以控制台结算页为准。另外 AWS 若选 EKS Auto Mode,还要在 EC2 实例费之外付一笔"按实例类型浮动的管理费",这笔钱与 EC2 的购买方式无关,享受了预留折扣也照收。
第二笔:半满节点的浪费(Karpenter 的价值所在)。 这是唯一一笔"不做任何采购优化、纯粹因为工具能力不足而付出的钱"。示意算例(非报价):一个 30 节点、平均 CPU 利用率 35% 的集群,把工作负载合并到 22 个满节点上是常见结果,直接省下约 27% 的节点费——而这 8 台机器在 CA 体系里不会被回收,因为每一台的利用率都超过了缩容阈值。这就是"Karpenter 省钱"的真实来源:不是折扣,是消除碎片。
第三笔:中断的隐性成本(重试、超时、扩缩抖动)。 合并太激进会让长尾请求超时、让 CI 流水线被反复打断、让缓存冷启动循环。把 consolidateAfter 从 1m 调到 5m~30m,用掉的机器钱可能只有几百美元,省下的排障时间远大于此。
参考价格表(新加坡 Region,公开官网参考区间,实际以官网实时报价为准):
| 计费项 | 阿里云国际版 | AWS | 腾讯云国际版 | |---|---|---|---| | K8s 控制面 | 以 ACK 集群版本控制台价为准 | $0.10/集群/小时(标准支持);扩展支持 $0.60/小时 | 以 TKE 集群类型控制台价为准 | | 2 核 2G 节点(按量) | 约 $31/月 | 约 $24/月(t3.small) | 约 $28/月 | | 2 核 4G 节点(按量) | 约 $47/月 | 约 $30/月(t3.medium) | 约 $34/月 | | 4 核 8G 节点(按量) | 约 $94/月 | 约 $60/月(t3.large) | 约 $68/月 | | 1 年预留 / 包年 | 约 5 折 | 约 6 折(标准 RI 全预付) | 约 5~6 折 | | Spot / 抢占 | 约 1~3 折 | 约 3~4 折 | 约 2~4 折 | | Karpenter 软件本身 | 开源免费(自管运维成本另计) | 开源免费;EKS Auto Mode 另收管理费 | 开源免费 | | 虚拟节点形态 | ECI 按用量计费 | 托管 Serverless 按 vCPU/内存计费 | 超级节点按用量计费 |
> 声明:本文价格数据采集于 2026 年 9 月,仅为公开官网参考区间与官方文档口径的整理,不构成报价,请以各厂商官网与控制台结算页的实时价格为准。除特别标注外,金额单位均为美元(USD)。文中出现的合并收益测算均为示意算例,用于说明计算口径,不代表任何客户的实际结果。
八、可观测与排障:五个信号 + 三个高频坑
节点伸缩出问题几乎不会报错,只会"变慢、变贵"。所以必须把这五个信号接进现有监控(复用站内 08-16 那套统一告警出口即可,不要再建一套):
| 信号 | 看什么 | 异常的含义 |
|---|---|---|
| Pending Pod 数与 Pending 时长 | 单位时间内处于 Pending 的 Pod、最长排队时间 | 供给跟不上需求,优先查 NodePool 的 limits 是否打满 |
| 节点供给延迟 | Pod 从 Pending 到 Running 的耗时 | 慢在"下单"还是"起机器"还是"拉镜像",三段分别计时 |
| 节点利用率分布 | 各节点的 CPU/内存请求率直方图 | 出现大量 30%~50% 的节点 = Consolidation 没生效或被预算挡住 |
| 中断次数与原因 | 按 Drifted / Empty / Underutilized / Expired / Spot 回收分类计数 | 某一类突然放量 = 配置或负载形态变了 |
| NodeClaim 失败率 | kubectl get nodeclaims 中 condition 非 Ready 的比例 | 通常是选不到资源,而非控制器故障 |
三个高频坑:
1. 扩容失败,九成是"选不到资源"而不是"控制器挂了"。 典型原因是子网/安全组的 tag 选择器写错、节点角色缺少 ec2:RunInstances 等权限、或要求的实例族在该可用区暂时无货。排查一律从 kubectl describe nodeclaim <名称> 的 status condition 入手,它会明确写出失败原因。
2. 节点 Ready 慢,往往不是节点慢,而是镜像大。 大镜像会把"起机器 40 秒"变成"起机器 3 分钟"。这属于镜像分发层的问题(见站内镜像分发与 P2P 加速那篇),不要指望靠调 Karpenter 参数解决。
3. Spot 池一定要接中断事件。 Karpenter 内置处理 EC2 Spot 中断通知的能力,但它依赖你安装时配置了对应的事件队列/中断通道;漏配这个通道,Spot 回收就退化成"节点突然消失",节点上的 Pod 来不及优雅退出。 前面 Helm 安装命令里的 settings.interruptionQueue 就是为这件事存在的,别省略。
九、90 天落地路线
不要一次性把集群从"节点组 + CA"切到 Karpenter,按下面四阶段走,每一阶段都有明确的验收口径:
| 阶段 | 时间 | 动作 | 验收口径 |
|---|---|---|---|
| 一、摸清底座 | 第 1~2 周 | 统计节点形状分布(机型、vCPU、内存、计费类型)、节点利用率直方图、Pending 事件频次与时长;确认集群内有多少固定规格负载(GPU / 大内存 / 本地盘) | 能回答"当前有多少节点长期低于 50% 利用率" |
| 二、影子运行 | 第 3~6 周 | 装 Karpenter 但把既有节点组保持原位,只让新增弹性走 Karpenter;Consolidation 先设 Never;建好 NodeClass 与两个 NodePool(Spot 承压 + 按量兜底) | 新节点 100% 由 Karpenter 供给,无 Pending 积压 |
| 三、开合并 | 第 7~10 周 | 打开 WhenEmpty,配三层中断预算 + 关键服务的 PDB;观察中断计数与 P99 延迟两周后,再灰度到 Balanced | 节点数下降但 P99 无回归,中断次数在预算内 |
| 四、收口与固化 | 第 11~13 周 | 把 NodePool/NodeClass 纳入 IaC 与代码评审;把单位成本(每千请求节点成本)接入看板;把降级预案(Karpenter 控制器不可用时回退节点组)写成 Runbook | 变更全部可审计、可回滚;成本看板能按业务分摊 |
常见问题 FAQ
Q1:Karpenter 能直接替代 Cluster Autoscaler 吗?迁移要推倒重来吗?
能力上可以替代,并且 Karpenter 是"超集"(多出即时采购、Consolidation、Drift 三项)。但迁移不等于推倒重来:推荐路径是保留原有节点组不删,让 Karpenter 只承接新增弹性,跑顺之后再把节点组的期望容量逐步降到只留最小基线。Karpenter 与 CA 在同一集群共存是正常过渡状态,只要两者不在同一个自动伸缩组上争抢容量即可。
Q2:用了 Karpenter,是不是就不用买预留实例了?
不是。Karpenter 决定的是"买什么形状的机器",不决定"用什么计费方式"。 稳定基线该买的预留/节省计划照买——折扣体现在云账单的实例费上,与是谁发起的采购无关。正确分工是:预留/节省计划覆盖确定性基线负载,Karpenter 用 Spot 与按量承接波动部分。两者是叠加关系,不是替代关系。
Q3:Consolidation 会不会影响线上稳定性?
会,但可控。关键是把三件事配齐:consolidationPolicy 从 WhenEmpty 起步、consolidateAfter 不短于 5 分钟、关键服务都配 PDB。真正危险的不是 Consolidation 本身,而是它和 Spot 回收叠加——同一张节点上既被合并、又被回收,Pod 会经历两次中断。所以 Spot 池建议用 WhenEmpty,别用激进策略。
Q4:阿里云和腾讯云能用 Karpenter 吗?
能,但要接受能力差异(核实当日结论):阿里云有官方 Provider(AliyunContainerService/karpenter-provider-alibabacloud,有正式 release,CRD 为 ECSNodeClass + NodePool),但官方能力表明确写着 karpenter.sh/capacity-type 仅支持按量付费——想在 ACK 上自动采购抢占式实例,目前没有官方路径;腾讯云官方 Provider(tencentcloud/karpenter-provider-tke)仓库存在且持续更新,但尚无正式 release,安装需按 README 使用 chart 并预置 CAM 密钥 Secret。结论:单云评估可以上,跨云统一治理要有"能力不对等"的心理准备。
Q5:虚拟节点能不能完全替代节点池?
不能。虚拟节点(ECI / 超级节点 / 托管 Serverless 容器)解决的是"不想管节点",代价是规格档位受限、DaemonSet 与特权容器普遍不可用、GPU 与本地盘支持有限、单价高于同规格按量节点。它适合定时任务、Webhook、低频批处理;长连接、需要本地缓存的推理服务、依赖 DaemonSet 做日志采集的负载,仍然要落在真实节点上。
Q6:Karpenter 控制器自己是不是单点?它挂了会怎样?
控制器负责的是"供给与合并"这两个动作。它不可用期间,存量节点与运行中的 Pod 不受影响,但新的节点供给和合并动作会暂停——表现就是 Pending Pod 不再被自动满足。所以生产上要:控制器多副本部署、纳入告警(提示"控制器不可用"而不是等 Pending 积压)、并在 Runbook 里留一条"控制器故障时临时把节点组期望容量调大兜底"的降级路径。
Q7:集群要多大才值得上 Karpenter?
节点形状越混合、弹性越频繁,收益越大。判断口径不是"节点总数"而是"低利用节点的比例 × 节点单价":如果你有 30% 以上的节点长期低于 50% 利用率,或者存在 3 种以上差别很大的 Pod 形状(大内存 + 小 Web + 批处理),收益就很明显。反过来,一个 8 节点、全部同规格、利用率稳定在 70% 的集群,上 Karpenter 的收益可能抵不上运维成本。
Q8:怎么证明真的省了钱?
不要看总账单(业务增长会掩盖节省)。要看单位成本:每千次请求的节点成本、每 vCPU-小时产出的业务吞吐、以及"节点数 × 平均利用率"这条曲线的形态。节点数下降、单位成本下降但业务量不变,才是真省;总账单下降而业务量也下降,只是缩容而已。
总结
节点弹性这一层,2026 年的格局可以一句话概括:Karpenter 把"节点组"这个概念从运维的必答题变成了选答题,但它把复杂度从"配置节点组"搬到了"设计中断策略"上——省下的钱要靠预算、PDB 和灰度顺序守住。
三条可执行的最终建议:
1. 形状单一的小集群不要跟风迁移,Cluster Autoscaler + 节点池依然是最省心的答案; 2. 形状混合、弹性频繁的集群优先上 Karpenter,收益来自消除碎片而不是折扣,同时必须同步建设中断预算与 PDB; 3. 多云场景把"能力不对等"当成设计前提:AWS 侧可以用托管形态,阿里云侧 Spot 自动化目前缺失、腾讯云侧 Provider 尚未正式发版,跨云统一治理可以统一"模型"(NodePool + NodeClass),但不能统一"期望值"。
> 🚀 企业出海需要云架构咨询?通过 7.chengzicloud.cloud 联系我们,获取专属方案。
相关阅读
- 海外云服务器成本优化:预留实例 + Spot + 自动伸缩组合策略 — 本文的计费底座:VM 层的折扣数学与混合比例设计 - 多云容器镜像分发架构 — 节点拉起慢的另一半原因:镜像怎么又快又稳地到达节点 - 多云可观测与告警治理 — 本文第五节五个信号接入的统一告警出口 - 多云管理平台(CMP)建设实战 — 节点伸缩在平台体系中的位置:执行末端 - 容器运行时安全加固 — 节点频繁换新带来的镜像与凭据漂移怎么收口 - 企业出海 AI 应用多云架构(GPU + 向量库 + 推理平台) — GPU 推理节点的规格约束与弹性策略
> 本文由 7.chengzicloud.cloud 提供,点击访问首页了解更多