Karpenter:Kubernetes 节点自动伸缩器部署指南(替代 Cluster Autoscaler)
Kubernetes 集群的节点自动伸缩一直是生产运维的核心课题。传统的 Cluster Autoscaler(CA)依赖节点组配置,伸缩逻辑固定,响应速度较慢,且无法根据 Pod 的实际资源需求灵活选择机型。Karpenter 是由 AWS 开源的新一代节点伸缩器,它直接与云厂商 API 对接,能在数十秒内按需启动最合适的节点,支持混合实例类型、Spot 实例优先、节点整合(Consolidation)等高级特性,在弹性与成本控制方面大幅超越传统方案。
本文将带你在 K3s 集群环境中理解 Karpenter 的核心架构,并完成从安装到生产配置的完整部署流程,同时给出与 Cluster Autoscaler 的横向对比,帮助你做出合适的技术选型。
环境要求
Karpenter 对集群及节点有以下基本要求:
| 组件 | 要求 |
|---|---|
| Kubernetes 版本 | v1.26 及以上 |
| 控制节点 CPU | 2 核 |
| 控制节点内存 | 4 GB |
| 系统盘 | 40 GB SSD |
| 操作系统 | Ubuntu 22.04 LTS |
| Helm | v3.10+ |
| kubectl | 与集群版本匹配 |
如果你还没有合适的云服务器来搭建 K3s 控制节点,推荐使用雨云服务器 rainyun-com。注册填优惠码2026off领 5 折优惠券,2 核 4GB 机型性价比极高,完全能够胜任 K3s 单节点集群控制平面的运行需求,用于学习和中小型生产环境均可。
确认集群状态正常:
kubectl get nodes# NAME STATUS ROLES AGE VERSION# k3s-master Ready control-plane,master 1d v1.29.0+k3s1kubectl version--short# Client Version: v1.29.0# Server Version: v1.29.0+k3s1安装准备
Karpenter 与 Cluster Autoscaler 对比
在开始安装前,先了解两者的核心差异:
| 特性 | Karpenter | Cluster Autoscaler |
|---|---|---|
| 伸缩粒度 | 直接调用云 API,按 Pod 需求选机型 | 基于节点组,机型固定 |
| 响应速度 | ~30 秒 | 1-3 分钟 |
| Spot 支持 | 原生支持,自动 Fallback | 需要配置多节点组 |
| 节点整合 | 内置 Consolidation | 需要额外工具 |
| 配置复杂度 | 较简单(声明式 CRD) | 较复杂(节点组多) |
安装 Helm
curlhttps://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3|bashhelm version配置必要的环境变量
exportCLUSTER_NAME="my-k3s-cluster"exportCLUSTER_ENDPOINT=$(kubectl config view--minify-ojsonpath='{.clusters[0].cluster.server}')exportKARPENTER_VERSION="v0.37.0"exportKARPENTER_NAMESPACE="karpenter"部署步骤
第一步:安装 CRD
Karpenter 使用 NodePool 和 EC2NodeClass(AWS)或 NodeClaim 等 CRD 来描述节点配置:
# 创建命名空间kubectl create namespace${KARPENTER_NAMESPACE}# 添加 Helm 仓库helm repoaddkarpenter https://charts.karpenter.sh/ helm repo update第二步:部署 Karpenter 控制器
以下示例为通用部署配置(非 AWS 环境可使用社区版 Karpenter 或对应云厂商 Provider):
helm upgrade--installkarpenter karpenter/karpenter\--namespace"${KARPENTER_NAMESPACE}"\--create-namespace\--version"${KARPENTER_VERSION}"\--set"settings.clusterName=${CLUSTER_NAME}"\--set"settings.clusterEndpoint=${CLUSTER_ENDPOINT}"\--setcontroller.resources.requests.cpu=100m\--setcontroller.resources.requests.memory=160Mi\--setcontroller.resources.limits.cpu=1\--setcontroller.resources.limits.memory=1Gi\--wait第三步:创建 NodePool
NodePool 是 Karpenter v0.32+ 中替代 Provisioner 的核心 CRD,用于声明节点的约束条件和配置:
# nodepool.yamlapiVersion:karpenter.sh/v1beta1kind:NodePoolmetadata:name:defaultspec:template:spec:requirements:-key:kubernetes.io/archoperator:Invalues:["amd64"]-key:kubernetes.io/osoperator:Invalues:["linux"]-key:karpenter.sh/capacity-typeoperator:Invalues:["spot","on-demand"]-key:node.kubernetes.io/instance-typeoperator:Invalues:["c5.large","c5.xlarge","m5.large","m5.xlarge"]nodeClassRef:apiVersion:karpenter.k8s.aws/v1beta1kind:EC2NodeClassname:defaultlimits:cpu:100memory:400Gidisruption:consolidationPolicy:WhenUnderutilizedconsolidateAfter:30sexpireAfter:720h# 30 天后节点自动轮转kubectl apply-fnodepool.yaml第四步:创建 EC2NodeClass(AWS 环境)
# ec2nodeclass.yamlapiVersion:karpenter.k8s.aws/v1beta1kind:EC2NodeClassmetadata:name:defaultspec:amiFamily:AL2role:"KarpenterNodeRole-${CLUSTER_NAME}"subnetSelectorTerms:-tags:karpenter.sh/discovery:"${CLUSTER_NAME}"securityGroupSelectorTerms:-tags:karpenter.sh/discovery:"${CLUSTER_NAME}"blockDeviceMappings:-deviceName:/dev/xvdaebs:volumeSize:50GivolumeType:gp3encrypted:truekubectl apply-fec2nodeclass.yaml第五步:迁移 Cluster Autoscaler 工作负载
如果你正在从 Cluster Autoscaler 迁移,建议分步进行:
# 暂停 Cluster Autoscalerkubectl scale deployment cluster-autoscaler\-nkube-system--replicas=0# 验证 Karpenter 正常工作后再卸载 CAhelm uninstall cluster-autoscaler-nkube-system配置说明
Disruption(节点整合)策略
Karpenter 的节点整合功能可以主动合并低利用率节点,降低成本:
disruption:consolidationPolicy:WhenUnderutilized# 当节点利用率低时整合# 也可使用 WhenEmpty:仅当节点完全空闲时整合consolidateAfter:1m# 等待 1 分钟后执行整合expireAfter:168h# 节点存活 7 天后强制轮转(安全补丁)权重与优先级
多个 NodePool 可以设置权重,Karpenter 优先选择权重高的:
spec:weight:100# 数值越高优先级越高(默认 10)资源限制
防止 Karpenter 无限扩容,务必设置集群级别的资源上限:
limits:cpu:"200"# 集群最多 200 核 CPUmemory:800Gi# 集群最多 800GB 内存验证测试
触发自动扩容
创建一个需要额外节点的高资源 Deployment:
cat<<EOF|kubectl apply-f-apiVersion: apps/v1 kind: Deployment metadata: name: karpenter-test spec: replicas: 5 selector: matchLabels: app: karpenter-test template: metadata: labels: app: karpenter-test spec: containers: - name: pause image: public.ecr.aws/eks-distro/kubernetes/pause:3.7 resources: requests: cpu: "1" memory: "1Gi" EOF观察 Karpenter 日志
# 查看 Karpenter 控制器日志kubectl logs-nkarpenter-lapp.kubernetes.io/name=karpenter\-ccontroller--follow# 观察 NodeClaim 创建过程kubectl get nodeclaim-w# 查看节点何时 Readykubectl get nodes-w验证节点整合
# 删除测试 Deployment,观察节点是否被回收kubectl delete deployment karpenter-test# 约 1-2 分钟后查看节点数量变化kubectl get nodes常见问题
Q:Karpenter 一直无法启动新节点,Pod 持续 Pending?
检查以下几点:
- NodePool 的
requirements与实际可用实例类型是否匹配 - 云厂商 IAM 权限是否赋予了 Karpenter 创建实例的权限
- 子网和安全组标签是否正确打上了
karpenter.sh/discovery
kubectl describe nodeclaim<nodeclaim-name>kubectl logs-nkarpenter-lapp.kubernetes.io/name=karpenter-ccontroller|grepERRORQ:节点被 Karpenter 意外驱逐,如何保护关键 Pod?
为关键工作负载添加do-not-disrupt注解:
metadata:annotations:karpenter.sh/do-not-disrupt:"true"Q:如何限制 Karpenter 只使用特定可用区?
在 NodePool requirements 中添加约束:
-key:topology.kubernetes.io/zoneoperator:Invalues:["us-east-1a","us-east-1b"]Q:Karpenter 与 HPA(Horizontal Pod Autoscaler)如何协同?
HPA 根据 CPU/内存指标水平扩展 Pod 副本数,Karpenter 负责为新 Pod 提供节点。两者天然配合,无需额外配置,形成完整的弹性伸缩链路:指标上升 → HPA 增加副本 → Pod Pending → Karpenter 新增节点。