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

このドキュメントでは、既知の Kubernetes の制限に近づいている際のワークロードに対応できる Google Kubernetes Engine(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 ネットワークにはすべての Pod IP アドレスのセカンダリ範囲があります。その後、各ノードに特定の Pod IP アドレス用のセカンダリ範囲のスライスが割り当てられます。これにより、VPC ネットワークは、カスタムルートに依存せずに Pod にトラフィックをルーティングする方法をネイティブに理解できます。1 つの VPC ネットワークには最大 15,000 個の VM を持つことができます。この上限の結果の詳細については、VPC ネットワークあたりの VM の上限をご覧ください。

限定公開クラスタ

通常の GKE クラスタでは、すべてのノードにパブリック IP アドレスが指定されます。限定公開クラスタでは、ノードはインターネットへの送受信接続からノードを分離するための内部 IP アドレスのみが付与されます。GKE は VPC ネットワーク ピアリングを使用して、Kubernetes API サーバーを実行している VM をクラスタの残りの部分と接続します。これにより、トラフィックは公共のインターネット経由でルーティングされないため、GKE コントロール プレーンとノード間のスループットが向上します。

限定公開クラスタを使用すると、ノードがインターネットに公開されないというセキュリティ上のメリットがあります。

クラスタの負荷分散

Compute Engine の GKE Ingress と Cloud Load Balancing は、ロードバランサを構成してデプロイし、Kubernetes ワークロードをクラスタの外部と公共のインターネットに公開します。GKE Ingress と Service コントローラは、GKE ワークロードに代わり、転送ルール、URL マップ、バックエンド サービス、ネットワーク エンドポイント グループなどのオブジェクトをデプロイします。それぞれのリソースには割り当てと上限があり、これらの上限は GKE にも適用されます。特定の Cloud Load Balancing リソースが割り当て量に達すると、特定の Ingress または Service が正しくデプロイされず、リソースのイベントにエラーが表示されます。

GKE Ingress と Service を使用する場合は、次の推奨事項とスケール制限に留意してください。

  • Ingress(外部と内部): GKE を通じて公開される Service。GKE Ingress で公開される Service では、NEG を使用したコンテナ ネイティブ負荷分散を使用することをおすすめします。
  • NEG を使用しない Ingress リソースは、最大 1,000 ノードまでのクラスタでサポートされます。NEG の Ingress にクラスタノードの上限はありません。
  • 内部ロードバランサ サービス: TCP / UDP 内部ロードバランサをデプロイする Service は、最大 250 ノードまでのクラスタでサポートされます。

この上限を増やす場合は、Google Cloud のセールスチームまでお問い合わせください。内部 HTTP(S) 負荷分散の Ingress には、クラスタ単位のノード上限がありません。内部 TCP / UDP ロードバランサの代わりに、内部 HTTP トラフィックの処理に使用できます。

DNS

GKE のサービス ディスカバリは kube-dns によって提供されます。これは、クラスタ内で実行される Pod に DNS 解決を提供する一元化されたリソースです。非常に大規模なクラスタや、リクエストの負荷が高いワークロードの場合、これはボトルネックになる可能性があります。GKE は、クラスタのサイズに基づいて kube-dn を自動的にスケーリングし、容量を増やします。まだ十分な容量でない場合、GKE は、NodeLocal DNSCache が設定された各ノードに DNS クエリの解決処理を分散します。この場合、各 GKE ノードに用意されたローカルの DNS キャッシュでクエリが処理されます。これにより、負荷が分散され、応答時間が短縮されます。

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 機能を使用すると、ノードごとに Pod の CIDR ブロックサイズを構成し、使用する IP アドレスを減らすことができます。

RFC 1918 のプライベート空間より多くの IP アドレスが必要な場合は、RFC 1918 以外のアドレスを使用することをおすすめします。

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

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

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

下りトラフィック

Google Cloud では、インスタンスに割り当てられるマシンタイプとコアの数によってネットワーク容量が決まります。下り(外向き)の最大帯域幅は 1~32 Gbps とさまざまですが、デフォルトの e2-medium-2 マシンの最大下り帯域幅は 2 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 です。

スケーラビリティに関連する上限と割り当て

VPC ネットワークあたりの VM 数の上限

1 つの VPC ネットワークは、最大 15,000 ノードの VM 接続に対応できます。これは、GKE 1.17 以前のバージョンでクラスタあたり 5,000 ノードの上限を超える数です。GKE 1.18 以降では、最大 15,000 ノードをサポートできます。VPC ネイティブ クラスタでは、アドレスを少し GKE コントロール プレーン用に予約する必要があるため、ほぼ 15,000 ノードになります。

ネットワーク ピアリングを構成している場合、ピアリングされるネットワークには、デフォルトで 15,000 VM の上限が適用されます。

Compute Engine API の割り当て

GKE コントロール プレーンは Compute Engine API を使用して、クラスタ内のノードのメタデータを検出するか、永続ディスクを VM インスタンスにアタッチします。

デフォルトでは、Compute Engine API は 100 秒あたり 2,000 件の読み取りリクエストを許可します。この数は、100 ノードを超えるクラスタには十分ではありません。

100 ノードを超えるクラスタを作成する場合は、Read requests per 100 secondsRead requests per 100 seconds per user の割り当てを 4, 000 以上に増やすことをおすすめします。これらの設定は、Google Cloud Console から変更できます。

ロギングとモニタリングの割り当て

Cloud Logging API の割り当て(デフォルトでは 1 分あたり 60,000 ログの挿入リクエスト)と Cloud Monitoring API(デフォルトでは 1 分あたり 6,000 時系列の挿入リクエスト)の割り当ては、クラスタの拡大に合わせて増加させる必要が生じる場合があります。

ノードの割り当て

GKE 1.18 以降ではノード数が 5,000 に制限されており、必要に応じて 15,000 に増やすことができます。詳細については、5, 000 ノードを超えるクラスタをご覧ください。

上限について

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

GKE バージョン 1.17 以前では、1 つのクラスタで最大 5,000 ノードをサポートします。GKE 1.18 以降では、最大 15,000 ノードがサポートされます。ただし、Kubernetes は大規模な機能面を備える複雑なシステムです。ノード数はあくまで Kubernetes がスケーリングできる多くのディメンションの 1 つです。その他のディメンションには、Pod の総数、Service の総数、Service の背後で実行されるバックエンドの総数などがあります。大規模なクラスタの作成に関連する考慮事項については、5, 000 ノードを超えるクラスタをご覧ください。

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

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

ディメンションの上限

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

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

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

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

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

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

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

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

5,000 ノードを超えるクラスタ

リリース 1.18 以降、GKE は、単一のクラスタで最大 15,000 ノードをサポートします。ただし、上述のすべての上限(特に etcd の制限によって生じるオブジェクト数の上限)が引き続き存在します。このため、5,000 ノードにデプロイされたワークロードの中には、15,000 ノードまでスケールアップされるものが生じる可能性があります。

また、5,000 ノードを超えるクラスタは、リージョン限定公開の両方となる必要があります。

したがって、5,000 ノードを超えるクラスタを作成する場合は、まずサポート チケットを作成して、5,000 ノードを超える割り当ての引き上げをリクエストする必要があります。次に、Google においてワークロードの詳細について検討を行い、必要に応じて、スケーラビリティ向上のためにワークロードをどのように変更するかについて提案します。この作業の一環として、Google では、その他の関連する割り当てを適切に引き上げるサポートも行います。

自動マウントのデフォルトのサービス アカウントを無効にする

Pod を作成すると、自動的にデフォルトのサービス アカウントが設定されます。デフォルトのサービス アカウントを使用して、自動的にマウントされたサービス アカウントの認証情報により Pod 内から Kubernetes API にアクセスできます。

マウントされた各 Secret ごとに、kube-apiserver のその Secret に対する変更が kubelet によって監視されます。大規模なクラスタの場合、監視が数千個にも上ることになり、kube-apiserver に過大な負荷がかかる可能性が生じます。Pod から Kubernetes API にアクセスしない場合は、デフォルトのサービス アカウントを無効にする必要があります。

次のステップ