Karpenter:Kubernetes 节点自动伸缩器部署指南(替代 Cluster Autoscaler)
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+k3s1
kubectl 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
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
配置必要的环境变量
export CLUSTER_NAME="my-k3s-cluster"
export CLUSTER_ENDPOINT=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
export KARPENTER_VERSION="v0.37.0"
export KARPENTER_NAMESPACE="karpenter"
部署步骤
第一步:安装 CRD
Karpenter 使用 NodePool 和 EC2NodeClass(AWS)或 NodeClaim 等 CRD 来描述节点配置:
# 创建命名空间
kubectl create namespace ${KARPENTER_NAMESPACE}
# 添加 Helm 仓库
helm repo add karpenter https://charts.karpenter.sh/
helm repo update
第二步:部署 Karpenter 控制器
以下示例为通用部署配置(非 AWS 环境可使用社区版 Karpenter 或对应云厂商 Provider):
helm upgrade --install karpenter karpenter/karpenter \
--namespace "${KARPENTER_NAMESPACE}" \
--create-namespace \
--version "${KARPENTER_VERSION}" \
--set "settings.clusterName=${CLUSTER_NAME}" \
--set "settings.clusterEndpoint=${CLUSTER_ENDPOINT}" \
--set controller.resources.requests.cpu=100m \
--set controller.resources.requests.memory=160Mi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1Gi \
--wait
第三步:创建 NodePool
NodePool 是 Karpenter v0.32+ 中替代 Provisioner 的核心 CRD,用于声明节点的约束条件和配置:
# nodepool.yaml
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: default
spec:
template:
spec:
requirements:
- key: kubernetes.io/arch
operator: In
values: ["amd64"]
- key: kubernetes.io/os
operator: In
values: ["linux"]
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["c5.large", "c5.xlarge", "m5.large", "m5.xlarge"]
nodeClassRef:
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
name: default
limits:
cpu: 100
memory: 400Gi
disruption:
consolidationPolicy: WhenUnderutilized
consolidateAfter: 30s
expireAfter: 720h # 30 天后节点自动轮转
kubectl apply -f nodepool.yaml
第四步:创建 EC2NodeClass(AWS 环境)
# ec2nodeclass.yaml
apiVersion: karpenter.k8s.aws/v1beta1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: AL2
role: "KarpenterNodeRole-${CLUSTER_NAME}"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "${CLUSTER_NAME}"
blockDeviceMappings:
- deviceName: /dev/xvda
ebs:
volumeSize: 50Gi
volumeType: gp3
encrypted: true
kubectl apply -f ec2nodeclass.yaml
第五步:迁移 Cluster Autoscaler 工作负载
如果你正在从 Cluster Autoscaler 迁移,建议分步进行:
# 暂停 Cluster Autoscaler
kubectl scale deployment cluster-autoscaler \
-n kube-system --replicas=0
# 验证 Karpenter 正常工作后再卸载 CA
helm uninstall cluster-autoscaler -n kube-system
配置说明
Disruption(节点整合)策略
Karpenter 的节点整合功能可以主动合并低利用率节点,降低成本:
disruption:
consolidationPolicy: WhenUnderutilized # 当节点利用率低时整合
# 也可使用 WhenEmpty:仅当节点完全空闲时整合
consolidateAfter: 1m # 等待 1 分钟后执行整合
expireAfter: 168h # 节点存活 7 天后强制轮转(安全补丁)
权重与优先级
多个 NodePool 可以设置权重,Karpenter 优先选择权重高的:
spec:
weight: 100 # 数值越高优先级越高(默认 10)
资源限制
防止 Karpenter 无限扩容,务必设置集群级别的资源上限:
limits:
cpu: "200" # 集群最多 200 核 CPU
memory: 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 -n karpenter -l app.kubernetes.io/name=karpenter \
-c controller --follow
# 观察 NodeClaim 创建过程
kubectl get nodeclaim -w
# 查看节点何时 Ready
kubectl 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 -n karpenter -l app.kubernetes.io/name=karpenter -c controller | grep ERROR
Q:节点被 Karpenter 意外驱逐,如何保护关键 Pod?
为关键工作负载添加 do-not-disrupt 注解:
metadata:
annotations:
karpenter.sh/do-not-disrupt: "true"
Q:如何限制 Karpenter 只使用特定可用区?
在 NodePool requirements 中添加约束:
- key: topology.kubernetes.io/zone
operator: In
values: ["us-east-1a", "us-east-1b"]
Q:Karpenter 与 HPA(Horizontal Pod Autoscaler)如何协同?
HPA 根据 CPU/内存指标水平扩展 Pod 副本数,Karpenter 负责为新 Pod 提供节点。两者天然配合,无需额外配置,形成完整的弹性伸缩链路:指标上升 → HPA 增加副本 → Pod Pending → Karpenter 新增节点。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)