Edited at

KubernetesのResource RequestsとResource Limitsについて


Resource Requests


Resource Requests とは

podをデプロイする時に必要とするリソース(CPU/メモリ)を指定することができる仕組み。

ただしpodは指定したresource requests以上のリソースを使うことができる。(リソース使用量の制限はlimitを使う)

またその指定したリソースがそのpod用に確保されるわけではない。

あくまでpodをデプロイ時にそのリソース量が空いているかをチェックするためのもの。

ポイントとしてはpodをデプロイするときに、nodeのリソース使用量は見ないで、resource requestsをみてデプロイが行われる。

なので、nodeのリソース(CPUやメモリ)の使用率が100%でも、resource requestsに空きがあればデプロイされる。空きがないnodeにはデプロイされない。

たとえばメモリ1Gのnodeがあって、resource requestsが400MBの指定がされているpodが2つデプロイされていた場合、3つ目はデプロイできない。

デプロイしようとしたらそのpodのSTATUSはPendingになる。

apiVersion: v1

kind: Pod
metadata:
name: requests-pod
spec:
containers:
- image: busybox
command: ["dd", "if=/dev/zero", "of=/dev/null"]
name: main
resources:
requests: # ここで指定
cpu: 200m
memory: 10Mi

cpu 200m は200 millicoresの略で1000milli coreで1cpu。200 mill coreで 1/5 CPU使うということ。(ちなみにcpu: 1と指定したらcpu: 1000mと解釈される)

10Miは 10 mebibytes 。


例: Resource Requestsを指定してみる

$ kubectl run requests-pod-1 --image=busybox --restart Never --requests='cpu=1200m,memory=500Mi' -- sleep 100000

$ kubectl describe nodes
Name: minikube
...
Capacity: # nodeの使用可能リソース量
cpu: 2
memory: 2048484Ki
pods: 110
Allocatable: # Podが使用可能なリソース量(Capacityより若干少ないのはsystem daemonが少しリソースを使っているから)。なおResouceRequestを指定指定してもここの数値は減らない。
cpu: 2
memory: 1946084Ki
pods: 110
...
Non-terminated Pods: (5 in total) #ここにpodで指定したResource Request値が表示される
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
default requests-pod-1 1200m (60%) 0 (0%) 500Mi (26%) 0 (0%)
kube-system kube-addon-manager-minikube 5m (0%) 0 (0%) 50Mi (2%) 0 (0%)
kube-system kube-dns-54cccfbdf8-686qf 260m (13%) 0 (0%) 110Mi (5%) 170Mi (8%)
kube-system kubernetes-dashboard-77d8b98585-mwptt 0 (0%) 0 (0%) 0 (0%) 0 (0%)
kube-system storage-provisioner 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources: #ここにpodで指定した総Resource Request値が表示される
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
1465m (73%) 0 (0%) 660Mi (34%) 170Mi (8%)


例2: nodeのCapacityを超えてResource Requestを指定してみる

$  kubectl run requests-pod-2 --image=busybox --restart Never --requests='cpu=2000m,memory=2000Mi' -- sleep 100000

pod "requests-pod-2" created

# Resource Requestの空きがないためSTATUSは`Pending`になっている
$ kc get pod
NAME READY STATUS RESTARTS AGE
requests-pod-1 1/1 Running 0 52m
requests-pod-2 0/1 Pending 0 2s

# EventsのMessageに`0/1 nodes are available: 1 Insufficient cpu, 1 Insufficient memory.`と表示されていることが分かる。
$ kc describe pod requests-pod-2
Name: requests-pod-2
Namespace: default
Node: <none>
Labels: run=requests-pod-2
Annotations: <none>
Status: Pending
IP:
Containers:
requests-pod-2:
Image: busybox
Port: <none>
Args:
sleep
100000
Requests:
cpu: 2
memory: 2000Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-lvqmh (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
default-token-lvqmh:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-lvqmh
Optional: false
QoS Class: Burstable
Node-Selectors: <none>
Tolerations: <none>
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 3s (x5 over 10s) default-scheduler 0/1 nodes are available: 1 Insufficient cpu, 1 Insufficient memory.


Resource Limits


Resource Limitsとは

resource limitsを指定すると、そのpodが使用するリソース(CPU/メモリ)に制限を設けることができる。

たとえnodeにリソースの空きがあっても指定されたresource limits以上のリソースは使用することができなくなる。

resource limitsを指定しない場合、無制限にリソースを使用できる。

上記のようにresource requestsを指定していなかったら、limit値と同様の値がresource requestsに設定される。

resource requestと違って、resource limitはnodeの使用可能リソース量を超えて指定ができる。

たとえばメモリが1Gのnodeがあって、pod Aのメモリrequestが500MBでlimitが800MB、pod Bのメモリrequestが500MBでlimitが500MBでもOK。

CPUも同様。

ちなみにResource Limitで指定されたCPUリソース以上をコンテナのプロセスが実際に使用しようとした場合、

CPU速度が遅くなるだけで、問題が起きるわけではない。

しかしメモリの場合は違う。Resource Limitで指定した以上のメモリをコンテナのプロセスが使用しようとした場合、

コンテナのプロセスはkillされる(一般に"コンテナがOOM Killされた"という)。

もしpodのrestart policyがAlwaysもしくはOnFailureが設定されていた場合、podのコンテナは自動的に再起動される。なのでkillされたことに気づかないかもしれない。

もし再度メモリオーバーになったら再度再起動されるが、再起動時間はexponential backoffアルゴリズムにしたがって段々遅くなる。

その場合、podのstatusはCrashLoopBackOffになる。

CrashLoopBackOffはkubeletが諦めたことをささない。少しずつ再起動期間は伸びるが最終的に5分間隔で再起動が繰り返されるようになる。

再起動回数はpodのRESTARTSに表示される。


例: Resource Limitsを指定してみる

apiVersion: v1

kind: Pod
metadata:
name: limited-pod
spec:
containers:
- image: busybox
command: ["dd", "if=/dev/zero", "of=/dev/null"]
name: main
resources:
limits: # ここで制限を指定
cpu: 1
memory: 20Mi

以下のようにCPU Limits、Memory LimitsはnodeのCapacityを超えて指定ができる

$ kubectl run requests-pod-1 --image=busybox --restart Never --requests='cpu=1200m,memory=500Mi' -- sleep 100000

$ kubectl run requests-and-limits-pod-2 --image=busybox --restart Never --requests='cpu=200m,memory=400Mi' --limits='cpu=1500m,memory=1500Mi' -- sleep 100000
$ kubectl run requests-and-limits-pod-3 --image=busybox --restart Never --requests='cpu=200m,memory=400Mi' --limits='cpu=1500m,memory=1500Mi' -- sleep 100000

$ kubectl describe nodes
・・・
Non-terminated Pods: (7 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits
--------- ---- ------------ ---------- --------------- -------------
default requests-and-limits-pod-2 200m (10%) 1500m (75%) 400Mi (21%) 1500Mi (78%)
default requests-and-limits-pod-3 200m (10%) 1500m (75%) 400Mi (21%) 1500Mi (78%)
default requests-pod-1 1200m (60%) 0 (0%) 500Mi (26%) 0 (0%)
kube-system kube-addon-manager-minikube 5m (0%) 0 (0%) 50Mi (2%) 0 (0%)
kube-system kube-dns-54cccfbdf8-686qf 260m (13%) 0 (0%) 110Mi (5%) 170Mi (8%)
kube-system kubernetes-dashboard-77d8b98585-mwptt 0 (0%) 0 (0%) 0 (0%) 0 (0%)
kube-system storage-provisioner 0 (0%) 0 (0%) 0 (0%) 0 (0%)
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
1865m (93%) 3 (150%) 1460Mi (76%) 3170Mi (166%)
・・・


参考