Kubernetes Karpenter 节点自动供给
Karpenter 是 Kubernetes 新一代的节点自动供给(Node Auto Provisioning)解决方案,专为现代云原生工作负载设计,特别是 GPU 推理等需要快速弹性扩展的场景。相比传统的 Cluster Autoscaler,Karpenter 提供了更快的节点启动速度、更灵活的实例选择和更精细的资源调度能力。在 GPU 推理服务场景中,Karpenter 是实现 Pod 和节点协同弹性的关键组件。
Karpenter 核心概念
什么是 Karpenter
Karpenter 是一个开源的 Kubernetes 节点供给器,它能够根据 Pending Pod 的需求自动创建最合适的节点。与 Cluster Autoscaler 不同,Karpenter 直接与云厂商 API 交互,可以更快速地响应资源需求变化,并且提供了更灵活实例类型选择策略。
Karpenter 的工作原理可以概括为以下几个核心概念。首先是 NodePool(节点池),NodePool 定义了节点的配置模板,包括实例类型、标签、污点、容量限制等。当集群中有 Pending Pod 无法被调度时,Karpenter 会根据 Pod 的资源请求和 NodePool 的配置自动创建合适的节点。其次是 Consolidation(整合),Karpenter 支持自动整合空闲节点,通过合并或 consolidation 来优化成本。第三是 Capacity Types(容量类型),Karpenter 支持按需(On-Demand)和竞价(Spot)实例的混合使用。
Karpenter 与 Cluster Autoscaler 的对比
Cluster Autoscaler 是 Kubernetes 最早期的节点自动供给方案,而 Karpenter 是后起之秀,设计上更加现代化。在 GPU 推理场景中,Karpenter 的优势更加明显。
从响应速度来看,Cluster Autoscaler 通常需要 30 秒到数分钟,而 Karpenter 可以更快地在 10 秒内开始节点创建。从实例选择来看,Cluster Autoscaler 受限于节点组配置,选择不够灵活,而 Karpenter 可以根据 Pod 请求动态选择最合适的实例类型。从成本优化来看,Cluster Autoscaler 支持基础的 Spot 实例,而 Karpenter 支持更细粒度的成本控制。从扩展性来看,Cluster Autoscaler 扩展性有限,而 Karpenter 支持更多云厂商和配置选项。
为什么 GPU 推理需要 Karpenter
GPU 推理服务的弹性不仅仅依赖于 Pod 级别的扩缩容,更关键的是节点级别的弹性。当推理请求增加时,Pod 可以通过 HPA 或 KEDA 扩容,但如果节点上没有可用的 GPU,Pod 会一直处于 Pending 状态,用户请求仍然会超时。这就是 GPU 推理服务中最常见的「假扩容」问题。
Karpenter 能够很好地解决这个问题。当 Pending Pod 请求 GPU 资源时,Karpenter 会自动识别并快速创建带有合适 GPU 的节点。这种 Pod 和节点的协同弹性是 GPU 推理服务稳定运行的基础。
Karpenter 核心概念详解
NodePool
NodePool 是 Karpenter 的核心资源,定义了如何创建节点。NodePool 的配置非常灵活,可以根据不同的工作负载需求创建不同的节点类型。
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-inference
spec:
template:
metadata:
labels:
workload-type: online-inference
accelerator: nvidia-l40s
spec:
requirements:
# 架构要求
- key: kubernetes.io/arch
operator: In
values: [amd64]
# 实例类别(g 表示 GPU 实例)
- key: karpenter.k8s.aws/instance-category
operator: In
values: [g]
# GPU 数量
- key: karpenter.k8s.aws/instance-gpu-count
operator: In
values: ["1", "4", "8"]
# GPU 类型
- key: karpenter.k8s.aws/instance-gpu-name
operator: In
values: [l40s, a10g, h100]
# 容量类型
- key: karpenter.k8s.aws/instance-capacity-type
operator: In
values: [on-demand, spot]
# 污点配置,防止普通 Pod 调度到 GPU 节点
taints:
- key: nvidia.com/gpu
effect: NoSchedule
# 节点标签
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodeclass
# 破坏策略(节点回收策略)
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 300s
# 节点过期时间
expireAfter: 720h
# 资源限制
limits:
cpu: "1000"
memory: 1000Ti
nvidia.com/gpu: "100"这个配置定义了一个用于在线推理的 GPU 节点池,要求节点带有 NVIDIA GPU(L40s/A10g/H100),使用 on-demand 或 spot 实例,节点上有 GPU 污点防止普通 Pod 占用。
EC2NodeClass
EC2NodeClass 定义了如何与 AWS API 交互创建节点:
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: gpu-nodeclass
spec:
# IAM 角色(需要 Karpenter 控制器权限)
role: KarpenterNodeRole
# AMI 配置
amiFamily: AL2023
# 标签配置
tags:
Environment: production
workload-type: inference
# 用户数据(节点初始化脚本)
userData: |
#!/bin/bash
echo "Hello from Karpenter user data"
# 块设备配置
blockDeviceMappings:
- deviceName: /dev/sda1
ebs:
volumeSize: 100Gi
volumeType: gp3
# 安全组配置
securityGroupSelector:
karpenter.sh/discovery: gpu-cluster
# 子网配置
subnetSelector:
karpenter.sh/discovery: gpu-clusterConsolidation 策略
Karpenter 支持多种节点整合策略,用于优化成本:
- WhenEmpty:当节点上没有 Pod 时删除节点
- WhenUnderutilized:当节点资源利用率低时删除或整合节点
- WhenEmptyOrUnderutilized:结合以上两种策略
- Never:不自动删除节点
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 300s # 等待 5 分钟确认多个 NodePool 的设计
建议在 GPU 推理场景中设置多个 NodePool:
# 核心在线池 - 使用稳定实例
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-core
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-capacity-type
operator: In
values: [on-demand]
taints:
- key: workload-type
value: core
effect: NoSchedule
limits:
nvidia.com/gpu: "50"
---
# 弹性池 - 允许使用 Spot
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-elastic
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-capacity-type
operator: In
values: [spot]
taints:
- key: workload-type
value: elastic
effect: NoSchedule
limits:
nvidia.com/gpu: "100"Karpenter 在 GPU 推理中的应用
GPU 节点池设计
建议至少拆成三类节点池:
| 节点池 | 用途 | 实例类型 | 保留容量 |
|---|---|---|---|
| 在线核心池 | 承接高优先级在线推理 | On-Demand | 保留基础容量 |
| 弹性池 | 应对流量峰值 | On-Demand + Spot | 按需补货 |
| 低价池 | 批处理或可降级流量 | Spot | 按需 |
标签设计上建议明确:
nodeSelector:
workload-type: online-inference
accelerator: nvidia-l40s
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoSchedule与 HPA/KEDA 协同
Karpenter 与 HPA/KEDA 的协同是 GPU 推理弹性扩展的关键:
- 流量增加 → KEDA/HPA 检测到指标超阈值
- KEDA/HPA 增加 Pod 副本数
- 新 Pod 创建但 Pending(无 GPU 节点)
- Karpenter 检测到 Pending Pod
- Karpenter 根据 NodePool 配置启动新 GPU 节点
- 节点 Ready 后,Pod 被调度并运行
- 服务 Ready 后接收流量
这种协同需要确保:HPA/KEDA 的 maxReplicas 不会超过 Karpenter 的 limits;节点启动时间需要考虑在扩容延迟中;预留核心池的基础容量。
镜像预拉取和模型缓存
为了减少冷启动时间,建议配合镜像预拉取和模型缓存:
# DaemonSet 预拉取镜像
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: image-prepull
spec:
template:
spec:
containers:
- name: prepull
image: registry.example.com/llm-inference:v1.0.0
command: ["sleep", "infinity"]模型缓存可以使用 localPV 或共享存储(如 EFS/FSx for Lustre)。
Karpenter 安装
# 使用 Helm 安装
helm repo add karpenter https://刻 Karpenter.github.io/charts
helm install karpenter karpenter/karpenter \
--namespace karpenter \
--create-namespace \
--set serviceAccount.create=true \
--set settings.featureGates.disruptionGracePeriod=30s \
--set controller.resources.requests.cpu=1 \
--set controller.resources.requests.memory=1Gi \
--set controller.resources.limits.cpu=1 \
--set controller.resources.limits.memory=1GiKarpenter 监控和调试
查看节点状态
# 查看 Karpenter 管理的节点
kubectl get nodes -l karpenter.sh/nodepool
# 查看 NodePool 状态
kubectl get nodepool
# 查看 Karpenter 控制器日志
kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter常见问题排查
问题:节点创建失败
可能原因:AWS 配额不足、IAM 权限不足、可用区资源不足。检查 Karpenter 控制器日志和 AWS 控制台。
问题:Pod 长时间 Pending
可能原因:节点启动时间过长或节点不足。检查节点创建进度和 NodePool 配置。
问题:Spot 实例被回收
可能原因:Spot 实例被云厂商回收。设计应用时需要支持驱逐容忍(tolerations)。
问题:节点创建太快导致成本增加
可能原因:consolidation 策略过于激进。调整 consolidateAfter 和 limits。
Karpenter 最佳实践总结
在 GPU 推理服务中使用 Karpenter 时,有几个关键的最佳实践。首先是多 NodePool 设计:为不同优先级的工作负载使用不同的 NodePool,核心业务使用 On-Demand,低优先级使用 Spot。其次是合理的 limits:根据集群容量设置 GPU 数量限制,防止无限扩容。第三是配合镜像预拉取:使用 DaemonSet 预拉取镜像,减少节点启动后的拉镜像时间。第四是模型缓存:将模型缓存到节点本地或共享存储,减少冷启动时间。第五是监控节点创建时间:节点创建时间应该在可接受的范围内,否则需要优化。
多云支持
虽然 Karpenter 最初为 AWS 设计,但现在也支持其他云厂商:
- AWS:EC2 NodeClass
- Azure:AzureNodeClass(预览)
- GCP:GCPNodeClass(开发中)
- 阿里云:社区开发中
如果使用其他云厂商,可能需要使用 Cluster Autoscaler 或其他方案。
总结
Karpenter 是 Kubernetes GPU 推理服务弹性扩展的关键组件。它能够快速响应 GPU Pod 的资源需求,自动创建合适的 GPU 节点,实现 Pod 和节点的协同弹性。在使用时,需要根据业务需求设计合理的 NodePool,配合镜像预拉取和模型缓存优化冷启动时间,并设置合理的 limits 防止无限扩容。
