EKS Managed Node GroupでSpot Instanceを使うために調べたことまとめ

5 min read読了の目安(約4800字

これは何?

EKS Managed Node Groupに対してSpot Instanceを使いたくなって調べた際のまとめです。

経緯

EKS Managed Node GroupでSpot Instanceが解禁されてたので導入したい。
Amazon EKS が、マネージド型ノードグループでの EC2 スポットインスタンスのプロビジョニングと管理をサポートに記載されている通り、EKSのworker nodeでもSpot Instanceが使用できるようになり、Spot Instanceを使いたいなとなった。

Spot Instanceの仕様概説

EKS Managed Node Groupに使用するSpot Instanceの仕様はざっくり以下の感じです。

  • Instanceの割り当て戦略は capacity-optimized が適応されている
  • Capacity Rebalancing により、Spot Instanceが中断されるリスクを早期検知してInstanceの入れ替えを行う
    • 基本的にはGraceful shutdownかつ、今動いてるinstanceがterminateされる前に新しいinstanceがreadyになる
    • ただし必ず保証されているわけではなく、場合によっては(on-demanで要求されるインスタンス数が爆上がりするなど?)EC2のterminate 2分前通知と同じタイミングで実行されることもあり、代わりのnodeがreadyになる前に既存のnodeがterminateされる可能性もある
    • 参考
  • Spot Instanceには eks.amazonaws.com/capacityType=SPOT というラベルが付与されている
    • Affinity, AntiAffinityなどに使える
  • 最も遅い場合でterminate 2分前にシステムの停止作業が行われる
    • EC2にシグナルが送られ、停止へと向かう

Spot Instanceを使う上での注意点

  • いつEC2がTerminateされてもいいように、フォールトトレラントのアプリケーションに対して使用すること
    • 最悪のケースではSpot Instanceがterminateされる2分前にterminateの準備が始まる
    • DaemonSetや監視ツール用のnodeに対しては推奨されてない
  • アプリケーションの可用性を高めるために、マネージド型ノードグループに複数のインスタンスタイプを含めること
    • 特定のインスタンスタイプが必ず空いているという保証はない
    • ほぼ同量の vCPU とメモリを持つ全てのインスタンスタイプを全て指定するのが推奨されている
      • 例)m5.xlarge, m4.xlarge, m5a.xlarge, m5d.xlarge, …
  • 1つのNode Groupに対してはOn-Demand or Spot Instanceのどちらかのみ指定できる
    • 切り替える場合にはNode Groupが作り直される
  • Spot Instanceのmax料金設定はできない
    • Managed Node Groupに対する指定は未対応の模様(Terraformでの挙動を見る限り)
      • その他、普通のlaunch templateでは指定できるものができなかったりする

Terraformでの適応方法

基本的には aws_eks_node_groupcapacity_typeSPOT にするだけでSpot Instanceをつかえるようになります。
Resource: aws_eks_node_groupにも以下のように記載があります。

capacity_type - (Optional) Type of capacity associated with the EKS Node Group. Valid values: ON_DEMAND, SPOT. Terraform will only perform drift detection if a configuration value is provided.

ただし aws_launch_templateaws_eks_node_group を併用した場合、設定値に制約があるのでapplyして確認するのが安全そう。
例えば capacity_type=SPOT を指定すると、 aws_launch_templateinstance_market_options が使用できない。

variable "is_prod" { type = bool }

resource "aws_launch_template" "eks_worker_template" {
  name     = "launch_template"

  # Spot Instanceを利用する場合にはaws_eks_node_group側でinstance typeを指定する
  instance_type  = var.is_prod ? "t3.medium" : ""

  # いろいろ設定が続く...
}

resource "aws_eks_node_group" "eks_worker" {
  cluster_name = "eks-cluster-name"
  node_group_name = "node-group-name"

  capacity_type = var.is_prod ? "ON_DEMAND" : "SPOT"
  instance_types = local.is_prod ? [] : ["t3.medium", "t2.medium"]

  launch_template {
    id      = aws_launch_template.eks_worker_template.id
    version = aws_launch_template.eks_worker_template.latest_version
  }

  # いろいろ設定が続く...
}

雑感

  • 設定1つでSpot Instanceに切り替えられるのはとても便利
  • 便利すぎて仕様を理解してないと何かあった際に障害に繋がりそう

参考

概念系

Terraforem実装系