GKE ノードプールのアップグレードを中断(キャンセル)する

GKE ノードプールのアップグレードがキャンセルできるようになっていたので試してみました。
現状はベータ版として提供されている機能になります。
公式ドキュメントの該当箇所はこちら。

cloud.google.com

検証

GKE では、アップグレードに限らずクラスタに対するオペレーション(作成・削除・アップグレードなど)はその都度オペレーション ID が割り振られるようになっており、gcloud container operations list コマンドで確認することができます。

cloudshell:~ $ gcloud container operations list

...

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

...

検証対象のクラスタ sample-cluster の作成オペレーションが完了していることがわかります。

今回は、コントロールプレーン・ノードプールともに 1.21.5-gke.1302 から 1.21.6-gke.1500 にアップグレードします。
ノードプールはノード数 3 の状態で開始します。
ノードプールのアップグレードを行う前に、まずはコントロールプレーンがノードプールのアップグレード先のバージョンをサポートできるようアップグレードしておきます。

f:id:polar3130:20220120120422p:plain

gcloud container operations list コマンドでオペレーションの状態を確認します。

cloudshell:~ $ gcloud container operations list

...

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

NAME: operation-1642599713836-a095ee51
TYPE: UPGRADE_MASTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: RUNNING
START_TIME: 2022-01-19T13:41:53.836300031Z
END_TIME:

...

コントロールプレーンのアップグレードが開始されていることがわかります。
今回検証するキャンセルの機能はノードプールのアップグレードが対象とされていますが、試しにこの状態でもオペレーションのキャンセルをリクエストしてみます。

GKE クラスタに対するオペレーションのキャンセルはベータ機能であるため、gcloud beta コマンドを使います。
gcloud beta container operations cancel コマンドのリファレンスは以下で確認することができます。

cloud.google.com

cloudshell:~ $ gcloud beta container operations cancel operation-1642599713836-a095ee51
Are you sure you want to cancel operation operation-1642599713836-a095ee51?

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

ERROR: (gcloud.beta.container.operations.cancel) INVALID_ARGUMENT: Only node upgrade operations can be cancelled.

エラーになりました。
メッセージにもあるとおり、やはりノードプールのアップグレードのみがサポートされていることがわかります。

コントロールプレーンのアップグレードが完了したのち、ノードプールのアップグレードを行います。

f:id:polar3130:20220120120429p:plain

gcloud container operations list コマンドでオペレーションの状態を確認します。

cloudshell:~ $ gcloud container operations list

...

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

NAME: operation-1642599713836-a095ee51
TYPE: UPGRADE_MASTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T13:41:53.836300031Z
END_TIME: 2022-01-19T14:06:04.341528233Z

NAME: operation-1642601615896-46119ad0
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE:
STATUS: RUNNING
START_TIME: 2022-01-19T14:13:35.896076128Z
END_TIME:

...

ノードのアップグレードは正常に開始されているようです。
では、一部のノードのアップグレードが完了したところを見計らってキャンセルしてみます。
コンソールではノードプールが以下のような状態となっていました。

f:id:polar3130:20220120120437p:plain

ここで、先程と同様に gcloud beta container operations cancel コマンドを実行します。

cloudshell:~ $ gcloud beta container operations cancel operation-1642601615896-46119ad0
Are you sure you want to cancel operation operation-1642601615896-46119ad0?

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

Cancelation of operation operation-1642601615896-46119ad0 has been requested. Please use gcloud container operations describe operation-1642601615896-46119ad0 to check if the operation has been canceled successfully.
detail: 'Updating default-pool, done with 1 out of 3 nodes (33.3%): 1 being processed'
name: operation-1642601615896-46119ad0
operationType: UPGRADE_NODES
progress:
  metrics:
  - intValue: '3'
    name: NODES_TOTAL
  - intValue: '0'
    name: NODES_FAILED
  - intValue: '1'
    name: NODES_COMPLETE
  - intValue: '1'
    name: NODES_DONE
  - intValue: '0'
    name: NODE_PDB_DELAY_SECONDS
selfLink: https://container.googleapis.com/v1beta1/projects/************/locations/asia-northeast1/operations/operation-1642601615896-46119ad0
startTime: '2022-01-19T14:13:35.896076128Z'
status: ABORTING
targetLink: https://container.googleapis.com/v1beta1/projects/************/locations/asia-northeast1/clusters/sample-cluster/nodePools/default-pool
zone: asia-northeast1

キャンセルのリクエストが受け付けられました。
detail の内容はコンソールで確認したノードプールの状態と一致しています。
この時点では status が ABORTING となっており、キャンセルが成否を問わずリクエストの受付が完了した時点でコマンドへの応答が行われていることがわかります。

メッセージの指示にあるとおり、キャンセルの成否は別途 gcloud container operations describe コマンドで確認する必要があります。
キャンセルのリクエストをかけたのち間を置かずに確認しましたが、既にキャンセルのリクエストは成功していました。
結果は下記のように出力されました。

cloudshell:~ $ gcloud container operations describe operation-1642601615896-46119ad0
clusterConditions:
- canonicalCode: CANCELLED
  message: 'Operation was aborted: operation-1642601615896-46119ad0.'
detail: 'Operation was aborted: operation-1642601615896-46119ad0.'
endTime: '2022-01-19T14:21:01.520708481Z'
error:
  code: 1
  message: 'Operation was aborted: operation-1642601615896-46119ad0.'
name: operation-1642601615896-46119ad0
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/************/locations/asia-northeast1/operations/operation-1642601615896-46119ad0
startTime: '2022-01-19T14:13:35.896076128Z'
status: DONE
statusMessage: 'Operation was aborted: operation-1642601615896-46119ad0.'
targetLink: https://container.googleapis.com/v1/projects/************/locations/asia-northeast1/clusters/sample-cluster/nodePools/default-pool
zone: asia-northeast1

gcloud beta container operations list コマンドでも確認してみます。

cloudshell:~ $ gcloud container operations list

...

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

NAME: operation-1642599713836-a095ee51
TYPE: UPGRADE_MASTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T13:41:53.836300031Z
END_TIME: 2022-01-19T14:06:04.341528233Z

NAME: operation-1642601615896-46119ad0
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE: Operation was aborted: operation-1642601615896-46119ad0.
STATUS: DONE
START_TIME: 2022-01-19T14:13:35.896076128Z
END_TIME: 2022-01-19T14:21:01.520708481Z

NAME: operation-1642602132989-39493995
TYPE: UPDATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T14:22:12.989734846Z
END_TIME: 2022-01-19T14:22:13.741871596Z

...

キャンセルが完了していることが確認できました。
アップグレードは最後まで完了しなかったため、コンソール上の当該ノードプールはアップグレード前のバージョンとして表示されています。

f:id:polar3130:20220120120441p:plain

しかし、実際には一部のノードのアップグレードが完了していたため、ノードのバージョンが混在した状態となっています。

cloudshell:~ $ kubectl get node
NAME                                            STATUS                     ROLES    AGE    VERSION
gke-sample-cluster-default-pool-4a3a874a-0mqn   Ready                      <none>   16m    v1.21.6-gke.1500
gke-sample-cluster-default-pool-7a3668ce-5tb7   Ready                      <none>   100m   v1.21.5-gke.1302
gke-sample-cluster-default-pool-8005ab02-2iq1   Ready                      <none>   10m    v1.21.6-gke.1500
gke-sample-cluster-default-pool-8005ab02-79ff   Ready,SchedulingDisabled   <none>   101m   v1.21.5-gke.1302

コンソールでは以下のように見えています。

f:id:polar3130:20220120120447p:plain

ここで、元のノードプールのサイズは 3 でしたが、キャンセル後のノード数は 4 に増えています。
これはサージアップグレードを有効化(max surge: 1)していたためで、アップグレード中に新しいノードを追加し、そのセットアップが完了して古いノードを cordon したあたりでキャンセルが受け付けられたようです。

f:id:polar3130:20220120120454p:plain

ではこの状態でもう一度アップグレードをリクエストするとどうなるか試してみます。
先ほどと同じようにノードプールのアップグレードを開始します。 4 台のノードに対してアップグレードのプロセスを開始していることが確認できます。

f:id:polar3130:20220120120502p:plain

gcloud beta container operations list コマンドでも確認してみます。

cloudshell:~ $ gcloud container operations list

...

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

NAME: operation-1642599713836-a095ee51
TYPE: UPGRADE_MASTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T13:41:53.836300031Z
END_TIME: 2022-01-19T14:06:04.341528233Z

NAME: operation-1642601615896-46119ad0
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE: Operation was aborted: operation-1642601615896-46119ad0.
STATUS: DONE
START_TIME: 2022-01-19T14:13:35.896076128Z
END_TIME: 2022-01-19T14:21:01.520708481Z

NAME: operation-1642602132989-39493995
TYPE: UPDATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T14:22:12.989734846Z
END_TIME: 2022-01-19T14:22:13.741871596Z

NAME: operation-1642603081158-8a2f2134
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE:
STATUS: RUNNING
START_TIME: 2022-01-19T14:38:01.158573778Z
END_TIME:

...

その後、アップグレードが完了すると、コンソールでは以下のように表示されました。

f:id:polar3130:20220120120508p:plain

改めて gcloud beta container operations list コマンドでも確認してみます。

cloudshell:~ $ gcloud container operations list

NAME: operation-1642596393580-28fce564
TYPE: CREATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T12:46:33.580352532Z
END_TIME: 2022-01-19T12:50:24.97742246Z

NAME: operation-1642599713836-a095ee51
TYPE: UPGRADE_MASTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T13:41:53.836300031Z
END_TIME: 2022-01-19T14:06:04.341528233Z

NAME: operation-1642601615896-46119ad0
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE: Operation was aborted: operation-1642601615896-46119ad0.
STATUS: DONE
START_TIME: 2022-01-19T14:13:35.896076128Z
END_TIME: 2022-01-19T14:21:01.520708481Z

NAME: operation-1642602132989-39493995
TYPE: UPDATE_CLUSTER
LOCATION: asia-northeast1
TARGET: sample-cluster
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T14:22:12.989734846Z
END_TIME: 2022-01-19T14:22:13.741871596Z

NAME: operation-1642603081158-8a2f2134
TYPE: UPGRADE_NODES
LOCATION: asia-northeast1
TARGET: default-pool
STATUS_MESSAGE:
STATUS: DONE
START_TIME: 2022-01-19T14:38:01.158573778Z
END_TIME: 2022-01-19T14:44:55.142139747Z

...

kubectl get nodes コマンドの実行結果は以下のとおりです。

cloudshell:~ $ kubectl get nodes
NAME                                            STATUS   ROLES    AGE     VERSION
gke-sample-cluster-default-pool-4a3a874a-0mqn   Ready    <none>   31m     v1.21.6-gke.1500
gke-sample-cluster-default-pool-7a3668ce-yhk7   Ready    <none>   4m37s   v1.21.6-gke.1500
gke-sample-cluster-default-pool-8005ab02-2iq1   Ready    <none>   26m     v1.21.6-gke.1500

ノード数は 3 となっており、すべてのノードが v1.21.6-gke.1500 にアップグレードされたことがわかります。
ノードの作成時間からして、中断した 1 回目のアップグレードでアップグレードが完了したノードはそのまま使われる(再作成はしない)ようですね。
また、1 回目のアップグレードと 2 回目のアップグレードは独立したオペレーションなのでノードプールのサイズは 4 のままアップグレードが完了するのではと思ったのですが、実際には元のノードプールのサイズに収束したことが確認できました。

キャンセルの使い所

今回試したアップグレードのキャンセルの機能は、例えばノードプールのアップグレード中に障害が発生した場合などに活用できそうです。
従来、ノードプールのアップグレードが開始されるとクラスタアンタッチャブルな状態となってしまうため、アップグレード中に障害が発生するなどして特定のノードを切り離したいという状況下においてもユーザにはアップグレードの完了を待つしか選択肢がありませんでした。
アップグレードがキャンセルできるようになったことで、アップグレードが長時間化する状況下でも、ある程度短い待ち時間でクラスタへの操作権をユーザに戻すことができるようになりました。

まとめ

GKE におけるノードプールのアップグレードをキャンセルする機能について基本的な動作の確認をしました。
アップグレードが想定外に長期化するようなシチュエーションでも、「いざとなれば中断できる」という選択肢ができたことで安心感してアップグレードの完了を待てそうです。