在 Azure Kubernetes Service 中使用 Azure Spot 实例

2025-08-13#Azure#Kubernetes

出于成本优化的考虑,在 AKS (Azure Kubernetes Service) 可使用 Spot 实例作为工作节点。但是,Spot 实例可能在任何时间被 Azure 关机。不过每种类型的虚拟机都有一个驱逐率( Eviction Rate),该驱逐率以百分比范围表示,例如 0%-5%、5%-10%、10%-15%、15%-20% 或 20% 以上。基于具体需求,要综合考虑成本、VM规格和驱逐率等因素,选择合适的VM类型。同时每个VM类型的驱逐率是随着时间变化的,可能需要定期地更新工作负载所需要的VM类型。

查询相关因素 🔗

VM 的规格 🔗

不同类型的VM有不同的内存、本地存储等,比如Dadsv5 系列就有不同的类型。在网页上检索效率低,可使用 Azure CLI 或者编程语言获取。比如使用 Azure CLI 命令:

az vm list-sizes

驱逐率和价格历史 🔗

参考《Use Azure Spot Virtual Machines》 一文,可在 Azure Resource Graph Explorer 中查询不同 VM 类型的驱逐率:

SpotResources 
| where type =~ 'microsoft.compute/skuspotevictionrate/location' 
| where sku.name in~ ('standard_d2s_v4', 'standard_d4s_v4') 
| where location in~ ('eastus', 'southcentralus') 
| project skuName = tostring(sku.name), location, spotEvictionRate = tostring(properties.evictionRate) 
| order by skuName asc, location asc

使用如下查询获取价格历史:

SpotResources 
| where type =~ 'microsoft.compute/skuspotpricehistory/ostype/location' 
| where sku.name in~ ('standard_d2s_v4', 'standard_d4s_v4') 
| where properties.osType =~ 'linux' 
| where location in~ ('eastus', 'southcentralus') 
| project skuName = tostring(sku.name), osType = tostring(properties.osType), location, latestSpotPriceUSD = todouble(properties.spotPrices[0].priceUSD) 
| order by latestSpotPriceUSD asc

修改节点池的VM类型 🔗

直接修改节点池的 VM 类型是不可能的。为了尽量保证 AKS 服务在线,可使用新的 VM 类型创建新的节点池,然后再删除老的节点池。删除节点池的操作可能会持续很长时间。期间 AKS 会对节点执行清空 (Drain)操作,并可能会失败。

删除节点池时的常见失败是由于 Pod Disruption Budget (POD)策略。Azure 在错误信息中,给出了相关链接 《Troubleshoot UpgradeFailed errors due to eviction failures caused by PDBs》,并建议在删除节点时使用 --ignore-pod-disruption-budget true 选项。但在当前的 az 版本里,应该使用 --ignore-pdb 选项。

如果使用 Pulumi、Terraform 等工具管理基础设置,那么并不能直接在删除时添加 --ignore-pdb 选项。同时,由于删除节点池非常耗时,有可能导致 CD 流水线超时。一种可行的方法是,将修改节点池VM类型的操作分为两次代码提交和多个执行步骤:

  1. 在第一次的代码提交中,使用新的节点池名称(节点池的名称最大长度是 6 个字符),创建新的节点池
  2. 执行部署
  3. 在第二次代码提交中,删除旧的节点池
  4. 执行部署。这一次部署可能失败,如果失败了,那就在 Azure Portal 上手动再次点击删除。直至删除成功

整个部署多长可能非常耗时。