如何在AWS EKS中配置CPU/GPU节点组调度与自动扩缩容
AWS EKS Pod均衡调度与节点自动扩缩容配置方案
1. 节点组基础标签与污点预处理
先给4个节点组统一打标识标签,同时调整GPU节点默认污点,为后续调度和扩缩容提供判断依据:
- SpotNodeGroup:添加标签
lifecycle: Spot、instance-type: CPU,不配置额外污点 - MainNodeGroup:添加标签
lifecycle: OnDemand、instance-type: CPU,不配置额外污点 - GPUNodeGroup:添加标签
lifecycle: Spot、instance-type: GPU,删除EKS GPU AMI默认添加的nvidia.com/gpu:NoSchedule污点,允许未申请GPU资源的CPU Pod调度到该组节点 - GPUODNodeGroup:添加标签
lifecycle: OnDemand、instance-type: GPU,同样删除GPU专属排斥污点,支持CPU Pod混合调度
注意:如果节点组是通过EKS Managed Node Group创建的,标签和污点配置可以直接在节点组设置页修改,新启动的节点会自动带上对应配置,存量节点手动打标删污点即可。
2. 工作负载调度规则配置
通过节点亲和性+Pod拓扑分布约束实现调度要求,不需要额外安装第三方调度插件:
核心规则逻辑
- 硬约束保证基础副本分布:以
lifecycle标签为拓扑域,强制要求每个服务的副本在Spot、OnDemand两个域的分布偏差不超过1,当服务副本数≥2时,必然有1个副本跑在OnDemand节点、1个跑在Spot节点 - 软偏好实现扩容优先级:给Spot节点配置高权重调度偏好,服务扩容到3、4副本时,优先调度到Spot节点
- 放开CPU Pod调度限制:CPU服务不配置必须跑在CPU节点的硬约束,仅保留低权重偏好,GPU节点有剩余CPU、内存资源时允许CPU Pod调度上来,实现混合部署
- GPU服务硬约束:所有GPU服务必须调度到带
instance-type: GPU标签的节点,避免GPU Pod跑到无GPU卡的CPU节点启动失败
配置示例
CPU服务Deployment调度段参考配置:
spec: replicas: 2 # 基础副本数为2,满足1OD1Spot要求,后续可按需扩容到最高4 template: spec: affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: # 权重80优先选Spot实例 - weight: 80 preference: matchExpressions: - key: lifecycle operator: In values: ["Spot"] # 权重20优先选普通CPU节点,GPU节点有剩余资源时可调度 - weight: 20 preference: matchExpressions: - key: instance-type operator: In values: ["CPU"] podAntiAffinity: # 同服务Pod尽量不堆叠在同一节点,提升可用性 preferredDuringSchedulingIgnoredDuringExecution: - weight: 100 podAffinityTerm: labelSelector: matchLabels: app: <替换为你的服务名> topologyKey: kubernetes.io/hostname topologySpreadConstraints: # 硬约束保证副本均匀分布在Spot/OnDemand域 - maxSkew: 1 topologyKey: lifecycle whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: app: <替换为你的服务名> minDomains: 2 # 必须配置准确的资源请求,否则调度和CA扩缩容计算会出现偏差 resources: requests: cpu: "100m" memory: "256Mi" limits: cpu: "500m" memory: "512Mi"
GPU服务Deployment调度段参考配置,仅需在CPU服务配置基础上增加GPU节点硬亲和即可:
spec: template: spec: affinity: nodeAffinity: # 新增GPU节点硬约束,保证GPU Pod只调度到GPU节点 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: instance-type operator: In values: ["GPU"] preferredDuringSchedulingIgnoredDuringExecution: - weight: 80 preference: matchExpressions: - key: lifecycle operator: In values: ["Spot"] resources: requests: cpu: "1" memory: "2Gi" nvidia.com/gpu: "1" limits: cpu: "2" memory: "4Gi" nvidia.com/gpu: "1"
3. Cluster Autoscaler参数调优
调整已安装的Cluster Autoscaler启动参数,适配少节点、优先Spot、快速缩容的目标:
- 将
--expander参数设置为least-waste:扩容时优先选择部署Pod后剩余资源最少的节点组,尽可能把Pod打包到更少节点上,降低总节点数 - 配置节点组优先级:给SpotNodeGroup、GPUNodeGroup添加标签
k8s.io/cluster-autoscaler/priority: 100,给MainNodeGroup、GPUODNodeGroup添加标签k8s.io/cluster-autoscaler/priority: 10,CA扩容时会优先选择高优先级的Spot节点组弹机器,仅当Spot资源不足时才启动OnDemand节点 - 将
--scale-down-utilization-threshold调整为0.45:节点CPU、内存综合利用率低于45%时就纳入缩容候选,比默认值更激进,及时清理空闲节点 - 配置
--skip-nodes-with-system-pods=false,忽略DaemonSet管理的系统Pod(如CNI插件、kube-proxy)对缩容的判断影响,避免因为节点上跑了DaemonSet Pod就无法缩容 - 调整GPUNodeGroup的EC2 Auto Scaling Group混合实例策略:将g4dn.xlarge设为最高优先级的Spot机型,g4dn.2xlarge、g4dn.4xlarge、p3.2xlarge设为低优先级,避免优先启动大规格GPU节点造成资源浪费。
4. 可选优化项
- 部署Descheduler组件,定期扫描重调度低负载节点上的Pod,触发空闲节点缩容,进一步提升资源利用率
- 给Spot节点上运行的Pod添加
controller.kubernetes.io/pod-deletion-cost: -100注解,服务缩容时优先删除Spot上的多余副本,保留OnDemand上的基础副本 - 配置Spot实例中断通知处理,Spot节点被回收前2分钟会自动触发节点排水,保证服务可用性
内容的提问来源于stack exchange,提问作者dmitrii
相关产品推荐
相关产品推荐

