Azure - AKS - Spot Node Pool

31 October 2020 — Written by Sky Chang
#Azure#Container#Kubernetes#Docker#Linux#AKS

前言

至從 Spot 推出後,完全受到小弟的歡迎,因為透過 Spot 的特性與價格 ( 最重要的是價格 ),讓小弟在做很多測試的時候,可以無後顧之憂 ( 比較不會被老闆宰了~ ),所以現在很多的環境,例如模擬地端的 K8S VM,測試開發環境用的 VM,還有 Azure DevOps Server、AD 等等,之前都全部一口氣改成了 Spot VM 的模式來進行測試。

當然,Spot 的特性就是便宜,已超乎想像的價格提供給我們使用,But 啊 But,任何事情,便宜一定有一定的限制。例如,節點是沒有 SLA 的,節點基本上都是會部署在單一容錯網域中。( 當然,也不用想去開高可用性區用這個功能 )。另外,當 Azure 需要資源的時候,你的機器就會 "被收回!!"。

好吧,你想說,這種沒通知的收回,怎麼可能拿來使用!?,的確啦,正式環境很不適合,隨時有可能被回收的情況,也表示隨時會被老闆罵死。所以如果是正式環境,當然還是建議使用標準的 VM。( 備註,MSDN 提供的免費訂閱,也不可以用在正式環境喔~ )

至於 Spot,當然就很適合批次處理工作、開發和測試環境。所以對小弟來說,就是要拿來測試的環境,當然就是用 Spot 囉。

( 或許大家會想,應該不會真的回收吧,不好意思,小弟還真的滿常遇過,就在 Demo 的當下,真的被回收了 T^T )。

好,前面講了很多 Spot VM 的特性,而 AKS,也在不久之前,推出了 Spot Node,當然因為底層和 VM 是依樣的,所以這些 Spot Node,也是會有 Spot VM 同樣的特性。但對於我們要測試一些 AKS 的功能與服務的時候,Spot Node 還是一個很棒的選擇。

而 Spot Node Pool 目前有底下此限制。( 請注意,限制可能會隨著 AKS 更新而改變,請留意官網文件 )

但目前有幾個比較需要注意的。

  • 你的 AKS 還是需要一個預設的 Node Pool,不能全部都是 Spot Node Pool

    • 原本小弟就有一個 System Node Pool 了
  • Spot Node Pool 會無法升級 Spot Node Pool 的 K8S 版本

    • 未來只能自己建立新的 Node Pool 來轉移
  • 建立完後,目前沒辦法設定 ScaleSetPriority 或 SpotMaxPrice

    • 通常設定完就不會改了
  • 設定 SpotMaxPrice 時,值必須是-1 或具有最多五個小數位數的正數值

    • 下指令需注意一下
  • 點節點集區會有標籤 kubernetes.azure.com/scalesetpriority:spot、污點 kubernetes.azure.com/scalesetpriority=spot:NoSchedule 和 System pod 會有反親和性

    • 也無仿,反正原本我就將 System Pod 塞到 System Pool Node 了
  • 必須在 Yaml 新增 tolerations,才能放到 Spot Pool Node

    • 這個倒是有點小討厭 XDDD

建立 Spot Node Pool

如前一篇文章Azure - 建立 Azure Kubernetes Service - 2020-10-19 version,有提到,在 AKS ,其實是很多 Node Pool 組合而成的,而在前篇,我們建立了一個 System Node Pool,和一個 DefaultApp 的 User Node Pool,現在我們多建立一個 Spot Node Pool。

寫此稿的時候,Spot Node 雖然 GA,但還沒 UI。所以必須要透過 az cli 來處理。

( 其實寫這篇文章,寫到一半,剛好就看到 Tom 哥的發文,只能說,Tom 哥真是神算啊!!)

要執行,可以透過底下指令新增 Spot Node Pool。

請注意, spot-max-price -1 的定義如下

  • 使用默認的 Spot 價格
  • 該實例不會因價格而被關閉 ( 因為已經使用默認了 )
  • 價格為 Spot 當前價格或標準價格,通常只要有可用的容量和配額,價格就會更低 ( 但容量不夠,還是會被回收 Orz )

如果您想要定義自己的價格,可以在 spot-max-price 後面加上價格,加上去後,也代表,當股價,喔不是,當目前的費用超過此價格時,就會自動關閉回收。

eviction-policy 參數有兩個,一個是 Delete 和 Deallocate,當使用 Deallocate 的時候,若 VM 被收走,則會呈現關閉的狀況,雖然是關閉,但還是會有磁碟的費用產生,而且被關閉的 VM,還是會佔用掉 Auto Scale 的 Instance,其次,也有可能資源要不回來....

至於 Delete,就是真的砍掉,但好處是不回佔用 Auto Scale 的 Instace,而且,磁碟不會被收費 ( 畢竟都被砍光 = =|| )

而通常,我們會加上 enable-cluster-autoscaler 這個參數,因為透過這個參數和 Delete 匹配後,就可以想用到,被回收砍 Node,但有需要再自動加回來的機制。若沒有起用 autoscaler,那可能會被砍到變成 0 .....

最後,下面指令有啟用使用 Temp Disk,且只設定 30G,因為 D4as_V4 的 Temp Disk 也只有 32G,所以只能設定為最小,這邊就看需求,看要不要自行加上 node-osdisk-type Ephemeral 和 node-osdisk-size 30

Note : 請注意,選擇的 VM,是否有支援 Spot。

# 底下會用到一些上一篇用到的指令,例如 :
# ppg、node-osdisk-size、node-osdisk-type、aks-custom-headers
# 若有需要了解這些功能,請參考上一篇
# 若要使用 Ephemeral 磁碟,請注意選的 VM 暫存磁碟的大小是否有大於 node-osdist-size

# 若要使用 PPG ,請填入 PPG ID
MY_PPG_RESOURCE_ID=/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/Study4Dev-JE/providers/Microsoft.Compute/proximityPlacementGroups/Study4Dev-JE-PPG

az aks nodepool add \
    --resource-group study4dev-je \
    --cluster-name aks-study4dev-je \
    --name spotnodepool \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --max-pods 40 \
    --mode User\
    --kubernetes-version 1.19.0 \
    --node-vm-size Standard_D4as_v4 \
    --zones 1 \
    --ppg $MY_PPG_RESOURCE_ID \
    --node-osdisk-size 30 \
    --node-osdisk-type Ephemeral \
    --aks-custom-headers EnableAzureDiskFileCSIDriver=true,CustomizedUbuntu=aks-ubuntu-1804,ContainerRuntime=containerd

預設情況下,建立好的 Spot Node Pool,會加上 spot 的污點,所以如果有應用程式要部署到這個 Spot Node Pool 上,則需要使用底下的寫法 ( 寫法來自官網,也是標準的 K8S tolerations 寫法。 )

spec:
  containers:
  - name: spot-example
  tolerations:
  - key: "kubernetes.azure.com/scalesetpriority"
    operator: "Equal"
    value: "spot"
    effect: "NoSchedule"

大體上就這樣了,對於要開發測試來說,Spot 還是很好用的 :)

後記

其實這篇寫了後,擱置了很多天,因為過程中,Spot 變成 GA,而導致 az cli 的指令發生 500 錯誤 = =|||..不過 Azure 的好處也是有 bug,後端收到 Log,也自動地修復 XDD ( 但看起來假日沒排班... ),所以在修復後,也終於可以發了這篇 XDDDD

參考資料

Sky & Study4.TW