TechLunch

The free lunch is over.

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割り当てについて試して見たいと思います。