Google Kubernetes Engine(GKE)はKubernetesのマネージドサービスで、マスターノードがホストされています。また、Webの管理コンソールからバージョンを選択するだけでアップグレードも可能です。
ただし、素朴にバージョン更新操作でアップグレードした場合の挙動は、以下のような流れとなり、ダウンタイムが発生します。
- クラスタ内の1ノード停止。ノード上で動作しているPodもTerminate
- 停止ノードのバージョン更新
- 起動中のノードでPodの再作成&起動。空きリソースがない場合はノード更新が終わってReadyステータスになるまでウェイト
- 残りのノードも順次同様の挙動
更新の過程で以下のような挙動となり、サービスが出揃うまで数分〜10分程度かかります。
- 新バージョンのノードにはコンテナイメージのキャッシュがないため、イメージのpullに時間がかかる
- サービスの依存性が解決されない状態を経るため、起動エラーになるコンテナもありうる。前提サービスが起動したあとの再起動で収束する
- dnsサービスなどkubernetesのネットワーク機能も同様のプロセスを減るため、外部ドメインの名前解決ができないタイミングがある
また、Controller経由で管理していないPodはTerminateされたまま消失するので、あらかじめDeploymentやReplicaSetなどを定義して動作させておくことが必要です。
ノード更新はローリングアップデートのため、更新の際だけ1ノード追加して更新後に1ノード削除することでダウンタイムを削減できるのかという点も検証しました。
結果的には、更新時のノード追加は効果的ではありませんでした。
起動中のノードがPodの合計要求値に対して不足する状況は避けられているはずですが、けっきょく別ノードで起動する際にはイメージのpullが走るため、起動までの時間はとくに短縮されません。
また、更新後のプロセスで元のノード数に戻す操作の際にも、起動しているPod数の多いノードも削除対象となります。
そのため、一度更新が終わったはずなのにもう一度Podの再起動(所要時間:数分)が実行され、ダウンタイムが増える結果となりました。
けっきょく、ダウンタイムを減らしたい場合にはブルーグリーンデプロイメントのようにもう1クラスタ用意する必要があります。
ただ、DBMSなどのデータをPersistentDiskに書き込む構成の場合は、新環境のPodでそのPersistentDiskをマウントすることになるため、別のクラスタをあらかじめ構築しておく手法もとりづらい面もあります。
Chuma Takahiro