Kubernetes入門2: Podに割り当てるメモリを制限する
Kubernetesでは、VMを管理するとき同様に、Podに割り当てるリソースを制限することができます。公式ドキュメントを参照しながら、Podに割り当てるメモリを制限する方法と挙動について試してみました。英語が得意な方は元記事をご参照ください。
- Podが制限以下のメモリを消費
- Podが制限以上のメモリを消費
- Podがノードに搭載されているリソース以上のメモリを要求する
の3パターンを試して、実際にどのような挙動となるか見ていきます。
準備
metrics-serverというadd-onsを有効にします。
$ minikube addons enable metrics-server
metrics-serverが実行されているかどうかは次のコマンドで確認できます。
$ kubectl get apiservices NAME v1beta1.metrics.k8s.io
今回のチュートリアル用にnamespaceを作成します。
$ kubectl create namespace mem-example namespace/mem-example created $ kubectl get namespaces NAME STATUS AGE mem-example Active 18s
Podが制限以下のメモリを消費
まず、Podが要求するメモリ量とKubernetesによって制限されるメモリ量を設定ファイルに定義します。 Podが要求するメモリを100MiB、制限を200MiBとし、150MiB程度のメモリを消費するコンテナを定義しています。
# https://k8s.io/examples/pods/resource/memory-request-limit.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo namespace: mem-example spec: containers: - name: memory-demo-ctr image: polinux/stress resources: limits: memory: "200Mi" requests: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Podを作成。
$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
作成したPodが利用中のメモリ量を出力。
$ kubectl top pod --namespace=mem-example NAME CPU(cores) MEMORY(bytes) memory-demo 61m 150Mi
Podが実際に利用してるメモリ(150MiB)が、要求したメモリ(100MiB)よりも大きな値となっていますが、制限値である200MiBよりも小さな値ですので、Podは問題なく動作しています。
Podを削除。
$ kubectl delete pods memory-demo --namespace=mem-example
Podが制限以上のメモリを消費
次に制限値以上のメモリを消費した場合の挙動を見ていきます。設定ファイルは以下の通りです。制限値100MiBに対し、250MiBのメモリを消費するコンテナを起動するように定義しています。
# https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo-2 namespace: mem-example spec: containers: - name: memory-demo-2-ctr image: polinux/stress resources: requests: memory: "50Mi" limits: memory: "100Mi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
Podを作成。
$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
Pod状態を取得すると、STATUSが OOMKilled
となっており、メモリ不足により、プロセスがkillされたことがわかります。
$ kubectl get pods --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 OOMKilled 1 10s
このPodは、強制終了されても、再起動を試みていますので、再度情報を取得してみると、STATUSが CrashLoopBackOff
となっていることがわかります。
$ kubectl get pods --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-2 0/1 CrashLoopBackOff 3 1m
Podを削除。
$ kubectl delete pods memory-demo-2 --namespace=mem-example
Podがノードに搭載されているリソース以上のメモリを要求する
最後に、膨大なメモリ(設定では1000GiB)を要求するPodを作成した場合にどのような挙動を示すのか見てみます。
# https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml apiVersion: v1 kind: Pod metadata: name: memory-demo-3 namespace: mem-example spec: containers: - name: memory-demo-3-ctr image: polinux/stress resources: limits: memory: "1000Gi" requests: memory: "1000Gi" command: ["stress"] args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Podの作成
$ kubectl create -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
Podの情報を取得すると、STATUSが、 Pending
となっています。つまり、Podはスケジューリングされておらず、どのノードでも動作していない状態となります。
$ kubectl get pod memory-demo-3 --namespace=mem-example NAME READY STATUS RESTARTS AGE memory-demo-3 0/1 Pending 0 2m
Podの詳細情報を表示すると、
$ kubectl describe pod memory-demo-3 --namespace=mem-example
次のように、ノード上のメモリ不足により、スケジューリングができないことがわかります。
Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 40s (x22 over 5m) default-scheduler 0/1 nodes are available: 1 Insufficient memory.
PodとNamespaceを削除して終了。
$ kubectl delete pod memory-demo-3 --namespace=mem-example $ kubectl delete namespaces mem-example
以上で、メモリ割り当てに関するチュートリアルは終了となります。次は、CPU割り当てについて試して見たいと思います。