场景
结合SPOT 实例来运行超大规模工作负载同时节省成本,spot实例费用最多不超过按需实例单价/小时,根据时间、区域、可用区都在动态浮动,通常节省60-70之间浮动。
EKS 使用Spot 实例最佳实践
https://aws.amazon.com/cn/blogs/china/eks-use-spot-instance-best-practice/?nc1=b_rp
- 选择不同的Spot资源池,降低资源回收对整体负载的影响(选择更多实例类型和不同可用区)
- 需要结合Cluster Autoscaler(CA)组件一起使用来完成集群的动态扩缩容容,因为CA的扩展策略算法的限制,同一个Nodegroup内的所有实例类型的CPU 核数和内存必须一致。
- 通过配置instanceSelector中定义cpu和memory,可以自动帮助我们筛选实例类型(可选:不需要考虑实例选型的烦恼,通常还需要考虑实例类型如:计算/内存/spot实例近期成本等因素)
nodeGroups:
- name: ng
instanceSelector:
vCPUs: 2
memory: "4" # 4 GiB, unit defaults to GiB
gpus:
managedNodeGroups:
- name: mng
instanceSelector:
vCPUs: 2
memory: 2GiB #
cpuArchitecture: x86_64 # default value
gpus:
- ASG 设置中可以配置On-demand 和 Spot的比例,这样可以在Spot 资源出现大量回收的时候有On-demoand 托底资源,这虽然是个好办法,但是我们更建议扩充Spot 实例类型选择来提供ASG更充沛的资源选择,而不是使用On-demand进行托底,因为在CA 进行缩容策略的时候,无法感知ASG的on-demand和Spot比例,造成缩容时候关闭了托底的on-demond实例,后续ASG需要平衡比例,进行新的切换,可能也会带来业务的短暂不稳定。
- 注:目前如果使用Capacity Rebalance 调度资源建议时需要使用托管节点组,托管节点组会在节点终结前自动的调用Kubernates API对 Pod 进行调度,非托管节点组(二次开发)目前只能根据RBR信号创建新的节点关闭资源紧张的资源池节点,但是不能够自动调度Pod
eksctl配置项
https://eksctl.io/usage/schema/#nodeGroups-instancesDistribution-onDemandBaseCapacity
托管节点组(spot)
https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/managed-node-groups.html
以下预置配置基于spot实例最佳实践并且不可修改:
-
预置 Spot 容量的分配策略设置为 capacity-optimized,以确保您的 Spot 节点在最佳 Spot 容量池中进行配置。(在不同的Spot 资源池中挑选资源最充沛的资源池给到用户使用,从而降低中断概率)
-
启用了 Amazon EC2 Spot 容量再平衡,目标是确保不间断地处理工作负载,类似滚动升级,以便 Amazon EKS 能够顺畅地耗尽和重新平衡您的 Spot 节点,从而在 Spot 节点中断风险增加时最大限度地减少应用程序中断。(主动管理 Auto Scaling 组中的 Amazon EC2 Spot 实例生命周期,先启动1个新节点,当新节点ready后才会驱逐回收节点的Pods,这样在节点启动过程中,Pods并没有因为提前驱逐而影响访问,同时Pods的schedule 过程中,无需CA扩展策略的影响,直接通过Scheduler 部署,节省了不必要的时间开销)
-
Spot 节点收到再平衡建议时,Amazon EKS 会自动尝试启动新的替换 Spot 节点,并等待它成功加入集群。
-
当替换 Spot 节点引导启动并在 Kubernetes 中处于 Ready 状态后,Amazon EKS 将封锁并耗尽收到再平衡建议的 Spot 节点。封锁 Spot 节点可确保服务控制器不会向此 Spot 节点发送任何新请求。它还将其从其运行状况良好的活动 Spot 节点列表中删除。耗尽 Spot 节点可确保正在运行的 Pod 被自然地逐出。
-
如果 Spot 两分钟中断通知在替换 Spot 节点进入 Ready 状态之前到达时间,Amazon EKS 将开始耗尽收到再平衡建议的 Spot 节点。
-
-
Amazon EKS 会向您指定了容量类型的托管节点组中的所有节点添加以下 Kubernetes 标注:eks.amazonaws.com/capacityType: SPOT。您可以使用此标注在 Spot 节点上安排容错应用程序。
managedNodeGroups:
- name: mg-autoscaler-spot
instanceTypes: specifies a list of instance types string[]
spot: true
非托管节点组(spot)
https://docs.aws.amazon.com/zh_cn/eks/latest/userguide/worker.html
以下仅是列出典型配置,详情参看eksctl配置项,通过instancesDistribution配置spot实例,同时最大化的支持用户自定义配置,托管节点组则是根据最佳实践给出的通用配置
nodeGroups:
- name: autoscaler-spot
instancesDistribution: # 配置spot
maxPrice: 3 # 最大价格/h,RMB
instanceTypes: ["c3.xlarge", "c4.xlarge"]
onDemandBaseCapacity: 0 # ondemand实例数量
onDemandPercentageAboveBaseCapacity: 0 # ondemand实例占比
spotInstancePools: 2
spotAllocationStrategy: "capacity-optimized" # 推荐spot分配策略
capacityRebalance: false # 再平衡规则默认关闭,若使用需要自己实现:根据RBR信号创建新的节点关闭资源紧张的资源池节点,但是依然无法自动调度Pod,也需要想办法自己实现
kubeletExtraConfig: # 自定义kubelet启动参数
kubeReserved:
cpu: "100m"
memory: "300Mi"
ephemeral-storage: "1Gi"
kubeReservedCgroup: "/kube-reserved"
systemReserved:
cpu: "100m"
memory: "300Mi"
ephemeral-storage: "1Gi"
evictionHard:
memory.available: "200Mi"
nodefs.available: "10%"
featureGates:
DynamicKubeletConfig: true
RotateKubeletServerCertificate: true
结论
综上所述,通过 capacity-optimized 来选择最划算的spot节点,通过再平衡来最大化的保证spot节点的可用性。其中非托管节点组(nodeGroups)相比托管节点组(managedNodeGroups)增加了很多可自定义的参数,如果托管节点组默认的通用配置无法满足个别应用场景,可以考虑使用非托管节点组。实际场景中为了达到更智能的Spot调度效果,建议使用托管节点组,非托管节点组在spot实例容量平衡、pod优雅迁移这里比较粗犷,需要自己实现相关功能。
托管/ 非托管对比
配置成本:简单、复杂
可靠性:高、低(默认没有二次开发)
维护成本:低、高
费用:略高(先启动再过渡)、低