DUICUO

Kubernetes クラスターの容量とリソースを管理する方法

[51CTO.com クイック翻訳] ご存知の通り、システムリソースは無限ではありません。大規模なクラスター・アズ・ア・サービスのシナリオでは、クラスターリソースを慎重に計画し、割り当てる必要があります。しかし、様々なソフトウェアプロジェクトにおいて、開発者は仮想化やコンテナ化によってリソースが巨大なプールのように自由に使えるようになると誤解しがちです。例えば、大量のリソースを必要とするアプリケーションを実行しようとすると、特に自動スケーリングが有効になっているクラスターでは、下図のような状況に遭遇することがあります。

明らかに、`kubectl get` を使用すると、数十個のポッドが削除されたことがわかりますが、実際の目標は 5 個だけを実行することである可能性があります。この時点で、Kubernetes クラスター リソース管理を通じて容量とリソースの割り当てを自動化することが実際に必要になる場合があります。

2つの例

[[341211]]

上の図に示すように、16個の仮想CPUと64GBのRAMを備えたKubernetesクラスターがあるとします。このクラスターで、20GBのメモリを必要とするAIコンテナをスムーズに実行できるでしょうか?

クラスターに 4 つのワーカーがあり、それぞれが 16 GB の使用可能なメモリを必要とすると仮定すると (実際には、DaemonSet とシステム サービスはそれぞれノードを実行して少量のリソースを消費する必要があるため、実際に使用可能なメモリは少なくなる場合があります)、このシナリオでは、コンテナーに 16 GB のメモリのみを割り当てても、スムーズな操作は保証されません。

実際、このような大規模なコンテナのデプロイメントだけでなく、他の複雑なデプロイメントを行う場合や、Helm チャートなどのすぐに使用できる製品を使用する場合でも (https://grapeup.com/blog/asp-net-core-ci-cd-on-azure-pipelines-with-kubernetes-and-helm/ を参照)、リソース制約の問題を常に考慮する必要があります。

もう1つの例、つまり同一クラスタ内にCephをデプロイするケースを見てみましょう。目標は、1TBのストレージを10個のOSD(オブジェクトストレージデーモン)と3個のCeph MON(モニター)に分割することです。このストレージを2つのノードに配置し、残りの2つのノードは、そのストレージを使用するデプロイメント用に残しておきます。これにより、非常にスケーラブルなアーキテクチャが実現します。

一般的なユーザーが最初に行うことは、OSD の数を 10、MON を 3 に設定し、Ceph ポッドに許容値を追加して、テイントをノード 1 とノード 2 に一致させることです。その後、すべての Ceph デプロイメントとポッドは、nodeSelector をノード 1 と 2 のみをターゲットに設定するようになります。

下の図に示すように、Kubernetesは最初のワーカーでmon-1、mon-2、および5つのOSDを実行し、2番目のワーカーでmon-3とさらに5つのOSDを実行します。アプリケーションは大量のデータをCephに迅速に保存できます。

ダッシュボードも展開してレプリケーション プールを作成すると、使用可能な 1 TB のストレージと 10 個の OSD のステータスも視覚的に確認できるようになります。

しかし、しばらく実行してみると、実際に利用可能なストレージ容量は400GBしかなく、多数のOSDポッドが強制退去し、4つのOSDが同時に実行されていることがわかりました。そのため、初期のデプロイメント構成を再検討する必要があります。

制限と範囲

通常、13個のPod(場合によっては3個のモニターを含む)を実行しても、それほど多くのリソースを消費することはありません。しかし、OSDの場合はそうではありません。Cephは大量のデータをメモリにキャッシュするため、使用頻度が高くなるほど多くのリソースが必要になります。同時に、複数のストレージコンテナ間でのデータレプリケーションとバランス調整にもスペースが消費されます。そのため、初期デプロイメント後のメモリ割り当ては次の図のようになります。

数時間連続して実行すると、クラスターは次の特性を示します。

ご覧のとおり、ポッドの約50%が失われています。これは最終状態ではありません。残りのコンテナに高スループットを適用すると、すぐにさらに多くのポッドが失われるでしょう。では、Cephクラスターに32GB以上のメモリを設定する必要があるのでしょうか?いいえ、そうではありません。制限を正しく設定していれば(https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-requests-and-limits-of-pod-and-container を参照)、単一のOSDが他のポッドから利用可能なメモリをすべて奪うことはありません。

つまり、この場合、最も単純な方法は、各 OSD の最大容量を 650 MB として、mon 全体に 2 GB のメモリを割り当てて予約し、合計 30 GB のメモリを 10 個の OSD で分割することです (下の図を参照)。

OSDに15GBのメモリを割り当て、各Podに650MBのメモリを構成したため、最初のノードに必要なメモリ量は15 + 2 * 0.65 = 16.3GBとなります。さらに、同じノードで実行されるDaemonSetログも考慮する必要があります。したがって、正しい値は次のとおりです。

サービス品質

制限に完全に一致する Pod のリクエストも設定した場合、Kubernetes は次の図に示すように、このタイプの Pod を異なる方法で処理します。

この設定により、KubernetesのQoSが保証型(そうでない場合はバースト型)に設定されます。保証型QoSが設定されたPodは、強制的に削除されることはありません。同じリクエストと制限を設定することで、KubernetesによるPodの移動や管理を気にすることなく、Podのリソース使用率を確保できます。これによりスケジューラの柔軟性は低下しますが、デプロイメント全体の耐障害性が向上します。

環境内のリソースを自動的に拡張する

ミッションクリティカルなシステム(https://grapeup.com/ 参照)の場合、クラスタサイズに合わせて必要なリソースを見積もり、適切な制限を設定するだけでは十分ではありません。水平スケーリングを実現し、利用可能なワーカー数を調整するために、より複雑な構成と固定されていないクラスタ容量を使用する必要がある場合もあります。

リソースが線形に拡張される場合、クラスターの最小容量と最大容量を同時に計画できます。しかし、クラスターの拡張に合わせてポッドを水平方向と垂直方向の両方に比例的に拡張できる場合、クラスターが比例的に縮小した際に、他のポッドを「追い出す」可能性があります。この問題を軽減するために、Kubernetes はポッド優先度とポッド停止予算という2つの主要な概念を導入しています。

まず、テストシナリオの作成について説明します。今回は多数のノードは必要ありません。2つのノードグループを持つクラスターを作成するだけです。1つは通常のインスタンス(パーシステントインスタンス)で構成され、もう1つはプリエンプティブ/スポットインスタンスで構成されます。下の図に示すように、VM(既存ノード)のCPU使用率が0.7%(つまり70%)を超えると、プリエンプティブノードグループが拡張されます。

プリエンプティブルインスタンスの利点は、同じパフォーマンスを持つ通常のVMよりもはるかに簡単に実装できることです。唯一の欠点は、寿命が保証されていないことです。つまり、クラウドプロバイダーがメンテナンス目的で他の用途で使用する必要があると判断した場合、または24時間経過した場合、インスタンスは強制的に削除される可能性があります。そのため、プリエンプティブルインスタンスでは、フォールトトレラントでステートレスなワークロードしか実行できません。

では、なぜクラスター内に永続ノードが1つしかないのでしょうか?これは、極端なケースに備えるためです。すべてのプリエンプティブノードが動作していない場合でも、最小限のコンテナセットを維持することで、アプリケーションの運用性を管理・確保します。以下の表は、このようなルーチンの構造を示しています。ノードセレクターを使用して、Redisマスターを永続ノードで実行するように設定できます。

ポッドの優先度

以下では、Horizo​​ntal Pod Autoscaler (HPA) の例を見ていきます。

フロントエンド:

後部:

ビデオコンバーター:

ビデオコンバーターとしての目標は、平均リソース使用率を削減することです。つまり、スケーリング戦略をチェックすることで、複数の変換キューの平均CPU使用率がすぐに25%に達する可能性がある場合、自動的にスケールアップします。例えば、約10分以内に50件のビデオ変換が必要な場合、コンバーターは25インスタンスにスケールアップします。クラスター内の他のコンテナが強制退去されるのを防ぐため、優先度カテゴリを作成できます(https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption を参照)。優先度の高いポッドはスケジューラーにとってより重要な価値を持ち、優先度の低いポッドは強制退去されます。

したがって、コンバーターの優先度を低く設定すると、フロントエンドとバックエンドのPodの重要性が高まります。最悪の場合、ビデオコンバーターがクラスターから排除される可能性があります。

ポッド混乱予算

ポッドの制御とスケジューリングのためのより優れた方法として、ポッド停止予算(PDB)があります。これにより、一度に最小数のポッドを設定できます。これは、ノードリソースの枯渇を効果的に防ぐため、ポッド優先度のみを使用する場合よりも厳格です。他のワーカーにポッドの再スケジュールに必要なスペースが不足している場合でも、レプリカ数が割り当て可能な予約数を下回らないことを保証します。

上記の表は最も基本的な構成を示しています。フロントエンドのレプリカ数は2以上です。これを基に、すべてのポッドに最小値を割り当て、リクエストを処理できるポッドが常に少なくとも1~2個確保されるようにすることができます。

これは、ポッドの自動スケーリングとクラスターのスケーラビリティを確保するための最もシンプルかつ安全な方法です。最小限のコンテナセットを設定し、割り込みを事前に設定すれば、全体的な安定性に影響を与えることなく、クラスターの最小キャパシティと様々なリクエストに対する最小処理要件を満たすことができます。

この時点で、安定したソリューションを構築するために必要なコンポーネントがすべて揃っています。スケジューラの作業を簡素化するために、HPAのレプリカの最小数をPDBと同じ数に設定できます。同時に、制限数とリクエスト数が一致するだけでなく、最大クラスターサイズに基づいてポッドが排除されないようにする必要があります。具体的な構成は以下の表のとおりです。

スケジューラの柔軟性に基づいて、フロントエンドとバックエンドの負荷が低すぎるが、変換する必要があるデータの量が多い場合、コンバーターは自動的に 19 ~ 21 のインスタンスに拡張されます。

自動拡張に関する注意事項

自動拡張に関しては、次の 2 つの点に注意する必要があります。

まず、クラウド サービス プロバイダーからの仮想マシンの起動時間を特定できないため (数秒の場合もあれば、数分かかる場合もあります)、自動スケーリングによってピーク負荷の問題が確実に解決されるとは保証できません。

次に、クラスターをスケールダウンする場合、実行中のコンポーネントについては、アプリケーションの操作を中断せずに仮想マシンを効果的にシャットダウンできるように、スケジューラが負荷を他のワーカーにすばやく移動できるように、繰り返しテストを実施する必要があります。

原題: Kubernetes Cluster Management: Size and Resources、著者: Adam Kozlowski

[この記事は51CTOによって翻訳されました。提携サイトへの転載の際は、元の翻訳者と出典を51CTO.comとして明記してください。]