ブログ

例を交えてKubernetesのリミットとリクエストを理解する

例を交えてKubernetesのリミットとリクエストを理解する

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

Kubernetesの制限とリクエストをどのように設定するかは、アプリケーションとクラスターのパフォーマンスを最適化するために不可欠です。

Kubernetesなど、アプリケーション間でリソースを共有するように設計されたすべての分散システムの課題の1つは、逆説的に、リソースを適切に共有する方法です。アプリケーションは通常、マシン上でスタンドアロンとして実行し、手元のすべてのリソースを使用するように設計されていいます。良いフェンスは良い隣人を作ると言われています。新しいランドスケープでは、同じスペースを他のユーザーと共有する必要があるため、リソースクォータがハード要件になります。

Namespace クォータ

Kubernetesを使用すると、管理者はリソース使用量のハードリミットとして、ネームスペースでクォータを設定できます。これには追加の効果があります。 ネームスペースにCPUリクエストクォータを設定する場合、すべてのポッドは定義でCPUリクエストを設定する必要があります。設定しないと、スケジュールがなされません。

例を見ていきましょう。

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-example
spec:
  hard:
    requests.cpu: 2
    requests.memory: 2Gi
    limits.cpu: 3
    limits.memory: 4Gi 

このファイルをネームスペースに適用する場合、次の要件を設定します。

  • すべてのポッドコンテナは、CPUとメモリのリクエストとリミットを宣言する必要があります。
  • すべてのCPUリクエストの合計が2コアを超えることはできません。
  • すべてのCPU制限の合計が3コアを超えることはできません。
  • すべてのメモリリクエストの合計が2 GiBを超えることはできません。
  • すべてのメモリリミットの合計が4 GiBを超えることはできません。

ポッドで割り当てられた1.9コアが既にあり、200mのCPU要求で新しいポッドを割り当てようとすると、ポッドはスケジュールされず、ペンディングの状態となります。

ポッドリクエストとリミットの説明

以下のデプロイメントの例で考えてみましょう。

kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: redis
labels:
   name: redis-deployment
   app: example-voting-app
spec:
replicas: 1
selector:
   matchLabels:
    name: redis
    role: redisdb
    app: example-voting-app
template:
   spec:
     containers:
       - name: redis
         image: redis:5.0.3-alpine
         resources:
           limits:
             memory: 600Mi
             cpu: 1
           requests:
             memory: 300Mi
             cpu: 500m
       - name: busybox
         image: busybox:1.28
         resources:
           limits:
             memory: 200Mi
             cpu: 300m
           requests:
             memory: 100Mi
             cpu: 100m 

たとえば、4つのコアと16GBのRAMノードでクラスターを実行しているとします。 多くの情報を抽出できます。

u01.png
  1. ポッドの有効な要求は、400 MiBのメモリと600ミリコアのCPUです。ポッドをスケジュールするには、十分な空き割り振り可能スペースを備えたノードが必要です。
  2. redisコンテナのCPUシェアは512で、busyboxコンテナのCPUシェアは102です。 Kubernetesは常にすべてのコアに1024のシェアを割り当てます。 redis:1024 / 0.5コア≅512 busybox:1024 / 0.1コア≅102
  3. Redisコンテナーは、600MBを超えるRAMを割り当てようとするとOOMで強制終了され、ポッドがフェイルする可能性が高くなります。
  4. Redisは、100ミリ秒ごとに100ミリ秒以上のCPUを使用しようとするとCPUスロットルの影響を受けます(コアが4つあるため、利用可能な時間は100ミリ秒ごとに400ミリ秒になります)。
  5. Busyboxコンテナーは、200MBを超えるRAMを割り当てようとするとOOMで終了し、ポッドがフェイルします。
  6. Busyboxは、100ミリ秒ごとに30ミリ秒以上のCPUを使用しようとすると、CPUスロットルの影響を受け、パフォーマンスが低下します。

問題を検出するには、以下をモニタリングする必要があります。

ノードのCPUとメモリの使用量。ノードのメモリがいっぱいになると、すべてのコンテナが制限内にあるにもかかわらず、メモリのプレッシャーによりOOMで強制終了されます。CPUのプレッシャーはプロセスを抑制し、パフォーマンスに影響します。

u02.png

Sysdig MonitorのダッシュボードにKubernetes → Resource usage → Kubernetes node healthにメトリクスがあります。

u03.png

Sysdig MonitorのダッシュボードにKubernetes → Resource usage → Kubernetes node healthにメトリクスがあります。

ノードのディスク容量。ノードがディスクを使い果たすと、Podevictionでディスクスペースを解放する可能性があります。

u04.png

Sysdig MonitorのダッシュボードにKubernetes → Resource usage → Kubernetes node healthにメトリクスがあります。

CPUクォータのパーセンテージは、コンテナ毎として使われます。ポッドのCPU使用率をモニタリングすると、誤認識となる場合があります。Kubernetesのリミットは、ポッドごとではなく、コンテナーごとに制限されることに注意してください。使用されるCPUシェアなどのその他のCPUメトリクスは、割り当てにのみ有効であるため、パフォーマンスの問題がある場合に時間を無駄にしないでください。

u05.png

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

コンテナごとのメモリ使用量。この値を同じグラフのリミットに関連付けるか、使用されているメモリリミットの割合を分析を利用できます。ポッドのメモリ使用量を使用しないでください。この例のポッドは300MiBのRAMを使用でき、ポッドの有効制限(400MiB)を大幅に下回りますが、redisコンテナーが100MiBを使用し、busyboxコンテナーが200MiBを使用している場合、ポッドはフェイルします。

u06.png

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

クラスターおよびノードにおけるリソース割り当ての割合。これは、使用可能なリソース全体から割り当てられたリソースの割合として表すことができます。適切な警告のしきい値は(n-1)/n*100です。ここでの、nはノードの数です。このしきい値を超えると、ノードに障害が発生した場合、残りのノードでワークロードを再割り当てできなくなります。

u07.png

Sysdig MonitorのOverview機能 → clustersにメトリクスがあります。

オーバーコミットリミット(メモリおよびCPU)。これを明確に確認する最善の方法は、割り当て可能なリソース全体のリミットが表す割合です。通常のオペレーションでは、これは100%を超える可能性があります。

u08.png

CPU使用量、キャパシティ、リミット、リクエストを示すカスタムグラフ。

実用的なリクエストとリミットの選択

Kubernetesの使用経験がある場合は、通常、リクエストとリミットを適切に設定することがアプリケーションとクラスターのパフォーマンスにとって最も重要であることを(難しい方法で)理解されているでしょう。

理想的な世界では、ポッドは、リクエストしたリソースの正確な量を継続的に使用する必要があります。しかし、現実の世界は寒くて気まぐれな場所であり、リソースの使用は定期的または予測可能ではありません。良い状況として、リクエスト値の上下に25%のマージンを考慮してください。 使用量がリクエストよりもはるかに少ない場合、お金を無駄にしています。 それよりも高い場合、ノードにおけるパフォーマンス問題となるリスクとなります。

u09.png

リミットに関して良い設定を達成することは、試行錯誤が必要となるでしょう。アプリケーションの性質、需要モデル、エラーへの耐性、その他多くの要因にほとんど依存しないため、誰にとっても最適な値はありません。

u10.png

考慮すべきもう1つのことは、ノードで許可するリミットのオーバーコミットです。

u11.png

Kubernetesでは許可するオーバーコミットの量を通知する自動のメカニズムがないため、これらのリミットはユーザーが適切に使用する必要があります。

まとめ

このことから学ぶべき教訓は次のとおりです。

  • 大切なデベロッパーの方々、自身のワークロードにリクエストとリミットを設定してください。
  • 皆から親愛されるクラスター管理者の方、ネームスペースクォータを設定すると、ネームスペース内のすべてのワークロードがすべてのコンテナーでリクエストとリミットを持つようになります。

リソースを適切に共有するには、クォータが必要です。共有サービスをリミットなしで使用できると誰かが言った場合、それらは嘘をついているか、システムが最終的に崩壊します。

Sysdig Monitorのような優れたモニタリングシステムは、クォータが適切に構成されていることを確認するのに役立ちます。 試されたい方は、https://sysdig.jp/ 内の無料お試しをクリックすると14日間のトライアルライセンスが発行されます。

Sysdig Secureも試されたい方は、http://www.scsk.jp/sp/sysdig/index.htmlからお問い合わせいただければと存じます。

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

top