大規模クラスタ・ベスト・プラクティス

Kubernetes Engine (OKE)で作成した大規模なクラスタを管理するためのベストプラクティスをご覧ください。

この項では、大規模なクラスタおよびKubernetesエンジンのベスト・プラクティスについて説明します。

ベスト・プラクティス: バースト・スケーリングをクラスタ内のポッドおよびノードの約10%に制限します

ノードとポッドの両方を、合計数の約10%のバッチで大規模なクラスタに追加または削除することをお薦めします。

クラスタ・スケーリング・アクション(ノード・プール内のノード数の変更、デプロイメント内のレプリカ数の構成、クラスタ内のジョブの生成など)では、分散調整およびリソースのスケジューリングのために大量のAPIトラフィックを生成できます。10%の推奨事項は、通常、Kubernetes APIサーバーおよびその他のダウンストリーム・クラウド・エンドポイントでレート制限が発生するのを避けるために十分な保守的であるため、バックオフによる遅延の原因となる可能性のあるトラフィックの多い時間中に、コストのかかる再試行を回避します。

10%の推奨事項は開始点であり、クラスタのサイズとそれに含まれるワークロードのタイプによって異なります。すべてのオペレータがkube-apiserverと通信するワークロードでは、よりバースト・スムージングが必要になる場合がありますが、ワークロードが最小限の空のノードでは、より迅速にバーストできる場合があります。

Kubernetesドキュメントの大規模なクラスタに関する考慮事項を参照してください。

ベスト・プラクティス: ロード中のレート制限の決定を最適化するようにFlowSchemasを構成します

大規模なクラスタでは、時間的に重要ではないリクエストの優先順位を解除することをお薦めします。

kube-apiserverのAPI Priority and Fairness (APF)機能は、レート制限リクエストに対するいくつかの制御を公開します。優先度レベルを使用してAPF機能を構成できます。優先度レベルでは、特定の優先度に割り当てられるハンド・サイズおよびキュー・サイズの柔軟な構成を定義します。優先度レベルを使用すると、高度なワークロードでリクエスト処理を最適化し、優先順位の高いリクエストを処理できます。

FlowSchemaは、リクエストが属する優先度レベルを定義します。多数のポッドまたはノードの追加または削除を必要とするバースティング・ワークロードがあるクラスタで共通の構成は、LIST /eventsリクエストの優先度をcatch-all優先度レベルに減らすFlowSchemaを使用することです。Kubernetesでは、通常、LISTコールはkube-apiserverにとって最も高価であり、解約率が高くなるとイベント数が大きくなる可能性があります。これらのコールの優先度レベルを低くするFlowSchemaをインストールすると、より時間クリティカルなリクエストを処理できます。優先度の低いリクエストはHTTP 429 Too Many Requestsエラーを受信し、後でクライアントによって再試行されて最終的に一貫性が保たれます。

Kubernetesドキュメントの他のフローの飢餓による重要でないリクエストの分離を参照してください。

/metricsのkube-apiserverによって公開されるメトリックを使用して、スロットルが発生しているタイミングと、カスタム・スキーマに適したフローを識別できます。

  • apiserver_flowcontrol_rejected_requests_totalメトリックを使用して、リクエストの処理に失敗し、再試行する必要があるタイミングを確認します。値がゼロ以外になると、スロットルが発生し、アクションを実行できます。
  • apiserver_flowcontrol_request_wait_duration_secondsメトリックを使用して、ボトルネックである優先度レベルを確認します。

KubernetesドキュメントのAPI優先度と公平性を使用するための適切なプラクティスを参照してください。

ベスト・プラクティス: クラスタ・サイズで拡張するためのクラスタ・アドオンのチューニング

大規模なクラスタでCoreDNSおよびflannelアドオンを構成することをお薦めします。

Kubernetes Engineの拡張クラスタを使用すると、クラスタにインストールされているアドオンを構成できます(クラスタ・アドオンの更新を参照)。小さいクラスタで妥当なデフォルトは、大きいクラスタでは必ずしも最適とはかぎりません。

CoreDNSのデフォルト構成では、ノードごとに1つのレプリカが割り当てられます。ただし、大規模なクラスタでは、より適切なレプリカが少なくなる可能性があります。たとえば、大規模なクラスタでは、{minReplica: 3, nodesPerReplica: 8}などの構成がより適切である場合があります。レプリカが少ない構成では、クラスタ内のコンピュート・リソースが少なくなるだけでなく、DNSリクエストをより少ないレプリカに統合することで、効率的なキャッシュ・ヒットの可能性が高くなります。

使用できないノードが1つでも、フランネルDaemonSetへの変更のロールアウトを停止しないようにするには、25%などのmaxUnavailable値を持つようにロールアウト戦略を構成します。このような方法により、多数のノードが使用できない場合でも、何千ものノードを持つ大規模なクラスタへのフランネルDaemonSet変更のロールアウトが可能になります。

CoreDNSアドオンとフランネル・アドオンの両方で、大きいクラスタでは、負荷に対応するために、割り当てられたCPUおよびメモリーのリクエスト/制限を増やす必要がある場合があります。

Configuring Cluster Add-onsを参照してください。

ベスト・プラクティス: JSONではなくprotobufコンテンツ・タイプを使用するようにKubernetesクライアントを構成します

可能な場合は、大きいクラスタでprotobufコンテンツ・タイプを使用することをお薦めします。

デフォルトでは、Kubernetesクライアントは、すべてのリクエストのコンテンツ・タイプとしてJSONを使用します。JSONをコンテンツ・タイプとして使用することはユーザーフレンドリなオプションであり、ほとんどのユースケースで十分です。ただし、大規模なクラスタでは、コンテンツ・タイプとしてJSONではなくprotobufを使用するとパフォーマンスが向上します。

protobufコンテンツ・タイプの使用を指定するには:

  • リクエストの場合は、Content-Type: application/vnd.kubernetes.protobufヘッダーを使用します。
  • レスポンスの場合は、Accept: application/vnd.kubernetes.protobuf, application/jsonヘッダーを使用します。Acceptヘッダーにprotobufjsonの両方を指定することで、オブジェクトに対してprotobuf表現が存在しない場合、Kubernetes APIサーバーはJSONにフォールバックできます。

Kubernetesドキュメントのリソースの代替表現を参照してください。

ベスト・プラクティス: Kubernetesコントロール・プレーン・ログを可視化するためのサービス・ロギングの有効化

大規模なクラスタのサービス・ログを有効にすることをお薦めします。

Kubernetes APIサーバーは、サーバー・レスポンスの警告およびイベントを介してクライアントに多くの問題を報告します。ただし、次のKubernetesコントロール・プレーン・コンテナのログは、大規模なクラスタの動作を理解するのに役立つ追加情報も取得します:

  • キューブ・スケジューラ
  • kube-controller-manager
  • クラウド・コントローラ・マネージャ
  • kube-apiserver

これらのKubernetesコントロール・プレーン・ログをサービス・ログとしてOracle Cloud Infrastructure Loggingで有効化および表示するには、Kubernetesエンジン(OKE)サービス・ログの表示の手順に従います。

ベスト・プラクティス: 予想されるポッド数に十分なIPアドレスを持つネットワークCIDRブロックを割り当てます

大規模なクラスタに対して指定するネットワークCIDRブロックのサイズおよび選択するCNIプラグインを事前に検討することをお薦めします。

実行中のクラスタのサブネットの変更は中断されることがあります。ポッドCIDRブロックの場合、クラスタの作成後にクラスタに最初に指定したポッドCIDRブロックは変更できません。したがって、大規模なクラスタを作成する前に、クラスタ・スケールとしてのネットワークの複雑さを回避するために、どのCNIプラグインを選択するのが最適か、どのCIDRブロック・サイズを指定するのが最適かを慎重に検討してください。

flannel CNIプラグインを使用すると、大規模なプライベート・サブネットの使用を割り当てることができます。ポッドCIDRブロックには/12 CIDRブロックを推奨します。VXLANの性質上、Flannel CNIプラグインはポッドをすばやく割り当て/割り当て解除でき、ポッドトラフィックがVXLANカプセル化内にあるというトレードオフも実現します。ポッドCIDRブロックのサイズを選択する際は、Kubernetes Engineが各ノードに/25 CIDRブロックを割り当てることを考慮してください。指定したポッドCIDRブロックのサイズによって、クラスタで使用可能なノードの数を制限できます(たとえば、ポッドCIDRブロックとして/24 CIDRブロックを指定した場合、クラスタには8つのノードのみを指定できます)。予想されるポッドとノードの比率に応じて、未使用で他のノードで使用できない各ノードに多数のIPアドレスが割り当てられる場合があります。その場合は、より大きなポッドCIDRブロックを指定します(CIDRブロックおよびKubernetesエンジン(OKE)を参照)。

ネイティブ・ポッド・ネットワーキングCNIプラグインは、専用のVNICアタッチメントを使用してVCNネットワーキングと直接統合されます。この方法では、ノードごとのIP割り当てに関する制限がなくなり、クラスタ内の追加のVXLANオーバーレイネットワーク層が不要になります。ただし、VCNサブネットは/16 CIDRブロックに制限されます。これは、チャネルに収容できるよりも小さいアドレス空間です(許可されるVCNサイズおよびアドレス範囲を参照)。また、ネイティブ・ポッド・ネットワーキングCNIプラグインは自己管理ノードをまだサポートしていないため、ネイティブ・ポッド・ネットワーキングCNIプラグインを使用するクラスタには、管理対象ノードまたは仮想ノードのみを含めることができます。ノードにアタッチできるVNICの数はノード・サイズによって制限されるため、ポッドIPアドレスの数を評価する際に各ノードのシェイプの選択を検討してください(コンピュート・シェイプを参照)。

Kubernetes APIエンドポイント・サブネットには通常、小さいCIDRブロックのみが必要です。これは、サブネットを共有するクラスタごとに1つのエンドポイントIPアドレスが必要であるためです。たとえば、Kubernetes APIエンドポイント・サブネットに/29 CIDRブロックを指定すると、6つのクラスタでサブネットを共有できます。一方、/28 CIDRブロックでは、14個のクラスタでサブネットを共有できます。

ベスト・プラクティス: サービス制限の引上げを事前にリクエストします

テナンシに構成されているサービス制限を確認し、事前にリクエストを送信して、大規模なクラスタが到達すると予想されるサービス制限を増やすことをお薦めします。サービス制限を参照してください。

大規模なクラスタは通常、次の制限に達します。

  • コンテナ・イメージ・リポジトリの数およびサイズ。
  • 1つのクラスタで許可されるノード数。
  • 割り当て可能なブロック・ボリュームのギガバイト数。

したがって、中断の可能性を回避するために、特にノードのブート・ボリュームとして使用されるブロック・ボリュームの制限について、サービス制限を増やすリクエストを事前に送信することをお薦めします。

「サービス制限の引上げのリクエスト」を参照してください

ベスト・プラクティス: 自動スケーリングを活用し、ワークロードに応じてコンピュート・リソースを管理

自動スケーリング(Kubernetes Cluster Autoscaler (CA)、Horizontal Pod Autoscaler (HPA)、Vertical Pod Autoscaler (VPA))を大規模なクラスタで使用して、リソース使用率を最適化することをお薦めします。

オートスカラーを使用すると、より多くのノードをプロビジョニングするタイミング、より多くのレプリカを作成するタイミング、または静かな期間にクラスタをスケール・ダウンするタイミングを定義するルールを設定できます。

ルールベースの自動スケーリングは、数千のノードとポッドを含む大規模なクラスタを効率的に管理する方法です。

自動スケーリングのベスト・プラクティスを参照してください。

ベスト・プラクティス: セキュリティ・リストおよびネットワーク・セキュリティ・グループにステートレス・ルールを使用して、接続トラッキングのオーバーヘッドを最小限に抑えます

大規模なクラスタのセキュリティ・リストおよびネットワーク・セキュリティ・グループを構成する場合は、ステートレス・ルールを使用することをお薦めします。

チュートリアルとドキュメントは、多くの場合、ステートフル・ルールを使用してセキュリティ・リストとネットワーク・セキュリティ・グループを作成することを指定します。ステートフル・ルールでは、接続トラッキングを利用して、エグレス・ルールの存在に関係なく、リクエストの戻りパスが自動的に許可されるようにします(接続トラッキングを参照)。リターン・パスを自動的に許可することはルール設定を簡略化することを目的としていますが、これらの自動的に許可されるリターン・パスは、大規模なクラスタの問題になる可能性のある潜在的なオーバーヘッドです。追跡できる接続の数は、使用されるインスタンスのシェイプに比例しますが、大きいシェイプを選択するだけで、必ずしも問題に対処できるわけではありません。

接続追跡のオーバーヘッドを排除し、潜在的なスケーリング制限を回避するために、ネットワーク・パスごとに次のことをお薦めします。

  1. イングレス・ルールおよび対応するエグレス・ルールをペアとして定義します。
  2. イングレスおよびエグレス・ルールを"stateless"として指定します。

ステートフル・ルールとステートレス・ルールを参照してください。