ブログ

Kubernetes OOMおよびCPUスロットルのトラブルシューティング方法

Google Cloudとコンテナの継続的なセキュリティ

本文の内容は、2020年1月30日にSysdigのCarlos Arillaが投稿したブログ(https://sysdig.com/blog/troubleshoot-kubernetes-oom/)を元に日本語に翻訳・再構成した内容となっております。

KubernetesのOOMによるキルは非常にイライラする体験です。ノードに十分なCPUがある場合に、なぜアプリケーションが踠いているような状況になるのでしょうか?

Kubernetesポッドリソースの管理は困難な場合があります。 Kubernetesのリミットとリクエストの設定が正しくないために、多くの問題が発生する可能性があります。

この記事では、リソースの使用に関連する最も一般的な問題の本質に触れていきます。

Kubernetes OOM の問題

Unixベースのシステムのメモリが不足すると、OOMセーフガードが起動し、レベル12のダークシステム管理者(カオスニュートラル)のみがアクセスできる不明瞭なルールに基づいて特定のプロセスを強制終了します。Kubernetes OOM管理は、システムが独自にトリガーの背後で実行されるのを回避しようとします。ノードのメモリが少なくなると、Kubernetes evictionポリシーがゲームに入り、ポッドをFailとして停止させます。 これらのポッドがReplicaSetで管理されている場合、これらのポッドは別のノードでスケジュールされます。 これにより、メモリが解放され、メモリの負荷が軽減されます。

コンテナリミット到達によるOOM kill

これは、ポッドで発生する可能性のある最も単純なメモリエラーです。メモリリミットを設定すると、1つのコンテナが許可されているよりも多くのメモリを割り当てようとし、エラーが発生します。これは通常、コンテナが死に、1つのポッドが不健全になり、Kubernetesがそのポッドを再起動することになります。

test          frontend        0/1     Terminating         0          9m21s

ポッドのDescribeの出力は次のように表示されます。

   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
...


Events:
  Type    Reason          Age                    From                                                  Message
  ----    ------          ----                   ----                                                  -------
  Normal  Scheduled       6m39s                  default-scheduler                                     Successfully assigned test/frontend to gke-lab-kube-gke-default-pool-02126501-7nqc
  Normal  SandboxChanged  2m57s                  kubelet, gke-lab-kube-gke-default-pool-02126501-7nqc  Pod sandbox changed, it will be killed and re-created.
  Normal  Killing         2m56s                  kubelet, gke-lab-kube-gke-default-pool-02126501-7nqc  Killing container with id docker://db:Need to kill Pod 

Exit code137は、リミットより多くのメモリを使用しようとしたためにシステムがコンテナを終了したことを意味するため、重要です。

これをモニタチングするには、常にメモリの使用量をリミットと比較する必要があります。ポッドで使用されるノードメモリの割合は、メモリ使用量がリミットにどれだけ近いかを示すものではないため、通常は良くない指標です。Kubernetesでは、ポッドではなくコンテナにリミットが適用されるため、コンテナのメモリ使用量とそのコンテナのリミットをモニタリングします。

x01.png

Sysdig Monitorのダッシュボードにメトリクスがあります:Hosts & containers → Container limits

リミットオーバーコミットによるKubernetes OOM kill

リクエストされたメモリはコンテナに付与されるため、コンテナは常にそのメモリを使用できますよね? まあ、それは複雑です。Kubernetesは、ノードで利用可能なメモリよりも多くのメモリをリクエストするポッドを割り当てません。 ただし、リミットはリクエストよりも高くなる可能性があるため、すべてのリミットの合計がノードの容量よりも大きくなる可能性があります。これはオーバーコミットと呼ばれ、とても一般的です。実際には、すべてのコンテナがリクエストよりも多くのメモリを使用すると、ノード内のメモリを使い果たす可能性があります。これにより、通常、一部のポッドが死んでメモリが解放されます。

x02.png

Kubernetesのメモリ管理は、多くの側面があるため複雑です。 多くのパラメータが同時に方程式に入ります:

  • コンテナのメモリリクエスト
  • コンテナのメモリリミット
  • これらの設定の欠如
  • システムの空きメモリ。
  • さまざまなコンテナで使用されるメモリ

これらのパラメーター、ブレンダー、およびいくつかの数学を使用して、Kubernetesはスコアを綿密に作成します。テーブルの最後は、Killされるかevictedされます。ポッドはポリシーに応じて再起動できるため、ポッドが完全に削除されるわけではありません。

このメカニズムにも関わらず、Kubernetesのメモリ管理は数秒ごとにしか実行されないため、システムのOOMを強制終了できます。 システムメモリがすぐにいっぱいになると、システムはKubernetes制御プロセスを強制終了し、ノードを不安定にする可能性があります。

x03.png

このシナリオは、おそらく複雑なトラブルシューティングを必要とし、仮説とノードの再起動に基づいたRCAで終了するため、避ける必要があります。

日常の運用では、これは、リソースのオーバーコミットの場合においてリミットのないポッドがKillされる可能性が高く、リクエストされたよりも多くのリソースを使用するコンテナが死ぬ可能性があり、コンテナが保証される可能性が高いことを意味します。

CPUリミットによるCPUスロットリング

KubernetesでのCPUおよびメモリのリクエストとリミットの処理方法には多くの違いがあります。リミットよりも多くのメモリを使用するコンテナはおそらく死にますが、CPUを使用することでKubernetesがコンテナを強制終了することはありません。CPU管理はシステムスケジューラに委任され、リクエストとリミットの適用に2つの異なるメカニズムを使用します。

CPUリクエストは、シェアシステムを使用して管理されます。これは、CPUのリソースがシェアの値に応じて優先されることを意味します。各CPUコアは1,024のシェアに分割され、より多くのシェアを持つリソースにはより多くのCPU時間が予約されています。注意してください、CPUが枯渇した瞬間には、シェアは、アプリに十分なリソースがあることを保証しません。ボトルネックや一般的な崩壊の影響を受ける可能性があるためです。

x04.png

ヒント:コンテナーが100mをリクエストする場合、コンテナーには102のシェアがあります。 これらの値は、ポッドの割り当てにのみ使用されます。 ポッド内のシェアをモニタリングしても、CPUスロットリングに関連する問題はわかりません。

一方、リミットの扱いは異なります。 リミットは、CPUクォータシステムで管理されます。これは、CPU時間を100ミリ秒の期間に分割し、ノードの合計CPUにリミットが表すのと同じ割合でコンテナにリミットを割り当てることで機能します。

x05.png

ヒント:100mのリミットを設定すると、プロセスは各処理期間の10msを使用できます。システムは、クォータよりも多くの時間を使用しようとするとプロセスを調整し、パフォーマンスの問題を引き起こす可能性があります。ポッドは、クォータよりも多くのCPUを使用しようとしたために終了または排除されることはありません。システムはCPUを制限するだけです。

x06.png

ポッドがCPUスロットリングの影響を受けているかどうかを知りたい場合は、割り当てられている割り当てのうち、使用されている割合を調べる必要があります。次のグラフに示すように、CPU使用率は信頼できない場合があります。ポッドのCPU使用率は約25%ですが、割り当てられているクォータであるため、100%を使用しているため、CPUスロットルが発生しています。

x07.png

Sysdig Monitorのダッシュボードにメトリクスがあります:Hosts & containers → Container limits

x08.png

Sysdig Monitorのダッシュボードにメトリクスがあります:Hosts & containers → Container limits

CPUとメモリのクォータ管理には大きな違いがあります。メモリに関しては、リクエストとリミットのないポッドはバースト可能と見なされ、OOM killする最初のリストとなります。CPUの場合は、これは当てはまりません。 CPUリミットのないポッドは、ノード内のすべてのCPUリソースを自由に使用できます。実は、CPUが使用されているのですが、リソースを使用しているプロセスを制御できない場合、主要なプロセスのCPU不足により多くの問題が発生する可能性があります。

学んだ教訓

ワークロードのリソース使用量をモニタリングする方法を知ることは非常に重要です。これにより、クラスターで実行されているアプリケーションの状態に影響を与える可能性のあるさまざまな問題を発見できます。

リソースの使用量がアプリケーションを危険にさらし、クラスター内の他のアプリケーションに影響を与える可能性があることを理解することが、最初の重要なステップです。クォータを適切に構成する必要があります。リソースをモニタリングし、それらがリミットやリクエストにどのように関係しているかをモニタリングすることで、適切な値を設定し、Kubernetes OOM killを回避できます。これにより、クラスター内のすべてのアプリケーションのパフォーマンスが向上し、リソースが公平に共有されます。

sysdigモニターのような優れたモニタリングシステムは、ポッドevictionやペンディングのポッドを確実に回避するのに役立ちます。

Sysdigに関するお問い合わせはこちらから

最近の投稿

カテゴリー

アーカイブ

ご質問・お問い合わせはこちら

top