GKE ノードプールの並行アップグレード

Google Cloud Next '23 、盛り上がっていますね!
AI / ML 系のアップデートが目玉となっていますが、その他のサービスでも数多くのアップデートがリリースされています。
本記事では、Google Cloud Next '23 の開催期間中に発表された GKE 関連のアップデートのなかでも個人的に注目の「ノードプールの並行アップグレード」をピックアップしてご紹介します。

リリースノートはこちら:

cloud.google.com

機能概要

GKE は、ひとつのクラスタにワークロードやインスタンスタイプに応じた複数のノードプールを設けることができます。
従来、GKE のアップグレードや自動プロビジョニングを行う場合は、いずれかのノードプールでアップグレードやプロビジョニングなどの構成変更が行われている間、他のノードプールやクラスタの設定を変更することができないという制約がありました。
今回のアップデートにより、GKE クラスタ内の複数のノードプールを並行してアップグレード・自動プロビジョニングすることができるようになったため、上記の運用上の制約が解消されました。

このアップデートに関して特定のドキュメントは設けられていないようですが、リリースノートによれば既に GKE のすべてのバージョンで利用可能となっているようです。

実機検証

早速、実機で並行アップグレードを試してみたいと思います。
どのバージョンでも利用可能とのことだったので、あえて最新ではない GKE 1.23 (1.23.17-gke.10700) のクラスタを用意しました。
ふたつのノードプール (pool-1, pool-2) も作成しておきます。

$ gcloud container clusters describe sample-cluster
...
currentMasterVersion: 1.23.17-gke.10700
currentNodeCount: 6
currentNodeVersion: 1.23.17-gke.10700
initialClusterVersion: 1.23.17-gke.10700
location: us-central1
locations:
- us-central1-a
- us-central1-c
- us-central1-f
name: sample-cluster
nodeConfig:
  diskSizeGb: 50
  diskType: pd-balanced
  imageType: COS_CONTAINERD
  machineType: e2-small
  ...
nodePoolAutoConfig: {}
nodePoolDefaults:
  nodeConfigDefaults:
    loggingConfig:
      variantConfig:
        variant: DEFAULT
nodePools:
- autoscaling: {}
  config:
    diskSizeGb: 50
    diskType: pd-balanced
    imageType: COS_CONTAINERD
    machineType: e2-small
    ...
  initialNodeCount: 1
  locations:
  - us-central1-a
  - us-central1-c
  - us-central1-f
  management:
    autoRepair: true
    autoUpgrade: true
  maxPodsConstraint:
    maxPodsPerNode: '110'
  name: pool-1
  status: RUNNING
  upgradeSettings:
    maxSurge: 1
    strategy: SURGE
  version: 1.23.17-gke.10700
- autoscaling: {}
  config:
    diskSizeGb: 50
    diskType: pd-balanced
    imageType: COS_CONTAINERD
    machineType: e2-small
    ...
  initialNodeCount: 1
  locations:
  - us-central1-a
  - us-central1-c
  - us-central1-f
  management:
    autoRepair: true
    autoUpgrade: true
  maxPodsConstraint:
    maxPodsPerNode: '110'
  name: pool-2
  status: RUNNING
  upgradeSettings:
    maxSurge: 1
    strategy: SURGE
  version: 1.23.17-gke.10700
releaseChannel: {}
status: RUNNING
zone: us-central1

ノードプールのアップグレードを検証するには、先にクラスタのコントロールプレーンのバージョンをアップグレードしておかなければなりません。
今回はまずコントロールプレーンを 1.24.16-gke.500 に手動アップグレードします。

$ gcloud container clusters upgrade sample-cluster --master --cluster-version 1.24.16-gke.500
Master of cluster [sample-cluster] will be upgraded from version [1.23.17-gke.10700] to version [1.24.16-gke.500]. This operation is long-running and will block other operations on the cluster (including delete) until it has run to completion.

Do you want to continue (Y/n)?  Y

...

アップグレードが開始されました。
コントロールプレーンのアップグレード中は、ユーザがクラスタの構成(ノードプールの追加や削除、既存ノードプールのサイズ変更、クラスタの削除など)が一切行えません。
コンソールで確認すると以下のような表示となっており、クラスタやノードプールの設定を変更するボタンが押せなくなっていることがわかります(API でリクエストしてもエラーが返却されます)。

コントロールプレーンのアップグレードが完了したら、次は pool-1 のアップグレードに進みます。 こちらも 1.24.16-gke.500 に手動アップグレードします。

$ gcloud container clusters list
NAME: sample-cluster
LOCATION: us-central1
MASTER_VERSION: 1.24.16-gke.500
MASTER_IP: 34.132.4.227
MACHINE_TYPE: e2-small
NODE_VERSION: 1.23.17-gke.10700 *
NUM_NODES: 6
STATUS: RUNNING

* - There is an upgrade available for your cluster(s).

To upgrade nodes to the latest available version, run
  $ gcloud container clusters upgrade NAME
  
$ gcloud container clusters upgrade sample-cluster --node-pool=pool-1 --cluster-version 1.24.16-gke.500
All nodes in node pool [pool-1] of cluster [sample-cluster] will be upgraded from version [1.23.17-gke.10700] to version [1.24.16-gke.500]. This operation is long-running and will block other operations 
on the cluster (including delete) until it has run to completion.

Do you want to continue (Y/n)?  Y

Upgrading sample-cluster...Updating pool-1, done with 0 out of 3 nodes (0.0%): 1 being processed...working..    

アップグレードが開始されました。
従来であれば、ノードプールのアップグレード中においても、コントロールプレーンのアップグレードと同様に、いずれかのノードプールでアップグレードが行われている最中は別のノードプールの構成を変更することができませんでした。

それではここで、pool-1 のアップグレードの最中ですが pool-2 のアップグレードもリクエストしてみましょう。

$ gcloud container clusters upgrade sample-cluster --node-pool=pool-2 --cluster-version 1.24.16-gke.500
All nodes in node pool [pool-2] of cluster [sample-cluster] will be upgraded from version [1.23.17-gke.10700] to version [1.24.16-gke.500]. This operation is long-running and will block other operations 
on the cluster (including delete) until it has run to completion.

Do you want to continue (Y/n)?  Y

Upgrading sample-cluster... Updating pool-2, done with 0 out of 3 nodes (0.0%): 1 being processed...working..                                                                                             

pool-1 のアップグレード実行中に、pool-2 も並行してアップグレードを開始することができました。
コンソールでは以下のような表示になっていました。
「ノードプールを追加」のボタンは依然としてグレーアウトされているため、コンソールでの操作にはまだ対応していないようですが、同時に複数のノードプールのアップグレードが進行していることがわかります。

ちなみにプログレスバーが 2 本表示されていますが、これだけではどちらのバーがどちらのノードプールを指しているのか一見わからない表示となっています。
見た目の問題ではありますが、今後の改善に期待したいですね。

追加検証

ここからは、他のパターンでも複数のノードプールの構成変更が並行できるのかを試してみたいと思います。
まずは、pool-1 と pool-2 の同時アップグレード中に、pool-2 のアップグレードを中断してみましょう。
ノードプールのアップグレードを中断するには、クラスタに対するオペレーション ID を取得し、gcloud container operations cancel コマンドを実行します。
なお、ノードプールのアップグレードの中断を行うと、アップグレード未了のノードは古いバージョンのままとなりますが、アップグレードが完了しているノードはロールバックされず、先のオペレーションでアップグレードされたバージョンのままとなります。

$ gcloud container operations list
NAME: operation-1693444380760-f5e0b489-04d0-495d-9f8a-ba613bc87bdb
TYPE: CREATE_CLUSTER
LOCATION: us-central1
TARGET: sample-cluster
STATUS_MESSAGE: 
STATUS: DONE
START_TIME: 2023-08-31T09:13:00.760134453Z
END_TIME: 2023-08-31T09:17:42.6150337Z

NAME: operation-1693446415977-691a9f00-3221-4e62-ab01-16731084b815
TYPE: UPGRADE_MASTER
LOCATION: us-central1
TARGET: sample-cluster
STATUS_MESSAGE: 
STATUS: DONE
START_TIME: 2023-08-31T09:46:55.977872348Z
END_TIME: 2023-08-31T10:13:50.711133596Z

NAME: operation-1693448209722-720779cc-1896-4ffa-b956-3f9bc38581d2
TYPE: UPGRADE_NODES
LOCATION: us-central1
TARGET: pool-1
STATUS_MESSAGE: 
STATUS: RUNNING
START_TIME: 2023-08-31T10:16:49.722711057Z
END_TIME: 

NAME: operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b
TYPE: UPGRADE_NODES
LOCATION: us-central1
TARGET: pool-2
STATUS_MESSAGE: 
STATUS: RUNNING
START_TIME: 2023-08-31T10:19:51.857597571Z
END_TIME: 

$ gcloud container operations cancel operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b
Are you sure you want to cancel operation operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b?

Do you want to continue (Y/n)?  Y

Cancelation of operation operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b has been requested. Please use gcloud container operations describe operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b to check if the operation has been canceled successfully.
detail: 'Updating pool-2, done with 2 out of 3 nodes (66.7%): 1 being processed'
name: operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b
operationType: UPGRADE_NODES
progress:
  metrics:
  - intValue: '3'
    name: NODES_TOTAL
  - intValue: '0'
    name: NODES_FAILED
  - intValue: '2'
    name: NODES_COMPLETE
  - intValue: '2'
    name: NODES_DONE
  - intValue: '0'
    name: NODE_PDB_DELAY_SECONDS
selfLink: https://container.googleapis.com/v1/projects/950837876919/locations/us-central1/operations/operation-1693448391857-34fcdbe6-faed-4512-b636-1577dd989f0b
startTime: '2023-08-31T10:19:51.857597571Z'
status: ABORTING
targetLink: https://container.googleapis.com/v1/projects/950837876919/locations/us-central1/clusters/sample-cluster/nodePools/pool-2
zone: us-central1

引き続き pool-1 はアップグレード中ですが、pool-2 のアップグレードを中断させることができました。

次に、pool-1 がアップグレード中のまま、pool-2 アップグレードを再開してみます。
アップグレードを再開する場合は、通常のアップグレードと同じコマンドを再度実行するだけで再開できます。

$ gcloud container clusters upgrade sample-cluster --node-pool=pool-2  --cluster-version 1.24.16-gke.500
All nodes in node pool [pool-2] of cluster [sample-cluster] will be upgraded from version [1.24.16-gke.500] to version [1.24.16-gke.500]. This operation is long-running and will block other operations on
 the cluster (including delete) until it has run to completion.

Do you want to continue (Y/n)?  Y

Upgrading sample-cluster... Updating pool-2, done with 2 out of 3 nodes (66.7%): 1 succeeded...done.   

こちらも問題なくオペレーションできました。

pool-1 のアップグレードは完了しましたが、中断後に再開した pool-2 は引き続きアップグレードが進行中です。
そこで今度は、 pool-2 のアップグレード中に新しく pool-3 というノードプールを作成してみましょう。

$ gcloud beta container --project "hypnotic-surge-397600" node-pools create "pool-3" --cluster "sample-cluster" --region "us-central1" --node-version "1.24.16-gke.500" --machine-type "e2-small" --image-type "COS_CONTAINERD" --disk-type "pd-balanced" --disk-size "20" --metadata disable-legacy-endpoints=true --scopes 
...
Note: Node version is specified while node auto-upgrade is enabled. Node-pools created at the specified version will be auto-upgraded whenever auto-upgrade preconditions are met.
Creating node pool pool-3...working..          

こちらも問題なくオペレーションできました。

更に、pool-2 のアップグレード完了後、 pool-3 のアップグレード中に今度は pool-2 のスケールアウト(ノードプールのサイズ変更)を行ってみましょう。

$ gcloud container clusters resize sample-cluster --node-pool pool-2 --num-nodes 2
Pool [pool-2] for [sample-cluster] will be resized to 2 node(s) in each zone it spans.

Do you want to continue (Y/n)?  Y

Resizing sample-cluster...working..                                                                                                                                                                       

こちらも問題なくオペレーションできました。

コンソールからも、pool-2 のサイズ変更と pool-3 の新規作成が並行して実行できていることがわかります。

利用時の注意点

主なユースケースとしては、これまで直列に実行する必要のあった複数ノードプールのアップグレードの並行実施が考えられます。
アップグレード戦略によりますが、サージアップグレードの場合は最大サージ(max-surge-upgrade)とオフライン上限(max-unavailable-upgrade)の設定に注意しましょう。
並行で複数のノードプールのアップグレードを実行することで、あるタイミングで利用できないノードの数が直列で実施しているときよりも増えるため、クラスタ全体の利用可能リソースが少なくなり、最悪の場合古いノードを Evict しても新しいスケジュール先を確保できない、という状況に陥る可能性が出てくるかもしれません。
同時にアップグレードを行ってもクラスタのリソースの総量として問題がないかを事前に確認する、あるいはより安全なアップグレードを計画したい場合は Blue / Green によるアップグレード戦略を選択すると良いでしょう。

また、今回のアップデートによって、ノードプールのアップグレード中にトラブルが起きた場合の対応の選択肢が増えました(以前はアップグレード中のノードプールのオペレーションを中断することがまずもって必要でしたが、今回からはアップグレードをそのまま進行させておき、別途ノードプールを新規作成する、などの方法も採れるようになりました)。
そのため、ノードプールのアップグレード中のトラブル対応については想定しておくべきシナリオがかなり簡略化されたように思います。
しかし、依然としてコントロールプレーンのアップグレード中は構成変更やキャンセルが一切行えないため、アップグレード中にトラブルが起きた場合の対応を考えておく必要があることは意識しておきましょう(例えば手動でノードプールのサイジングを行っている場合は、リクエストの急増などでノードを追加したいと思ってもコントロールプレーンのアップグレード中であればその完了を待つまでノードを追加することはできません)。

まとめ

Google Cloud Next '23 で登場した GKE のアップデートの中から、「ノードプールの並行アップグレード」について、実機検証を交えてご紹介しました。
多数のノードプールを抱えているクラスタではアップグレードの総所要時間の短縮や、トラブル発生時のロールバックの高速化などに役立ちそうです。
地味ながら、日々 GKE の運用と格闘している人たちにとっては大きなアップデートになったのではないでしょうか。