今やKubernetesはコンテナオーケストレーションのデファクトスタンダートになっています。うまくインフラを抽象化しているため、開発者は必要なリソースを確保して可用性の高いコンテナアプリケーションを簡単にデプロイできるようになりました。しかし、これは運用管理者の立場に立ってみるとあまり嬉しいことではないかもしれません。あまりに簡単にデプロイできてしまうため、クラスターのキャパシティを枯渇する可能性が高まります。規模が小さいうちはコミュニケーションでカバーすることが可能ですが、サービスが拡大して規模も大きくなってくると、オンデマンドな手順ではすぐに限界を迎えます。規模が拡大しても良いように、運用管理者はしっかりとキャパシティマネジメントを行う必要があります。本ポストでは、Requests / LimitsによるPodスケジューリングの概念を理解した上で、Limit Rangesを使ってKubernetesクラスターノードのキャパシティ管理を確実に行うためTipsを紹介します。

Podスケジューリングの基本

Podが実際に配置されるのはノード上です。つまり、Podを配置するためにはどこかのノードのリソースが空いている必要があります。仮にクラスター全体としてリソースに空きがあったとしても、ノード単体で空きがなければどこにもPodを配置できません。Kubernetesでは、スケジューラーが各ノードに配置しているPodのRequestsの状況をみてPodを配置して良いかどうかを判断しています。

RequestsとLimitsとは?

Podは、起動するとその負荷に応じてノード側のCPUやメモリを使えるだけ使おうとします。そのため、ノード内で複数のPodが動いている場合、リソースの奪い合いが起きてしまいます。Kubernetesでは、Podが利用できるリソース量を指定し、必要以上にノード側に負荷をかけないようにする仕組みがあります。それがRequestsとLimitsです。

Requestsは、Podが最低限必要とするCPUとメモリの容量です。Limitsは、Podの負荷が高まった際に使えるCPUとメモリの最大容量です。マニフェストに指定することでPodごと(正確にはContainerごと)に設定することができます。

# Requests / Limits設定例

resources:

  requests:

    cpu: 100m

    memory: 512Mi

  limits:

    cpu: 250m

    memory: 768Mi

RequestsとLimitsの差が意味すること

差が大きい場合

PodのスケジューリングはRequestsに基づき決定されるので、実際には負荷が高いノードであっても、Requestsの合計値として空きがあれば新たなPodを配置することができてしまいます。これがオーバーコミットと呼ばれる状態です。全てのPodが必ず負荷が高い状態が続くわけではないので、このようなことができます。よしなにノードのリソースを使いあう状態になるので、コスト効率は高まります。しかし、この状態はノードのリソースを使い果たすリスクがあるため、負荷が高まった場合は一定の条件でPodを停止されます。

差が小さい(同じ)場合

RequestsとLimitsを同じ値にすると、オーバーコミットを回避することができ、不用意にPodが停止されるリスクを回避することができますが、リソースの集約率は低下します。

つまり、Podの安定稼働とリソース集約率のトレードオフの状態なのです。したがって、ユースケースに見合ったチューニングが必要になってきます。

Limit Rangesによるリソース使用量指定の自動化

Request / Limitsを指定することによって、Podが利用するリソース量を明示できるようになりました。しかし、この設定はあくまでPod側でしているするものです。つまり、どちらかというと開発者側に依存する形になります。言い換えれば、開発者が設定を忘れたままデプロイすることも可能になってしまいます。これでは意味がありません。そこで、Limit Rangesを使います。Limit Rangesは、Podが利用するCPU/メモリのRequests / Limitsの下限と上限を設定することで、必要以上に大きなPodが配置されるリスクを排除するとともに、開発者側でリソース使用量が指定されなかった場合に自動的にRequest / Limitsを設定することができます。

これで、クラスター内の全てのPodに必ずResuest / Limitsを明示させる仕組みを実現することができます。この辺りの詳細は、筆者の著書にも詳しく書いてありますので、興味があればこちらも読んでみると良いと思います。

まとめ

適切にかつ漏れなくRequest / Limitsを指定することで初めて確実なクラスターのキャパシティ管理が可能になります。Podを安定稼働させるためにはもちろんのこと、ノードのキャパシティ管理には不可欠な要素です。しっかりとしたリソースマネジメントを行うことは、安定したKubernetesクラスターの運用の第一歩です。必ず設定するようにしましょう。なお、これらの可視化方法は別のPostでご紹介します。お楽しみに。