ベストプラクティス第四弾です
こんにちは、jackです。
今回でKubernetesベストプラクティスもいよいよ中盤です。
今回も前回同様、概念的な部分が多いので長くなりますがお付き合いください。
公式ブログはこちら
Kubernetes best practices: Resource requests and limits
Kubernetesベストプラクティスまとめ一覧 というページも作りました。
TL;DR
- プロジェクトやチームが大きくなってきたら、リソース管理をするべし
- リソース管理には Requests と Limits がある
- Requestsは最低限割り振られるリソース(CPUやメモリ)
- Limitsは割り振られるリソースの上限
- CPUユニットは
m
(millicores) - Memoryユニットは
Mi
(mebibyte)
もっと詳しく
リソース管理をするべし
Kubernetesを運用する上でリソースを十分に確保するのは重要なことです。例えば巨大なアプリケーションをリソースの限られたNode上で動かそうとすれば、メモリやCPUが足りなくなり正常に動作しなくなります。
また、大規模な開発をする上でも設定の人為的なミスであったり、プログラムの誤動作で不用意にリソースを奪い合い、パフォーマンスが低下するといったことが考えられます。
今回はこのような問題を未然に防ぐため、Kubernetesのrequestsとlimitsを見ていきましょう。
RequestsとLimits
簡単にいうと、
Requestsは**コンテナに最低限割り振られるリソース(CPUやメモリ)**を指します。Limitsは言葉通り、割り振られるリソースの上限を指します。
もう少し詳しく言うと、Kubernetesは与えられたrequestを確保できるNodeにしかコンテナを生成しませんし、コンテナのリソースは与えられたlimitを超えてはいけません。また、limitがrequestを下回る設定はできません(エラーになります)。
ここで1つ注意する必要があるのが、requestsとlimitsはそれぞれコンテナ基準である点です。仮に、1つのPodに複数のコンテナがある場合、requestsとlimitsは複数コンテナの合算になります。
コンテナでのリソース設定
リソースタイプは2つあります。CPUとMemoryです。
Kubernetesのスケジューラーはこれらを元にどこにPodを生成するか判断します。
GKEを使っている場合のデフォルトNamespaceでは以下の初期設定がされています。
CPU | Memory | |
---|---|---|
Requests | 0.1 Cores | なし |
Limits | なし | なし |
"Hello World"のようなアプリケーションならデフォルトでも構いませんが、通常Podを作成する場合はデフォルトではなく以下にのように指定してあげます。
containers:
- name: container1
image: busybox
resources:
requests:
memory: "32Mi"
cpu: "200m"
limits:
memory: "64Mi"
cpu: "250m"
- name: container2
image: busybox
resources:
requests:
memory: "96Mi"
cpu: "300m"
limits:
memory: "192Mi"
cpu: "750m"
上の設定では合計で500m
CPUと128
MiBのMemoryとなります。
CPU
KubernetesのCPUの概念として、millicores
というものがあります。
CPU1コアが1000 unitとして換算されるので、1CPU = 1000mです。
例えば、1/4コアのリソースが欲しい場合は 250m
となります。
*CPUのRequestがNodeよりも多い場合、そのPodは永遠に立ち上がらないので注意しましょう。
また、CPU Limitsで指定したリソースに達するとスロットリングします。パフォーマンスが低下したりしますが、terminateはしません。ここで前回お話したLivenessプローブ等でhealth checkするといったことも考えられます。
Memory
メモリは bytes で表せます。bytesからpetabytesまで対応してますが、一般的には mebibyte(Mi) を使用することが多いでしょう。
CPUと同じようにメモリもNodeのリソースを超える場合はPodが生成されないので注意しましょう。
CPUとは違いMemoryはLimitを超えてしまうとPodが消失します。DeploymentやStatefulSet、DeamonSetを使用している場合、コントローラーが再度Podを生成してくれます。
名前空間でのリソース設定
一つのアプリケーションがクラスターの大部分のリソースを使ってしまうことが考えられます。それを防ぐために、Namespaceでのリソースを指定することも可能です。
ResourceQuotas
Namespace上にリソースを定義するには以下のようにします。
apiVersion: v1
kind: ResourceQuota
metadata:
name: demo
spec:
hard:
requests.cpu: 500m
requests.memory: 100Mib
limits.cpu: 700m
limits.memory: 500Mib
requests.cpu
とrequests.memory
はそれぞれCPUとMemory Requestsの合計最大値です。要するに10m CPUのコンテナが50個、もしくは100m CPUが5つ、といった具合です。
limits.cpu
とlimits.memory
はLimitsの合計最大値です。
LimitRange
Quotaの他にLimitRangeというものがあります。
極端に大きなコンテナや、また逆に小さすぎるコンテナを作れないように、RequestsとLimitsを制約できます。
LimitRangeについては至ってシンプルなのでここではスキップします。
原文もしくは公式ドキュメントをどうぞ。
まとめ
いかがでしたか?
すこし端折りましたが、基本的なことはまとめられたかと思います。
なにも考えずにKubernetesを使ってもうまく行ってしまうことが多いからこそ、内部を知って未然に思わぬ事故を防ぐことも大事ですね。
それでは、また次回!