5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[k8s] Pod への CPU/メモリ制限について確認した時のメモ(requests/limit/LimitRanges)

Posted at

以下を確認したときのメモ。

コンテナおよびPodへのCPUリソースの割り当て
コンテナおよびPodへのメモリーリソースの割り当て

動きとしては基本的に同じように見えたので、今回は コンテナおよびPodへのCPUリソースの割り当て を確認する。(メモリの場合、OOM Kill の可能性があるなどは違うと思うが)

まとめ

  • 各 Node で現状どれだけリソースが割当可能であるかは kubectl describe node コマンドで Allocated resources の情報を見て確認可能
  • resources:requests によって Pod が要求する下限の値を指定可能であり、スケジューリングで考慮される
  • resources:limits によって Pod が利用可能な上限の値を指定可能である
  • LimitRanges によってデフォルト値などの設定が可能

環境

AWS の EKS を利用。

$kubectl version
Client Version: version.Info{Major:"1", Minor:"16+", GitVersion:"v1.16.6-beta.0", GitCommit:"e7f962ba86f4ce7033828210ca3556393c377bcc", GitTreeState:"clean", BuildDate:"2020-01-15T08:26:26Z", GoVersion:"go1.13.5", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14+", GitVersion:"v1.14.9-eks-f459c0", GitCommit:"f459c0672169dd35e77af56c24556530a05e9ab1", GitTreeState:"clean", BuildDate:"2020-03-18T04:24:17Z", GoVersion:"go1.12.12", Compiler:"gc", Platform:"linux/amd64"}

# alias の設定
$alias |grep kubectl
k=kubectl

CPUの要求と制限を指定する

CPUの要求と制限を指定するという項目をやってみる
事前に kubectl create namespace cpu-example は実行済みとする。

まずは検証用の Pod を起動させてない状態で2つのNode のリソース状況を確認。

$k describe node ip-192-168-48-33.ap-northeast-1.compute.internal

・・・

Capacity:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           20959212Ki
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3977916Ki
 pods:                        17
Allocatable:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           19316009748
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3875516Ki
 pods:                        17

・・・

Non-terminated Pods:         (4 in total)
  Namespace                  Name                        CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                        ------------  ----------  ---------------  -------------  ---
  kube-system                aws-node-6gp92              10m (0%)      0 (0%)      0 (0%)           0 (0%)         15d
  kube-system                coredns-58986cd576-8s9gt    100m (5%)     0 (0%)      70Mi (1%)        170Mi (4%)     13d
  kube-system                coredns-58986cd576-cf457    100m (5%)     0 (0%)      70Mi (1%)        170Mi (4%)     13d
  kube-system                kube-proxy-cckxl            100m (5%)     0 (0%)      0 (0%)           0 (0%)         15d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                    Requests    Limits
  --------                    --------    ------
  cpu                         310m (15%)  0 (0%)
  memory                      140Mi (3%)  340Mi (8%)
  ephemeral-storage           0 (0%)      0 (0%)
  attachable-volumes-aws-ebs  0           0
Events:                       <none>

$ k describe node ip-192-168-74-169.ap-northeast-1.compute.internal

・・・

Capacity:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           20959212Ki
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3977916Ki
 pods:                        17
Allocatable:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           19316009748
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3875516Ki
 pods:                        17


・・・

Non-terminated Pods:         (2 in total)
  Namespace                  Name                CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                ------------  ----------  ---------------  -------------  ---
  kube-system                aws-node-vs6bm      10m (0%)      0 (0%)      0 (0%)           0 (0%)         15d
  kube-system                kube-proxy-sgv4g    100m (5%)     0 (0%)      0 (0%)           0 (0%)         15d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                    Requests   Limits
  --------                    --------   ------
  cpu                         110m (5%)  0 (0%)
  memory                      0 (0%)     0 (0%)
  ephemeral-storage           0 (0%)     0 (0%)
  attachable-volumes-aws-ebs  0          0
Events:                       <none>

同じインスタンスタイプを使っているので Capacity(総リソース量)Allocatable(割当可能なリソース量) については同じになっている。
こちらはあくまで Node の性能によるもので Pod の起動によって変わるものではないと思われる(違っていたらご指摘下さい)

実際に起動している Pod などを差し引いて対象 Node で割り当て済みリソースを確認出来るのは Allocated resources の部分となる。
「ip-192-168-48-33」の方が CPU リソースが利用されているが、これは core-dns の Pod 2つがこちらの Node で動いているためかと思われる。

# core-dns が片方の Node によっている
$k get pods -A -o wide
NAMESPACE     NAME                       READY   STATUS    RESTARTS   AGE   IP               NODE                                                NOMINATED NODE   READINESS GATES
kube-system   aws-node-6gp92             1/1     Running   0          15d   192.168.48.33    ip-192-168-48-33.ap-northeast-1.compute.internal    <none>           <none>
kube-system   aws-node-vs6bm             1/1     Running   0          15d   192.168.74.169   ip-192-168-74-169.ap-northeast-1.compute.internal   <none>           <none>
kube-system   coredns-58986cd576-8s9gt   1/1     Running   0          13d   192.168.53.252   ip-192-168-48-33.ap-northeast-1.compute.internal    <none>           <none>
kube-system   coredns-58986cd576-cf457   1/1     Running   0          13d   192.168.34.56    ip-192-168-48-33.ap-northeast-1.compute.internal    <none>           <none>
kube-system   kube-proxy-cckxl           1/1     Running   0          15d   192.168.48.33    ip-192-168-48-33.ap-northeast-1.compute.internal    <none>           <none>
kube-system   kube-proxy-sgv4g           1/1     Running   0          15d   192.168.74.169   ip-192-168-74-169.ap-northeast-1.compute.internal   <none>           <none>

# core-dns では request で cpu を要求していた
$k describe pods -A |less
・・・
    Requests:
      cpu:        100m
      memory:     70Mi

各 Node の CPU割当の差分は 200m(310m-110m) だったので core-dns の起動が影響している事が確認出来た。

次に以下の検証用の YAML を作る。

cpu-request-limit.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr
    image: vish/stress
    resources:
      limits:
        cpu: "1"
      requests:
        cpu: "0.5"
    args:
    - -cpus
    - "2"
# Pod を作成
$k apply -f cpu-request-limit.yaml
pod/cpu-demo created

# 起動した Node を特定
$k get pods -A -o wide |grep cpu-demo
cpu-example   cpu-demo                   1/1     Running   0          26s   192.168.84.154   ip-192-168-74-169.ap-northeast-1.compute.internal   <none>           <none>

# Node の状態を確認
$k describe node ip-192-168-74-169.ap-northeast-1.compute.internal

・・・

Capacity:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           20959212Ki
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3977916Ki
 pods:                        17
Allocatable:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           19316009748
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3875516Ki
 pods:                        17


・・・

Non-terminated Pods:         (3 in total)
  Namespace                  Name                CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                ------------  ----------  ---------------  -------------  ---
  cpu-example                cpu-demo            500m (25%)    1 (50%)     0 (0%)           0 (0%)         16s
  kube-system                aws-node-vs6bm      10m (0%)      0 (0%)      0 (0%)           0 (0%)         15d
  kube-system                kube-proxy-sgv4g    100m (5%)     0 (0%)      0 (0%)           0 (0%)         15d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                    Requests    Limits
  --------                    --------    ------
  cpu                         610m (30%)  1 (50%)
  memory                      0 (0%)      0 (0%)
  ephemeral-storage           0 (0%)      0 (0%)
  attachable-volumes-aws-ebs  0           0
Events:                       <none>

Allocated resources の項目が Pod 起動前の 110m から 610m になっているのが分かる。
これは Pod の requests で 「0.5」を指定した為であり、想定どおり。
実際に Allocated resources  より少し上の部分で各 Pod でどれだけリソース割当を行っているかも分かるがこちらもで 500m が cpu-demo Pod に割り当てられている事が分かる。

次に実際のリソース利用状況を見てみる。

$kubectl top pod cpu-demo --namespace=cpu-example
Error from server (NotFound): the server could not find the requested resource (get services http:heapster:)

失敗。
EKS ではメトリクスサーバーがデフォルではインストールされなかったので以下に従い、インストールする。

Kubernetes メトリクスサーバーのインストール

少し待てば kubectl top コマンドが使えるようになる。

$kubectl top pod cpu-demo --namespace=cpu-example
NAME       CPU(cores)   MEMORY(bytes)
cpu-demo   998m         1Mi

コンテナでは --cpus "2" を指定し、実際には Node では vCPU=2 ではあるが、limitscpu: "1" を指定する事で 1vCPU が上限となっている事が分かった。

リソースは削除しておく

$kubectl delete pod cpu-demo --namespace=cpu-example

ノードよりも大きいCPU要求を指定する

ノードよりも大きいCPU要求を指定する

以下のような 100vCPU を下限とする Pod を作成して確認する。

cpu-request-limit-2.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cpu-demo-2
  namespace: cpu-example
spec:
  containers:
  - name: cpu-demo-ctr-2
    image: vish/stress
    resources:
      limits:
        cpu: "100"
      requests:
        cpu: "100"
    args:
    - -cpus
    - "2"
$k apply -f cpu-request-limit-2.yaml

# pending になっている
$ kubectl get pod cpu-demo-2 --namespace=cpu-example
NAME         READY   STATUS    RESTARTS   AGE
cpu-demo-2   0/1     Pending   0          15s

# CPU が足りず、スケジューリングされていない
$k describe pod cpu-demo-2 --namespace=cpu-example

・・・

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  61s   default-scheduler  0/2 nodes are available: 2
 Insufficient cpu.

vCPU 100 の Node は存在しない為、スケジューリングされず、Pod は Pending の状態となる。

検証が終わったので削除しておく。

$kubectl delete pod cpu-demo-2 --namespace=cpu-example

requests を指定しない場合の挙動について

ドキュメントを見ると以下のように書いてある。

CPU制限を指定しない場合

  • コンテナのCPUリソースの使用量に上限がない状態となります。コンテナは実行中のノードで利用可能なすべてのCPUを使用できます。
  • CPU制限を与えられたnamespaceでコンテナを実行されると、コンテナにはデフォルトの制限値が自動的に指定されます。クラスターの管理者はLimitRangeによってCPU制限のデフォルト値を指定できます

EKS の環境では LimitRange はどのようになっているのだろうか。

$k get limitranges
No resources found in default namespace.

default namesapace には設定されてなさそうである。
この場合、requests を設定しない場合、どのようになるのか。

# deployment を作る
$kubectl create deployment test --image=nginx

# Pod 数を50 にする
$kubectl scale deployment test --replicas=50

# 確認
$kubectl get deployment test --watch
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
test   27/50   50           27          93s

$k get pods |grep Pending
test-7b66484b7d-2jknd   0/1     Pending   0          2m
test-7b66484b7d-4wsqn   0/1     Pending   0          119s
test-7b66484b7d-795gl   0/1     Pending   0          119s
test-7b66484b7d-92w2s   0/1     Pending   0          119s
test-7b66484b7d-94ggn   0/1     Pending   0          119s
test-7b66484b7d-9bvkm   0/1     Pending   0          119s
test-7b66484b7d-9vpqx   0/1     Pending   0          2m
test-7b66484b7d-b2zfk   0/1     Pending   0          2m
test-7b66484b7d-dthfr   0/1     Pending   0          2m
test-7b66484b7d-ghsq4   0/1     Pending   0          2m
test-7b66484b7d-h2w8b   0/1     Pending   0          119s
test-7b66484b7d-j8bj9   0/1     Pending   0          119s
test-7b66484b7d-k9666   0/1     Pending   0          119s
test-7b66484b7d-msf2g   0/1     Pending   0          119s
test-7b66484b7d-n5llc   0/1     Pending   0          2m
test-7b66484b7d-n6hmf   0/1     Pending   0          119s
test-7b66484b7d-nrkvz   0/1     Pending   0          119s
test-7b66484b7d-q9q88   0/1     Pending   0          119s
test-7b66484b7d-rdntb   0/1     Pending   0          119s
test-7b66484b7d-ttfm4   0/1     Pending   0          119s
test-7b66484b7d-wjkbt   0/1     Pending   0          119s
test-7b66484b7d-z5gxk   0/1     Pending   0          2m
test-7b66484b7d-zrptl   0/1     Pending   0          119s

こんな感じでいくつかの Pod は Pending になっており、50 の Pod は起動できなかった。
なぜか。

# Insufficient pods となっている
$ k describe pods test-7b66484b7d-zrptl

・・・

Events:
  Type     Reason            Age                  From               Message
  ----     ------            ----                 ----               -------
  Warning  FailedScheduling  79s (x2 over 2m31s)  default-scheduler  0/2 nodes a
re available: 2 Insufficient pods.

# Node を見てみる
$k describe node ip-192-168-74-169.ap-northeast-1.compute.internal

・・・

Capacity:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           20959212Ki
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3977916Ki
 pods:                        17
Allocatable:
 attachable-volumes-aws-ebs:  25
 cpu:                         2
 ephemeral-storage:           19316009748
 hugepages-1Gi:               0
 hugepages-2Mi:               0
 memory:                      3875516Ki
 pods:                        17


・・・

Non-terminated Pods:         (17 in total)

・・・

Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource                    Requests   Limits
  --------                    --------   ------
  cpu                         110m (5%)  0 (0%)

今回の場合、 Allocatable pods=17 であり、17 の Pod が起動しているので追加の Pod が起動できないという状況であると思われる。
リソースという意味では Allocated resources を見ると余裕があり、こちらの制限によってスケジューリングされた状況ではなく、実際に Event のメッセージが違うことからも判断が出来る。

以下で削除しておく

$k delete deployments test
deployment.extensions "test" deleted

requests/limit のデフォルト値を設定する

Configure Default CPU Requests and Limits for a Namespace

LimitRange を設定して、requests がない場合でもデフォルト値が設定されるようにしてみる。

cpu-defaults.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-limit-range
spec:
  limits:
  - default:
      cpu: 1
    defaultRequest:
      cpu: 0.5
    type: Container
$k apply -f cpu-defaults.yaml

$k get limitranges
NAME              CREATED AT
cpu-limit-range   2020-06-01T00:24:48Z

OK.

ではこの状態で request 及び limits 設定しない Pod を作成してみる。

# request/limits を指定しない Pod を作成する
$kubectl run nginx-pod --image=nginx:alpine --generator=run-pod/v1
pod/nginx-pod created

# LimitRange で指定したデフォルト値が設定されている
$k get pods -o json |less
・・・

            "spec": {
                "containers": [
                    {
                        "image": "nginx:alpine",
                        "imagePullPolicy": "IfNotPresent",
                        "name": "nginx-pod",
                        "resources": {
                            "limits": {
                                "cpu": "1"
                            },
                            "requests": {
                                "cpu": "500m"
                            }
                        },

以下で削除

$ k delete pod nginx-pod

$ k delete limitranges cpu-limit-range
5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?