AKS にスポットノードプールを追加してみた

AKS (Azure Kubernetes Service) にスポットノードプールを追加してみました。

以下のドキュメントを参考にしました。

docs.microsoft.com

動機

スポットノードプールを試した理由ですが、AKS を安く使えると思ったから です。

AKS は最低でも 1 台のノードを含む 1 つのノードプールが必要です。 この 1 台分の料金をスポットノードプールを使うことで、スポット料金が適用されて通常のノードを使うよりも安く済むと考えました。

結論から言うと、できません!安くなりません!

スポットノードプール

スポットノードプールとは

スポット VM という、Azure の余っているリソースを通常より安く利用できる VMAKS で利用するノードプールです。 安く利用できる反面、Azure のリソースが不足してきたら自動で VM は排除されてしまいます。

AKS でのスポットノードプールの利用は、バッチ処理ジョブ や 開発・テスト環境 といったワークロードが適しているようです。

制限事項

スポットノードプールにはいくつかの制限事項があります。 ここでは一部だけ抜粋して紹介しますので、詳しくは公式ドキュメントを参照ください。

  • 規定のノードプールに設定不可

    スポットノード プールを AKS クラスタの既定のノード プールにすることはできません。 つまり、AKS クラスタでスポットノードプールのみ利用することはできません。

この時点で、「AKS を安く使う」という動機が満たせないことが分かりました…。 とりあえず、AKS クラスタにスポットノードプールを追加することは試してみました。

AKS クラスタにスポットノードプール追加

AKS クラスタ構築

まずは AKS クラスタを構築します。 今回はノードプールを最小構成 サイズ:Standard_B2S, ノード数:1 で構築しました。

$ az aks create \
    --resource-group aks \
    --name aks-test \
    --location japaneast \
    --kubernetes-version 1.19.3 \
    --node-vm-size Standard_B2S \
    --node-count 1 \
    --no-wait

構築完了後は、ノードプールが 1 つだけ作成されています。

f:id:nnstt1:20201220233314p:plain

このノードプールで使用しているノードサイズ Standard_B2S月額 ¥4,447.744 です。 もしスポット VM として利用できれば、60% オフの 月額 ¥1,779.0976 となります。

f:id:nnstt1:20201221000624p:plain

スポットノードプール追加

次に、構築した AKS クラスタにスポットノードプールを追加します。

公式ドキュメントベースの設定で az aks nodepool add コマンドを実行します。 コマンド自体は通常のノードプールを追加するものと同じです。 --priority, --eviction-policy, --spot-max-price がスポットノードプール用のオプションになります。

az aks nodepool add \
    --resource-group aks \
    --cluster-name aks-test \
    --name spotnodepool \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --no-wait

spotnodepool という名前のノードプールが追加されました。(画像はプール作成途中です)

追加されたスポットノードプールの状態を見てみると、 サイズ:Standard_DS2_v2, ノード数:3 になっています。 コマンドでノードサイズを指定しない場合はデフォルトの Standard_DS2_v2 になります。

オプションの --enable-cluster-autoscalerAKSクラスタオートスケーラを有効化しており、 オートスケーラによる最大ノード数を --max-count で指定しているためノード数が 3 となっています。

f:id:nnstt1:20201220235303p:plain

Standard_DS2_v2 のスポット料金は通常の 78% オフとなりますが、Standard_B2S と比べると約 2 倍の料金となります。 また、ノード数も 3 となっているので 3 台分の料金が掛かります。

f:id:nnstt1:20201221000336p:plain

これでは、せっかくスポットノードプールを使っていても高くついてしまうため、 既定のノードプールと同じく サイズ:Standard_B2S, ノード数:1 でスポットノードプールを作ってみます。

Standard_B2S のスポットノードプール追加

まずは、ノードサイズに Standard_B2S を指定します。

az aks nodepool add \
    --resource-group aks \
    --cluster-name aks-test \
    --name spotnodepool \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --node-vm-size Standard_B2S \    # このオプションを追加
    --no-wait

上記コマンドを実行するとスポットノードプールの作成は始まるのですが、 最終的には Failed となってしまいました。

Azure に Standard_B2S 用のリソースが余ってないということでしょうか。 執筆時点では原因は分かっていません…。

f:id:nnstt1:20201221001908p:plain

ノード数 1 のスポットノードプール追加

次に、ノード数が 1 となるように指定します。

az aks nodepool add \
    --resource-group aks \
    --cluster-name aks-test \
    --name spotnodepool \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 1 \    # 3 → 1 に変更
    --no-wait

上記コマンドを実行すると node-count is not in the range of min-count and max-count というエラーになりました。 どうやら --min-count--max-count は同じ値にしてはいけないようです。

--node-count オプションでノード数を指定してみます。

az aks nodepool add \
    --resource-group aks \
    --cluster-name aks-test \
    --name spotnodepool \
    --priority Spot \
    --eviction-policy Delete \
    --spot-max-price -1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 3 \
    --node-count 1 \    # ノード数指定
    --no-wait

この指定方法だとノード数を 1 にできました。

f:id:nnstt1:20201221003632p:plain

まとめ

スポットノードプールを使って AKS を安く使う計画はうまくいきませんでした。

しかし、ノードの冗長構成を検証するなどであれば、通常のノードプールを使うよりも費用は抑えられ、 勝手にノードが削除されることを利用した可用性の確認などもできるかもしれません。