はじめに
Kubernetesでは、Podに割り当てるリソースの制限が出来ます。主に2種類の指定方法があります。自分たちのワークロードに応じて、適切なものを選択すると良いでしょう。
Resource Requests
Podを作成する時に必要なリソースをリクエストする指定。実際にPodが使用するリソースは制限しない。Requestsで指定したリソースを超えて無制限にリソースを利用可能
Resource Limits
Podが実際に資料するリソースを制限する仕組み。CPUを指定すると、指定した数以上は使用されない。メモリを指定すると、指定した数を超えた場合は、OOM Killer でPodを強制終了する(OOM Killer)
今回の記事では、Resource Limit の挙動確認します。Kubernetes は、Oracle Cloud の Kubernetesサービス(OKE)を使っていますが、一般的な環境と変わらないはずです。
Resource Limits
Resource Limits 有りの Pod を作成します。マニフェストファイル内に、cpu: "1"
や memory: "200Mi"
を指定します。余談ですがコンテナイメージのsugimount/toolbox
は、便利なツール群を導入済みの Ubuntu 18.04 の Image です。自作のものです。Dockerfile は Docker Hub 経由でたどれるので興味があればどうぞ。
-
cpu: "1"
: 1秒間に、1個の vCPU を1000ミリ秒使用可能な制限 -
memory: "200Mi"
: Memory を 200MiB の制限
cat <<'EOF' > /home/testuser01/manifests/resourcelimit.yaml
apiVersion: v1
kind: Pod
metadata:
name: limited-pod
spec:
containers:
- image: sugimount/toolbox:release-0.0.3
name: limited-pod
command: ["sleep", "1800m"]
resources:
limits:
cpu: "1"
memory: "200Mi"
EOF
Apply して作成します。
kubectl apply -f /home/testuser01/manifests/resourcelimit.yaml
Resource Limits 無し。
cat <<'EOF' > /home/testuser01/manifests/no_resourcelimit.yaml
apiVersion: v1
kind: Pod
metadata:
name: no-limited-pod
spec:
containers:
- image: sugimount/toolbox:release-0.0.3
name: no-limited-pod
command: ["sleep", "1800m"]
EOF
Apply
kubectl apply -f /home/testuser01/manifests/no_resourcelimit.yaml
2個の Pod が稼働しています
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
limited-pod 1/1 Running 0 38m 10.244.3.18 10.0.10.6 <none> <none>
no-limited-pod 1/1 Running 0 33s 10.244.3.19 10.0.10.6 <none> <none>
動作確認 Resource Limits あり
Resource Limits が指定されているPod 内で負荷を掛けるために、bash を起動します。
kubectl exec -it limited-pod bash
なお、Pod 内からCPUの詳細情報を確認すると、Hostで見えているCPUがすべての数見えています。特に Resource Limits の指定は関係ないようです。(下の例だと2vCPU分)
root@limited-pod:/# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum 8167M CPU @ 2.00GHz
stepping : 4
microcode : 0x1
cpu MHz : 1995.308
cache size : 16384 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip pku ospke md_clear
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
bogomips : 3990.61
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum 8167M CPU @ 2.00GHz
stepping : 4
microcode : 0x1
cpu MHz : 1995.308
cache size : 16384 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip pku ospke md_clear
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
bogomips : 3990.61
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
root@limited-pod:/#
メモリについても同様で、Host側に搭載されているメモリが全て見えています。こちらも、特に Resource Limits の指定は関係なく、すべてが見えています。
# free -m
total used free shared buff/cache available
Mem: 14761 607 12669 25 1485 13848
Swap: 0 0 0
stress コマンドで CPU に負荷を掛けます
stress -c 2
Host側で dstat コマンドを実行し、消費したリソースを確認します。左列の usr
の部分が、50% 前後になっています。Resource Limits で cpu: "1"
指定しているため、2個中の1個が使用されたと考えると、数値は一致しています。正常に制限されていますね。(なお、Resource Limits の指定が無い場合は、100% になります。後で説明します)
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]# dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
6 2 92 0 0 0| 151k 230k| 0 0 | 0 0 |1005 2150
2 1 98 0 0 0| 0 20k|4276B 5411B| 0 0 | 782 1516
2 1 98 0 0 0| 0 0 |3139B 3357B| 0 0 | 684 1451
3 1 96 0 0 0| 0 8192B|8588B 13k| 0 0 | 737 1605
37 0 63 0 0 0| 0 0 |2939B 3176B| 0 0 |1255 1298
52 1 47 0 0 0| 0 0 |2566B 2886B| 0 0 |1655 1584
52 1 48 0 0 0| 0 4096B|2658B 2978B| 0 0 |1592 1379
53 1 45 0 0 0| 0 0 |2966B 3352B| 0 0 |1892 2590
52 0 48 0 0 0| 0 0 |4321B 5125B| 0 0 |1394 986
同様にメモリにも負荷を掛けましょう。Resource Limits の範囲に収まる指定です。
stress --vm 1 --vm-bytes 190M --vm-hang 1
Host側のメモリ消費量を見ると、used
の部分が 190M 程増えています。
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]# dstat -tpcdrmngy
Terminal width too small, trimming output.
----system---- ---procs--- ----total-cpu-usage---- -dsk/total- --io/total- ------memory-usage----- -net/total- ---paging-->
time |run blk new|usr sys idl wai hiq siq| read writ| read writ| used buff cach free| recv send| in out >
05-07 07:42:24| 0 0 9.5| 5 2 93 0 0 0| 107k 178k|1.96 6.81 | 717M 3108k 1382M 12.4G| 0 0 | 0 0 >
05-07 07:42:25| 0 0 0| 1 1 98 0 0 0| 0 0 | 0 0 | 717M 3108k 1382M 12.4G|5354B 4794B| 0 0 >
05-07 07:42:26| 0 0 12| 3 2 96 0 0 0| 0 0 | 0 0 | 717M 3108k 1382M 12.4G|6188B 6736B| 0 0 >
05-07 07:42:27| 0 0 4.0| 3 1 96 0 0 0| 0 16k| 0 4.00 | 717M 3108k 1382M 12.4G|4541B 973B| 0 0 >
05-07 07:42:28| 0 0 0| 4 1 96 0 0 0| 0 0 | 0 0 | 717M 3108k 1382M 12.4G|5445B 6106B| 0 0 >
05-07 07:42:29| 0 0 3.0| 2 3 95 0 0 0| 0 0 | 0 0 | 907M 3108k 1382M 12.2G|6244B 11k| 0 0 >
05-07 07:42:30| 0 0 0| 2 3 95 0 0 0| 0 0 | 0 0 | 907M 3108k 1382M 12.2G|5655B 5914B| 0 0 >
05-07 07:42:31| 0 0 23| 5 4 92 0 0 0| 0 0 | 0 0 | 908M 3108k 1382M 12.2G| 287B 875B| 0 0 >
05-07 07:42:32| 0 0 6.0| 3 3 94 0 0 0| 0 8192B| 0 1.00 | 908M 3108k 1382M 12.2G|3982B 4502B| 0 0 >
05-07 07:42:33| 0 0 0| 2 3 96 0 0 0| 0 0 | 0 0 | 908M 3108k 1382M 12.2G|2254B 2806B| 0 0 >^C
では今度は、Resource Limits を超える負荷を掛けてみます。すると、bash が強制終了して、Pod から排出されました。
root@limited-pod:/# stress --vm 1 --vm-bytes 250M --vm-hang 1
stress: info: [22] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
command terminated with exit code 137
testuser01@cloudshell:manifests (ap-tokyo-1)$
Pod が強制終了して、Restartしている様子が見えます。
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
limited-pod 1/1 Running 4 50m 10.244.3.29 10.0.10.6 <none> <none>
no-limited-pod 1/1 Running 0 48m 10.244.3.25 10.0.10.6 <none> <none>
output=yaml
を指定して、詳細な情報を確認しましょう。
kubectl get pod limited-pod --output=yaml
lastState の欄に、reason: OOMKilled
が見えます。Resource Limits の指定を超えて利用したため、コンテナプロセスが強制終了されましたね。
省略
lastState:
terminated:
containerID: docker://263b2ef2a1ee4cfdd86e37fb88ddecdcc2db92c05794c5b096a6b2cf756e3a83
exitCode: 137
finishedAt: "2020-07-05T07:43:13Z"
reason: OOMKilled
startedAt: "2020-07-05T07:38:59Z"
省略
Host側メモリを見ると、特段変化はありません。すぐにメモリが Limits を超えたことを検知して、OOM Killed されました。
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]# dstat -tpcdrmngy
Terminal width too small, trimming output.
----system---- ---procs--- ----total-cpu-usage---- -dsk/total- --io/total- ------memory-usage----- -net/total- ---paging-->
time |run blk new|usr sys idl wai hiq siq| read writ| read writ| used buff cach free| recv send| in out >
05-07 07:43:10| 0 0 9.5| 5 2 93 0 0 0| 106k 177k|1.95 6.77 | 717M 3108k 1383M 12.4G| 0 0 | 0 0 >
05-07 07:43:11| 0 0 10| 2 1 98 0 0 0| 0 0 | 0 0 | 717M 3108k 1383M 12.4G|2668B 4084B| 0 0 >
05-07 07:43:12| 0 0 0| 2 1 98 0 0 0| 0 0 | 0 0 | 717M 3108k 1383M 12.4G|3470B 3724B| 0 0 >
05-07 07:43:13| 0 0 6.0| 1 1 98 0 0 0| 0 16k| 0 3.00 | 718M 3108k 1383M 12.4G|3548B 4195B| 0 0 >
05-07 07:43:14|1.0 0 81| 21 21 51 6 0 1| 0 1860k| 0 85.0 | 716M 3108k 1383M 12.4G| 16k 18k| 0 0 >
05-07 07:43:15|2.0 0 81| 12 10 78 0 0 0| 0 436k| 0 80.0 | 724M 3108k 1390M 12.3G| 14k 9245B| 0 0 >
05-07 07:43:16|1.0 0 86| 14 8 77 0 0 0| 0 48k| 0 11.0 | 721M 3108k 1383M 12.4G| 11k 6252B| 0 0 >
05-07 07:43:17| 0 0 21| 7 3 90 0 0 0| 0 0 | 0 0 | 715M 3108k 1383M 12.4G|8982B 5462B| 0 0 >
05-07 07:43:18|1.0 0 25| 3 2 95 0 0 0| 0 0 | 0 0 | 715M 3108k 1383M 12.4G|2688B 3152B| 0 0 >^C
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]#
動作確認 Resource Limits なし
Resource Limits が無いPod 内で負荷を掛けるために、bash を起動します。
kubectl exec -it no-limited-pod bash
Pod 内から見える CPU の情報は、Resource Limits の有無では何もかわりません
root@no-limited-pod:/# cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum 8167M CPU @ 2.00GHz
stepping : 4
microcode : 0x1
cpu MHz : 1995.308
cache size : 16384 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip pku ospke md_clear
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
bogomips : 3990.61
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 85
model name : Intel(R) Xeon(R) Platinum 8167M CPU @ 2.00GHz
stepping : 4
microcode : 0x1
cpu MHz : 1995.308
cache size : 16384 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology cpuid tsc_known_freq pni pclmulqdq vmx ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx avx512f avx512dq rdseed adx smap clflushopt clwb avx512cd avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves arat umip pku ospke md_clear
bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs taa itlb_multihit
bogomips : 3990.61
clflush size : 64
cache_alignment : 64
address sizes : 40 bits physical, 48 bits virtual
power management:
root@no-limited-pod:/#
Memory も同様に何もかわりません
root@no-limited-pod:/# free -m
total used free shared buff/cache available
Mem: 14761 606 12666 25 1489 13851
Swap: 0 0 0
root@no-limited-pod:/#
stress コマンドで CPU に負荷を掛けます
stress -c 2
Host側で dstat コマンドを実行し、消費したリソースを確認します。usr
の部分が、99% 前後になっています。Resource Limits が有りでは、50% 前後になっていたところですが、何も制限されていないことが分かります。
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]# dstat -tpcdrmngy
Terminal width too small, trimming output.
----system---- ---procs--- ----total-cpu-usage---- -dsk/total- --io/total- ------memory-usage----- -net/total- ---paging-->
time |run blk new|usr sys idl wai hiq siq| read writ| read writ| used buff cach free| recv send| in out >
05-07 08:46:03| 0 0 8.3| 4 2 94 0 0 0| 69k 129k|1.26 4.83 | 721M 3108k 1385M 12.4G| 0 0 | 0 0 >
05-07 08:46:04| 0 0 4.0| 4 2 95 0 0 0| 0 0 | 0 0 | 721M 3108k 1385M 12.4G| 16k 19k| 0 0 >
05-07 08:46:05| 0 0 2.0| 1 0 99 0 0 0| 0 16k| 0 4.00 | 721M 3108k 1385M 12.4G|6948B 5678B| 0 0 >
05-07 08:46:06|1.0 0 10| 2 1 97 0 0 0| 0 212k| 0 28.0 | 722M 3108k 1385M 12.4G|2658B 3138B| 0 0 >
05-07 08:46:07|2.0 0 3.0| 75 0 25 0 0 0| 0 0 | 0 0 | 722M 3108k 1385M 12.4G|4912B 5792B| 0 0 >
05-07 08:46:08|3.0 0 2.0| 99 1 0 0 0 0| 0 0 | 0 0 | 722M 3108k 1385M 12.4G|3815B 4355B| 0 0 >
05-07 08:46:09|2.0 0 4.0| 99 1 1 0 0 0| 0 0 | 0 0 | 722M 3108k 1385M 12.4G|2566B 3072B| 0 0 >
05-07 08:46:10|2.0 0 6.0| 99 1 0 0 0 1| 0 12k| 0 3.00 | 722M 3108k 1385M 12.4G|7160B 3705B| 0 0 >
05-07 08:46:11|2.0 0 1.0| 99 1 1 0 0 0| 0 0 | 0 0 | 722M 3108k 1385M 12.4G|8320B 13k| 0 0 >^C
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]#
では今度は、メモリに負荷を掛けます。
root@limited-pod:/# stress --vm 1 --vm-bytes 250M --vm-hang 1
stress: info: [22] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
command terminated with exit code 137
testuser01@cloudshell:manifests (ap-tokyo-1)$
Host側メモリを見ると、250MB 程のメモリが使用されています。Resource Limits 有りでは OOM Killed されましたが、Resource Limits 無しでは正常に稼働しています。
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]# dstat -tpcdrmngy
Terminal width too small, trimming output.
----system---- ---procs--- ----total-cpu-usage---- -dsk/total- --io/total- ------memory-usage----- -net/total- ---paging-->
time |run blk new|usr sys idl wai hiq siq| read writ| read writ| used buff cach free| recv send| in out >
05-07 08:47:30| 0 0 8.3| 4 2 94 0 0 0| 69k 128k|1.25 4.80 | 721M 3108k 1385M 12.4G| 0 0 | 0 0 >
05-07 08:47:31| 0 0 12| 1 1 98 0 0 0| 0 0 | 0 0 | 721M 3108k 1385M 12.4G| 132B 150B| 0 0 >
05-07 08:47:32| 0 0 1.0| 3 1 96 0 0 0| 0 0 | 0 0 | 721M 3108k 1385M 12.4G| 11k 17k| 0 0 >
05-07 08:47:33| 0 0 13| 4 2 94 0 0 0| 0 0 | 0 0 | 721M 3108k 1385M 12.4G| 946B 1022B| 0 0 >
05-07 08:47:34| 0 0 2.0| 3 5 92 0 0 0| 0 28k| 0 5.00 | 972M 3108k 1385M 12.1G| 23k 24k| 0 0 >
05-07 08:47:35| 0 0 4.0| 3 4 94 0 0 0| 0 0 | 0 0 | 972M 3108k 1385M 12.1G| 66B 66B| 0 0 >
05-07 08:47:36| 0 0 12| 2 4 94 0 0 1| 0 136k| 0 20.0 | 972M 3108k 1385M 12.1G|6038B 7014B| 0 0 >
05-07 08:47:37| 0 0 0| 1 4 95 0 0 0| 0 0 | 0 0 | 972M 3108k 1385M 12.1G|1184B 1772B| 0 0 >
05-07 08:47:38| 0 0 0| 2 4 94 0 0 0| 0 0 | 0 0 | 972M 3108k 1385M 12.1G|6213B 6756B| 0 0 >^C
[root@oke-crdazdbgvsw-n3geolfmm3d-s6bnuvahoda-2 ~]#
まとめ
この結果をみると、CPU については Limits を指定すれば、指定した数を超えずに稼働してくれて良いです。
メモリについては、指定した数を超えると OOM Killed されて強制再起動されます。そのため、該当の Worker Node の全体でメモリをうまく管理していく必要があります。
参考URL
CPU
https://kubernetes.io/ja/docs/tasks/configure-pod-container/assign-cpu-resource/
Memory
https://kubernetes.io/ja/docs/tasks/configure-pod-container/assign-memory-resource/
Metric Server
https://github.com/kubernetes-sigs/metrics-server