コンテンツに移動
Containers & Kubernetes

Blibli はどのようにステートフルおよびステートレスのアプリケーションの更新を GKE で管理しているか

2021年9月15日
https://storage.googleapis.com/gweb-cloudblog-publish/images/GCP_Kubernetes_A.max-2600x2600.jpg
Google Cloud Japan Team

※この投稿は米国時間 2021 年 9 月 1 日に、Google Cloud blog に投稿されたものの抄訳です。

当社は、インドネシアで一般消費者向けの e コマース事業を展開する Blibli という会社です。IT インフラストラクチャの大半を Google Kubernetes Engine(GKE)で実行しています。これには、Redis、RabbitMQ、Spring Boot、Jenkins、Grafana など、ステートフルとステートレス双方のアプリケーションが含まれます。

GKE は、スケーラビリティと信頼性に優れた Kubernetes のマネージド サービスを提供し、他の Google Cloud サービスとの統合もスムーズです。当社は GKE を利用することで、インフラストラクチャにかかる費用を 30% 以上節約できるようになりました。しかし、多くの業務を抱え、そのいくつもを同時進行させなければならない企業が陥りがちなように、当社も一時期は、あまりにも多忙なためクラスタやノードプールの更新といったオペレーションを徹底できませんでした。その結果、GKE の現行バージョンよりかなり前のバージョンを実行する事態となりました。

サービス プロバイダとオープンソース ソフトウェア双方のポリシーを遵守するには、バージョンの更新に常に遅れずについていく必要があります。Google Cloud は Kubernetes クラスタを 3 か月周期でリリースするので、これは GKE 上でのワークロード実行における課題となり得ます。しかし現在、当社の GKE クラスタは 1.13.x から 1.15.x に更新され、さまざまなクラスタおよび環境でのその更新の検証も終わっています。それも、サービスの中断なしにです。

アップグレード先のバージョンのリリースノートと変更ログは誰でも読むことができるので、ここでは、当社の更新プロセスの詳細を長々と説明する代わりに、当社がどのように新しいバージョン リリースに合わせて GKE クラスタを最新の状態に保っているか、またどうすれば皆さんもそうできるかをご説明したいと思います。

ダウンタイムなしで GKE クラスタを更新する

GKE クラスタとそれに関連するものすべては、Terraform と GitOps を使って管理しています。この 2 つは更新プロセスの簡略化に有効なツールです。

リージョン クラスタを使用すれば、すべてのゾーンを対象に GKE がコントロール プレーンのレプリカを維持してくれるので、ダウンタイムを回避できます。つまり、単一ゾーンの障害からの回復力がクラスタに付与されるということです。これを実施するときは、リソースの空き状況を十分に確認してください。

クラスタの更新には 2 つの段階があります。最初にコントロール プレーン、次にノードプールです。これには非常に重要なネットワーク上の考慮事項がいくつか伴います。

コントロール プレーン

Kubernetes のコントロール プレーンには、Kubernetes の API サーバー、スケジューラ、コントローラ マネージャー サーバーが含まれます。コントロール プレーンのアップグレードは、1 回クリックするだけであとは GKE が自動で管理してくれるので、とても簡単です(Terraform での変数の変更など)。この更新には数分かかり、その間クラスタの構成は変更できませんが、ワークロードは通常どおり実行できます。

ノードプール

クラスタのノードはデフォルトで自動更新が有効になっており、Google Cloud はこの状態で使用することを推奨しています。自動更新を選択していれば、すべて GKE が自動で行ってくれるので、ユーザーが操作することは特にありません。

コントロール プレーンの場合と違い、ノードプールの更新プロセスは多くの部分が可視化されます。このプロセスには、クラスタ内のノードの総数が大きく影響します。ノードプール内のノードごとに見ると、ノードによるノード Pod のスケジューリングの中断、既存の Pod のドレイン、最後にノードの更新という順で進んでいきます。

当社を含め、依存関係と資格情報を注意深く管理する必要がある組織は、独自のアップグレード ワークフローを管理したほうがよい場合があります。サージ アップグレードを使用すると、GKE が一度に更新できるノード数の管理と、更新によるワークロードの中断を制御できるようになります。ワーカーノードの更新を決定したら、いくつかの選択肢が考えられます。まず一つに、更新を手動でトリガーする方法があります。プロセスは、更新のタイミングの決定以外は自動更新と同様です。

gcloud container clusters upgrade cluster-name  --node-pool=node-pool-name --cluster-version cluster-version

豆知識: ノードプールは、コントロール プレーンのバージョンと一致するバージョンに更新することも、コントロール プレーンと互換性のある過去のバージョン(利用可能なものに限られる)に更新することも可能です。Kubernetes バージョンとバージョン スキューのサポート ポリシーにより、コントロール プレーンよりノードのバージョンが古くても、差異がマイナー バージョン 2 つ以内であれば、コントロール プレーンとノードの互換性が保証されています。たとえば、Kubernetes 1.13.x のコントロール プレーンは、Kubernetes 1.11.x のノードと互換性があります。

いくら GKE が大規模なクラスタをすばやく更新できるとはいえ、実行しているノードが 100 個を超え、GKE のサージ アップグレードも使用しないという条件下では、すべてのノードをドレインしてアップグレードするには時間がいくらあっても足りないだろうと考えました。そこで当社がとった戦略は、アプリケーションの継続的デプロイの活用、およびダウンタイムの回避でした。

ここで、最も関心が高いと思われる実装のパートに移りたいと思います。当社は、ノードプールにある現行のノードを更新する代わりに、バージョン更新済みのノードプールを新しく作成することにしました。ただし、ちょっとした工夫があります。新しいノードプールに付与される taint は、古いバージョンのノードプールに応じて変わります。ではどうしたと思いますか。実は単純なことで、新しいバージョンのノードプールの taint に一致するようアプリケーションをデプロイしたのです。これは皆さんにも可能です。

しかし(何事にも「しかし」はついて回るものです)、ダウンタイムを回避するには、ローリング更新を更新の戦略にする必要があります。加えて、アプリケーションをデプロイする前に確認すべき点が 2 つほどあります。

DaemonSet

作成したノードプールには異なる taint が付与されるため、新しいノードプール内にノードが生成されたらまず、DaemonSet がデプロイされていて正常に稼働していることを確認します。

Pod 停止予算(PDB)

PDB は、停止させる Pod の数と割合をユーザーが制御できるようにするメカニズムです。レプリカ数と PDB は密接に関連するため、当社はワークロードの PDB を maxUnavailable: 1 に設定しました。こうすることで、アプリケーション デプロイのどの段階でも Pod を最低 1 つは確実に実行できるようになります。

読み込んでいます...

ステートフル セットは扱いがたいへん難しいものですが、GKE を利用すればさまざまな方法で管理できます。当社では、ダウンタイムを回避するために以下のようなチェックリストを使用しています。参考にしてみてください。永続ボリューム要求のスナップショットを作成することもできます。

ネットワークのチェックリスト

基本的に、この手法によるノードプール更新では、更新プロセスの間、実行中のクラスタのサイズが倍になります。そのため、ノードが外部と通信する必要性が生じた場合でもプライマリ IP や NAT IP などのネットワーク要件を満たせるように、十分なリソースを確保する必要があります。

次の条件をすべて満たす場合には、下り(外向き)トラフィックのパケットがマスカレードされないため、Pod IP が表示されます。

  • 1.14.x より古いバージョンを実行している

  • 実行中の ip-masq-agent がない

  • CIDR 10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 のいずれかに該当する宛先アドレス範囲がある

解決手段の一つとして、ip-masq-agent を追加し、nonMasqueradeCIDRs 構成に宛先の CIDR をすべて記述する方法があります。

GKE は汎用性の高いプラットフォームで、マイクロサービスの管理と効率的な実行に使用すると大きなメリットを生みます。極めて効果的な Kubernetes フルマネージド ソリューションを、保守の手間を抑えつつ使用したければ、GKE を検討してみてください。そうすれば、基盤となるシステムを管理することではなく、駆使することに力を注ぐことができます。

-Blibli DevOps エンジニア Pelash Choudhary 氏

-Blibli DevOps およびクラウド運用責任者 Santosh Kumar D 氏

投稿先