クラウドのリソース不足に備えよ - GKE ComputeClass によるフォールバック運用

目次

はじめに

こんにちは。saorioです。今回は GKE で使える ComputeClass の活用について書きたいと思います。

先日、次のようなニュースがありました。

dealroom.co dealroom.co

AWS のコンピュートリソースは 2026 年分が売り切れ、2027 年分もほぼ売り切れだというのです。これは AWS に限った話ではなく、他のクラウド事業者でも同様だと考えています。実際に筆者も、2026 年の上半期に Google Cloud で同じような現象を経験しました。

VM が立ち上がらない

ある日、VM が起動しなくなりました。よく使う東京リージョンだけでなく、世界中で在庫がないようでした。当時調べた範囲では、汎用マシンである N2D がどのリージョンでも確保できない状態でした。

すぐに別のマシンタイプへ切り替えるという判断もしづらかったのですが、この状態が何日も続いたため、そうも言っていられなくなりました。幸い N4 は東京リージョンで提供が始まっていたので、N4 を試すことにしました。

GCP Batch や GKE でも同じ現象が起きた

VM だけでなく、GCP Batch や GKE でも同様に Node が起動しない現象が起きました。そこで、Cloud Logging で Cluster Autoscaler の scale.up.error.out.of.resources イベントをダッシュボードにし、毎日何件起こっているか確認できるようにしました。

logName="projects/<PROJECT_ID>/logs/container.googleapis.com%2Fcluster-autoscaler-visibility"
jsonPayload.resultInfo.results.errorMsg.messageId="scale.up.error.out.of.resources"

筆者の環境では、リソース不足によるスケールアップ失敗が約 400 回発生しました。特に週の始まりに集中していました。

フォールバックの仕組みを持つ

VM 単体ではこうした状況に対処する手段が限られます(MIG を使っていれば、ある程度は対応できます)。一方、GCP Batch と GKE には、リソース不足時に別の候補へフォールバックするための機能があります。GKE では ComputeClass がそれにあたります。

ComputeClass は非常に便利で、主に次の 3 つのメリットがあります。

  1. Terraform で多数の Node Pool を管理しなくてよくなる。Node Pool が多いと、アップグレード時にそれぞれを更新する必要があり、手間と時間がかかります。ComputeClass では Node Pool が自動作成されるため、この管理が不要になります。
  2. フォールバック先のマシンを複数書ける。単一のマシンタイプが在庫切れになっても、優先度順に別のマシンタイプで Node を起動できます。
  3. Spot VM を活用してコストを削減できる。Spot を優先し、Spot の在庫がないときはオンデマンドで起動する、という設定ができます。

筆者はすでに半年ほど ComputeClass を運用しており、途中から Spot VM を組み合わせたことで、コストを 1/4〜1/5 程度まで下げることができました。

導入方法

当時 1.33 系で動かしていた GKE クラスタは、Node Pool を Terraform で管理していました。これを ComputeClass の YAML による管理へ移行するにあたり、バージョンアップが必要だったため 1.34 系へ更新しました。

ComputeClass は次のように、優先度順にマシンの候補を並べて定義します。

apiVersion: cloud.google.com/v1
kind: ComputeClass
metadata:
  name: batch-fallback
spec:
  priorities:
    # 1. Spot の N2D
    - machineFamily: n2d
      spot: true
    # 2. Spot の N4
    - machineFamily: n4
      spot: true
    # 3. オンデマンドの N2D
    - machineFamily: n2d
    # 4. オンデマンドの N4
    - machineFamily: n4
  nodePoolAutoCreation:
    enabled: true
  whenUnsatisfiable: DoNotScaleUp

Pod や Job 側では、nodeSelector で ComputeClass を指定するだけです。

spec:
  nodeSelector:
    cloud.google.com/compute-class: batch-fallback

なお、デフォルトではスケールの上限(Cap)がないため、1.36 系から使える CapacityQuota を一緒に設定しておくと良いでしょう。設定できる値の一覧は次のリファレンスにまとまっています。

ComputeClass &nbsp;|&nbsp; Google Kubernetes Engine (GKE) &nbsp;|&nbsp; Google Cloud Documentation The ComputeClass custom resource definition (CRD) for controlling GKE node scaling decisions. Google Cloud Documentation

導入した結果

ComputeClass を使うと、Node Pool は nap- という接頭辞(Prefix)付きの名前で自動作成されます。Host名にも napという値が入るので、どれがComputeClassで起動したかがわかります。Job の場合、タスクが終わると Node はスケールダウンして消え、新しく Job を作成するとまた Node が作られる、という動きになります。

Node の起動時間は、筆者の環境ではおおむね 50 秒以内に収まっています。ただし、ときどき 2 分を超えることもあります。そのため運用では、起動にどれくらい時間がかかっているかを継続的にウォッチしています。筆者は Datadog で gcp.gke.node.latencies.startup の値を見ています。同様の値は、GKE の Observability にある Startup Latency のグラフでも確認できると思います。

導入から半年ほど経ち、scale.up.error.out.of.resources イベントはほとんど発生しなくなりました。

おわりに

リソース不足への対策としては、ComputeClass 以外に、Node を常に起動させておく(止めない)方法や、Compute Engine の予約機能を使う方法も検討しました。

About reservations &nbsp;|&nbsp; Compute Engine &nbsp;|&nbsp; Google Cloud Documentation Learn about reservations of Compute Engine VM instances. Google Cloud Documentation

どちらも確実にリソースを確保できる反面、使っていない時間もコストがかかるため、今回は採用を見送りました。

クラウドのリソースは「お金を払えばいつでも使える」ものではなくなりつつあります。リソース不足は今後も起こりうるため、万が一に備えて、この対応はやっておいて損はないと思います。