クラウドネイティブにおける OOM と CPU スロットリングの詳細な分析

I.はじめに

  • Kubernetes を使用する場合、メモリ不足 (OOM) エラーと CPU スロットルがクラウド アプリケーションでのリソース処理の大きな問題点となります。クラウド アプリケーションにおける CPU とメモリの要件は、クラウドのコストに直接関係しているため、ますます重要になっています。
  • 制限とリクエストを使用すると、ポッドがメモリと CPU リソースを割り当てる方法を構成して、リソースの枯渇を防ぎ、クラウド コストを調整できます。
    • ノードに十分なリソースがない場合、プリエンプションまたはノード プレッシャーによってポッドが駆動される可能性があります。プロセスがメモリ不足 (OOM) になると、必要なリソースがないためプロセスは終了します。
    • CPU 消費量が実際の制限よりも高い場合、プロセスはスロットルを開始しますが、Kubernetes ポッドが OOM と CPU スロットルにどれだけ近づいているかを事前に監視するにはどうすればよいでしょうか?

二、Kubernetes OOM

  • ポッド内の各コンテナの実行にはメモリが必要です。
  • Kubernetes の制限は、ポッド定義またはデプロイ定義でコンテナーごとに設定されます。
  • 最新の Unix システムはすべて、メモリを再利用する必要がある場合にプロセスを強制終了する方法を備えており、これはエラー 137 または OOMKilled としてマークされます。
State:          Running
      Started:      Thu, 10 Oct 2019 11:14:13 +0200
    Last State:     Terminated
      Reason:       OOMKilled
      Exit Code:    137
      Started:      Thu, 10 Oct 2019 11:04:03 +0200
      Finished:     Thu, 10 Oct 2019 11:14:11 +0200
  • この終了コード 137 は、プロセスが許容量を超えるメモリを使用しているため、プロセスを終了する必要があることを示します。これは Linux に存在する機能で、カーネル oom_score がシステム内で実行中のプロセスの値を設定します。さらに、サービス品質を確保するために Kubernetes によって使用される oom_score_adj と呼ばれる値を設定できます。また、プロセスを監査し、使用を許可されている以上のメモリを使用しているプロセスを強制終了する OOM Killer 機能もあります。
  • Kubernetes では、プロセスが次のいずれかの制限に達する可能性があることに注意してください。
    • コンテナーに設定された Kubernetes 制限。
    • 名前空間に設定された Kubernetes ResourceQuota。
    • ノードの実際のメモリ サイズ。

ここに画像の説明を挿入します

3. メモリの過剰使用

  • 制限はリクエストよりも大きくなる可能性があるため、すべての制限の合計がノードの容量よりも大きくなる可能性があり、これはオーバーコミットメントと呼ばれ、一般的に行われます。実際、すべてのコンテナーが要求された以上のメモリを使用すると、ノード内のメモリが不足する可能性があり、通常はメモリを解放するために一部のポッドが強制終了されます。

① Kubernetes OOM を監視する

  • Prometheus でノード エクスポータを使用する場合、node_vmstat_oom_kill と呼ばれるメトリクスがあり、OOM キルがいつ発生するかを追跡することが重要ですが、そのようなイベントが発生する前に事前に認識しておくことが必要になる場合があります。
  • 代わりに、プロセスが Kubernetes の制限にどの程度近づいているかを確認できます。
(sum by (namespace,pod,container)
(rate(container_cpu_usage_seconds_total{
    
    container!=""}[5m])) / sum by
(namespace,pod,container)
(kube_pod_container_resource_limits{
    
    resource="cpu"})) > 0.8

②KubernetesのCPUスロットリング

  • CPU スロットリングは、特定のリソース制限に達しそうになったときにプロセスの速度を低下させる動作です。
  • メモリの状況と同様に、これらの制限は次のようになります。
    • コンテナーに設定された Kubernetes 制限。
    • 名前空間に設定された Kubernetes ResourceQuota。
    • ノードの実際の CPU サイズ。
  • 次のたとえを考えてください。交通量の多い高速道路があるとします。
    • CPUがその方法です。
    • 車両はプロセスを表し、各車両のサイズは異なります。
    • 複数のチャネルは複数のコアを表します。
  • 要望としては、自転車専用道路などの専用道路の整備が挙げられます。ここでのスロットルは交通渋滞として現れ、最終的にはすべてのプロセスが実行されますが、すべてが遅くなります。

ここに画像の説明を挿入します

③KubernetesのCPU処理

  • CPU は、Kubernetes のシェアを使用して処理されます。各 CPU コアは 1024 のシェアに分割され、Linux カーネルの cgroups (コントロール グループ) 機能を使用して、実行中のすべてのプロセスに分散されます。

ここに画像の説明を挿入します

  • 現在のプロセスはすべて処理でき、アクションは必要ありません。プロセスが CPU を 100% を超えて使用する場合、共有が設定されます。他の Linux カーネルと同様に、Kubernetes は CFS (Completely Fair Scheduler) メカニズムを使用するため、共有数が多いプロセスほど多くの CPU 時間を取得できます。
  • メモリとは異なり、Kubernetes はスロットルによってポッドを強制終了しません。

ここに画像の説明を挿入します

  • CPU 統計は /sys/fs/cgroup/cpu/cpu.stat で表示できます。

4. CPUの過剰使用

  • プロセスのリソース消費を制限したい場合、制限またはリクエストを設定することが重要です。ただし、リクエストの合計数を実際の CPU サイズより大きく設定しないように注意してください。これは、各コンテナーに特定の数の CPU が必要であることを意味します。
  • Kubernetes の CPU スロットリングを監視すると、プロセスが Kubernetes の制限にどの程度近づいているかを確認できます。
(sum by (namespace,pod,container)(rate(container_cpu_usage_seconds_total
{
    
    container!=""}[5m])) / sum by (namespace,pod,container)
(kube_pod_container_resource_limits{
    
    resource="cpu"})) > 0.8
  • クラスター内で発生するスロットルの量を追跡する場合、cadvisor は、すべての CPU サイクルのスロットルの割合を簡単に計算できるcontainer_cpu_cfs_throttled_periods_total およびcontainer_cpu_cfs_periods_total を提供します。

5. ベストプラクティス

①制限やお願いに注意

  • スロットルはノードに最大リソース制限を設定する方法ですが、プロセスがスロットルされたり終了したりする状況が発生する可能性があるため、これらの制限は注意して扱う必要があります。

② 立ち退きの準備をしておく

  • リクエストを非常に低く設定すると、プロセスに最小限の CPU またはメモリが与えられると考えるかもしれません。ただし、kubelet は、最初に要求されたよりも使用率が高いポッドを削除するため、最初に強制終了されるポッドとしてマークされます。
  • 特定の Pod をプリエンプションから保護する必要がある場合 (kube-scheduler が新しい Pod を割り当てる必要がある場合)、最も重要なプロセスに優先順位を割り当てます。

③ スロットルは沈黙の敵

  • 非現実的な制限を設定したり、過度に使用したりすると、プロセスが調整されていることに気づかず、パフォーマンスが低下する可能性があります。 CPU 使用率をプロアクティブに監視し、コンテナーと名前空間内の実際の制限を把握します。

おすすめ

転載: blog.csdn.net/Forever_wj/article/details/134974547