以下を確認したときのメモ。
コンテナおよび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 を作る。
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 ではメトリクスサーバーがデフォルではインストールされなかったので以下に従い、インストールする。
少し待てば kubectl top
コマンドが使えるようになる。
$kubectl top pod cpu-demo --namespace=cpu-example
NAME CPU(cores) MEMORY(bytes)
cpu-demo 998m 1Mi
コンテナでは --cpus "2"
を指定し、実際には Node では vCPU=2 ではあるが、limits
で cpu: "1"
を指定する事で 1vCPU が上限となっている事が分かった。
リソースは削除しておく
$kubectl delete pod cpu-demo --namespace=cpu-example
ノードよりも大きいCPU要求を指定する
以下のような 100vCPU を下限とする Pod を作成して確認する。
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制限を与えられた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
がない場合でもデフォルト値が設定されるようにしてみる。
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