スケーラブルなクラスタを作成するためのガイドライン

このドキュメントでは、既知の Kubernetes の制限に近づいている際のワークロードに対応できる GKE クラスタの作成、構成、操作方法を決定するためのガイダンスを示します。

スケーラビリティとは

Kubernetes クラスタでは、スケーラビリティは、サービスレベル目標(SLO)を超えない範囲でのクラスタの拡張の機能を示します。Kubernetes には固有の SLO セットもあります。

Kubernetes は複合的なシステムであり、スケーリングできるかどうかは複数の要素によって決定されます。要素には、ノードプール内のノードのタイプと数、ノードプールのタイプと数、使用可能なポッドの数、リソースのポッドへの割り当て方法、サービスの数、サービスの背後で実行されるバックエンド数などがあります。

可用性に関する対策

リージョンまたはゾーンのコントロール プレーンの選択

アーキテクチャの違いにより、リージョン クラスタは高可用性のほうが適しています。リージョン クラスタには、リージョン内の複数のコンピューティング ゾーンに複数のマスターノードがあり、ゾーンクラスタには、単一のコンピューティング ゾーンに 1 個のマスターノードがあります。

ゾーンクラスタがアップグレードされると、単一のマスター VM にはダウンタイムが発生し、Kubernetes API はアップグレードが完了するまで使用できません。

リージョン クラスタでは、IP のローテーション、マスター VM のアップグレード、クラスタまたはノードプールのサイズ変更などのクラスタのメンテナンス中も、コントロール プレーンを使用できます。リージョン クラスタをアップグレードする場合、ローリング アップグレード中は 3 つのうち 2 つのマスター VM が常に実行中となるため、Kubernetes API を引き続き使用できます。同様に、シングルゾーンの停止によってリージョンのコントロール プレーンにダウンタイムが発生することもありません。

ただし、より高可用性のリージョン クラスタには次のような一定のトレードオフがあります。

  • クラスタの校正の変更は、ゾーンクラスタ内の単一のコントロール プレーンではなく、リージョン クラスタ内のすべてのマスターに反映される必要があるため、より長い時間を要します。

  • リージョン クラスタは、ゾーンクラスタほど頻繁に作成またはアップグレードできない場合があります。いずれかのゾーンで容量の不足またはその他の一時的な問題により VM を作成できない場合、クラスタの作成またはアップグレードはできません。

これらのトレードオフのため、ゾーンクラスタとリージョン クラスタのユースケースは異なります。

  • 可用性の重要度が比較的低い場合は、クラスタを迅速に作成またはアップグレードするには、ゾーンクラスタを使用します。
  • 柔軟性よりも可用性が重要な場合は、リージョン クラスタを使用します。

クラスタを作成した後は変更できないため、クラスタを作成する際にはクラスタタイプを慎重に選択してください。変更できないことにより、新しいクラスタを作成してからトラフィックを移行する必要があります。クラスタ間で本番環境トラフィックを移行することは可能ですが、大規模な場合は困難です。

ノードプールをマルチゾーンか、ゾーンのいずれにするかの選択

高可用性を実現するため、Kubernetes コントロール プレーンとそのノードを異なるゾーンに分散する必要があります。GKE には、ゾーンとマルチゾーンの 2 種類のノードプールがあります。

高可用性アプリケーションをデプロイするには、ゾーン全体のノードを均等に分散するマルチゾーン ノードプールを使用して、リージョン内の複数のコンピューティング ゾーンにワークロードを分散します。

すべてのノードが同じゾーンにある場合、ゾーンがアクセス不能になった場合に、ポッドのスケジュールを設定できなくなります。マルチゾーンのノードプールの使用には次のようなトレードオフがあります。

スケーリングに関する対策

ベース インフラストラクチャ

Kubernetes ワークロードにはネットワーキング、コンピューティング、ストレージが必要です。ポッドを実行するのに十分な CPU とメモリを用意する必要があります。ただし、GKE クラスタのパフォーマンスとスケーラビリティに影響する可能性のある、基盤となるインフラストラクチャのパラメータが他にもあります。

クラスタ ネットワーク

GKE には、「古いルートベース」と「新しい VPC ネイティブ」の 2 種類のクラスタ ネットワークがあります。

  • ルートベースのクラスタ: ノードが追加されるたびに、VPC ネットワークのルーティング テーブルにカスタムルートが追加されます。

  • VPC ネイティブのクラスタ: このモードでは、VPC ネットワークにはすべてのポッド IP アドレスのセカンダリ範囲があります。その後、各ノードに特定のポッド IP アドレス用のセカンダリ範囲のスライスが割り当てられます。これにより、VPC ネットワークは、カスタムルートに依存せずにポッドにトラフィックをルーティングする方法をネイティブに理解できます。1 つの VPC ネットワークは最大 15,000 の VM 接続に対応できるため、VPC ネイティブのクラスタは最大 5,000 ノードまでスケーリングできます。

VPC ネイティブのクラスタにおける IP の管理

VPC ネイティブのクラスタは、ノードのプライマリ IP 範囲とポッドとサービスの 2 つのセカンダリ IP 範囲を使用します。VPC ネイティブのクラスタ内のノードの最大数は、使用可能な IP アドレスによって制限されることがあります。ノード数は、プライマリ範囲(ノードのサブネット)とセカンダリ範囲(ポッドのサブネット)の両方によって決まります。ポッドとサービスの最大数は、クラスタのセカンダリ範囲のサイズ、ポッドのサブネット、サービスのサブネットによってそれぞれ決定されます。

デフォルトでの設定:

  • ポッドのセカンダリ範囲のデフォルトは /14 です(262,144 件の IP アドレス)。
  • 各ノードには、/24 の範囲がポッドに割り当てられます(ポッド用の 256 件の IP アドレス)。
  • ノードのサブネットは /20 です(4092 件の IP アドレス)です。

ただし、新しいノードをプロビジョニングするには、両方の範囲(ノードとポッド)内に十分なアドレスが必要です。デフォルトでは、ポッド IP の数により、作成できるのは 1024 件のみです。

デフォルトでは、1 ノードあたり最大 110 ポッドの設定が可能で、クラスタ内の各ノードはポッドに /24 の範囲を割り当てます。これにより、1 ノードあたり 256 件のポッド IP が設定されます。指定できるポッドの約 2 倍の数の利用可能な IP アドレスを指定することで、ポッドがノードに追加されたりノードから削除されたりするときに、Kubernetes によって IP アドレスの再利用を軽減できます。ただし、スケジュール設定するノードあたりのポッド数が少ない一部のアプリケーションでは、やや効率が低くなります。Flexible Pod CIDR 機能を使用すると、ノードごとにポッドの CIDR ブロックサイズを設定し、使用する IP アドレスを減らすことができます。

デフォルトでは、サービスのセカンダリ範囲は /20 に設定されており(4,096 件の IP アドレス)、クラスタ内のサービス数を 4,096 に制限しています。

パフォーマンス向上のためのノードの構成

GKE ノードは標準の Google Cloud の仮想マシンです。たとえば、コアの数やディスクのサイズなどのパラメータには、GKE クラスタのパフォーマンスに影響するものもあります。

下りトラフィック

Google Cloud では、インスタンスに割り当てられるコアの数によってネットワーク容量が決まります。1 つの仮想コアは 2 Gbps の下りの帯域幅を提供し、Skylake マシンでの最大帯域幅は 16 Gbps または 32 Gbps です(ベータ版の機能)。すべての共有コア マシンタイプでは 1 Gbps に制限されます。

IOPS とディスク スループット

Google Cloud では、永続ディスクのサイズによって、IOPS とディスクのスループットが決まります。通常、GKE は永続ディスクをブートディスクとして使用し、Kubernetes の永続ボリュームをバックアップします。ディスクサイズを増やすと、IOPS とスループットの両方が特定の上限まで向上します。

永続ディスクへの書き込み操作を行うたびに、仮想マシン インスタンスの累積下りネットワークの上限に向かって累積されます。したがって、ディスク(特に SSD)の IOPS パフォーマンスは、ディスクサイズだけでなく、インスタンスの vCPU の数によっても異なります。書き込みスループットに対する下りネットワークの上限のため、コア数の少ない VM のほうが書き込み IOPS が低くなります。

仮想マシン インスタンスの CPU が不足している場合、アプリケーションは IOPS の上限に近づくことはできなくなります。原則として、予想されるトラフィックの 2,000~2,500 IOPS ごとに 1 個の CPU が必要です。

大容量または多数のディスクを必要とするワークロードでは、1 つの VM に接続できる PD の数の上限を考慮する必要があります。通常の VM では、上限は合計サイズ 64 TB の 128 ディスクであり、共有コア VM の上限は、合計サイズ 3 TB の PD 16 個です。この上限を適用するのは Kubernetes ではなく、Google Cloud です。

上限について

Kubernetes には、他のシステムと同様に、アプリケーションの設計や拡大を計画する際に考慮すべき上限があります。

Kubernetes は、単一クラスタで最大 5,000 ノードをサポートします。ただし、Kubernetes は大規模な機能面を備える複雑なシステムです。ノード数はあくまで Kubernetes がスケーリングできる多くのディメンションの 1 つです。その他のディメンションには、ポッドの総数、サービスの総数、サービスの背後で実行されるバックエンドの総数などがあります。

一度に複数のディメンションを広げないようにしてください。このストレスは、たとえ小さなクラスタであっても問題を発生させる可能性があります。

例えば、5,000 ノードのクラスタでノードあたり 100 ポッドのスケジュールを設定しようとしても、ポッド数、ノードあたりのポッド数、ノード数が多くなりすぎるため、失敗する可能性が高くなります。

ディメンションの上限

Kubernetes の上限の公式リストをご覧ください。

以下のリストや例は、Kubernetes の上限をすべて記載しているわけではありません。これらの数値は、拡張機能がインストールされていない単純な Kubernetes クラスタを使用して取得されます。Webhooks や CRD を使用して Kubernetes クラスタを拡張することは一般的ですが、クラスタのスケーリング機能が制限される可能性があります。

これらの上限のほとんどは適用されないため、上限を超えることができます。上限を超えても、クラスタは即座には使用できなくなりません。障害が発生する前にパフォーマンスが低下します(SLO が失敗することもあります)。また、可能な限り最大限のクラスタに上限が適用されることがあります。小規模なクラスタでは、上限が比例して低くなります。

  • ノードあたりのポッドの数。GKE にはノードあたり 110 のポッドのハードリミットがあります。これは、ポッドあたり平均 2 つ以下のコンテナを前提としています。コンテナごとに割り当てられるリソースもあるため、コンテナ数が多すぎると 110 の上限が削減されることがあります。

  • サービスの合計数は 10,000 を超えないようにする必要があります。iptables のパフォーマンスは、サービスが多すぎる場合、またはサービスの背後で実行されるバックエンドの数が多い場合は低下します。

  • 1 つのサービスの背後のポッド数は、250 未満に保つと安全です。Kube-proxy はすべてのノードで実行され、エンドポイントとサービスに対するすべての変更を監視します。そのため、クラスタが大きいほど、送信されるデータは多くなります。ハードリミットは、ポッド名の長さと名前空間の長さに応じて、5,000 前後です。もっと長い場合は、エンドポイント オブジェクトが etcd 行の最大サイズを超える etcd に、より多くのバイト数が保存されます。バックエンドが増えると、トラフィック更新は、特に大規模なクラスタ(500 ノード以上)で大きくなります。サービスの背後にあるポッドのチャーンが最小限に抑えられるか、クラスタのサイズが小さく維持されている限り、この数をやや上回ることができます。

  • 名前空間あたりのサービス数は、5,000 を超えないようにする必要があります。5,000 を超えると、サービス環境変数の数が shell の上限を超え、起動時にポッドがクラッシュします。Kubernetes 1.13 からは、PodSpec の enableServiceLinks を false に設定することで、これらの変数の設定をオプトアウトできます。

  • オブジェクトの総数。クラスタ内のすべてのオブジェクトには、組み込みリソースと CRD の両方に上限があります。上限は、サイズ(etcd に保存されているバイト数)、変更の頻度、アクセス パターン(例えば、所定の型に該当するすべてのオブジェクトを頻繁に読み込むと、etcd がはるかに高速に強制終了されます)によって異なります。

次のステップ