#はじめに
今回はコンテナのリソース制御の動作を確認したいと思います。
コンピュータリソースとして制御できるものは、CPU、メモリ、GPUがあります。
GPUは用意できないので、CPU、メモリのみ確認します。
#設定
リソース制御はコンテナごとに定義します。CPU、メモリごとに「requests」と「limits」で値を指定します。
requestsはリソースの下限、limitsは上限です。
CPUは「1(v)CPU=1000m」として値を指定します。実際のCPUのクロック周波数とは関係ないので、注意が必要です。
1コアを指定したい場合は、「1000m」とします。
今回は以下のマニフェストを用意しました。
apiVersion: apps/v1
kind: Deployment
metadata:
name: resource-quota
spec:
replicas: 2
selector:
matchLabels:
env: prd
template:
metadata:
labels:
env: prd
spec:
containers:
- name: nginx
image: nginx:latest
resources:
requests:
memory: 100Mi
cpu: 100m
limits:
memory: 200Mi
cpu: 200m
- name: redis
image: redis:latest
resources:
requests:
memory: 200Mi
cpu: 200m
limits:
memory: 300Mi
cpu: 300m
このマニフェストをapplyします。
比較用として、リソース制御を設定していないDeploymentも用意しました。
$ kubectl apply -f nginx_redis-quota.yaml
deployment.apps/resource-quota created
$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
no-resource-quota-77d577889b-mjfj6 2/2 Running 0 4m8s 192.168.79.116 k8s-worker01 <none> <none>
no-resource-quota-77d577889b-nhkvg 2/2 Running 0 4m8s 192.168.69.250 k8s-worker02 <none> <none>
resource-quota-679594c947-j857k 2/2 Running 0 2m5s 192.168.79.123 k8s-worker01 <none> <none>
resource-quota-679594c947-ls75g 2/2 Running 0 2m5s 192.168.69.249 k8s-worker02 <none> <none>
設定値はkubectl describe podで確認できます。
$ kubectl describe pod resouce-quota-679594c947-j857k
Name: resouce-quota-679594c947-j857k
・・・
Containers:
nginx:
・・・
Limits:
cpu: 200m
memory: 200Mi
Requests:
cpu: 100m
memory: 100Mi
・・・
kubectl describe nodeでそのノードにデプロイされているPodの設定値を確認できます。
$ kubectl describe node k8s-worker01
Name: k8s-worker01
・・・
Non-terminated Pods: (5 in total)
Namespace Name CPU Requests CPU Limits Memory Requests Memory Limits AGE
--------- ---- ------------ ---------- --------------- ------------- ---
default no-resouce-quota-77d577889b-mjfj6 0 (0%) 0 (0%) 0 (0%) 0 (0%) 2d9h
default resouce-quota-679594c947-j857k 300m (15%) 500m (25%) 300Mi (10%) 500Mi (18%) 2d9h
kube-system calico-node-cgdgk 250m (12%) 0 (0%) 0 (0%) 0 (0%) 80d
kube-system kube-proxy-gqt42 0 (0%) 0 (0%) 0 (0%) 0 (0%) 80d
metallb-system speaker-scqps 100m (5%) 100m (5%) 100Mi (3%) 100Mi (3%) 36d
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
Resource Requests Limits
-------- -------- ------
cpu 650m (32%) 600m (30%)
memory 400Mi (14%) 600Mi (21%)
ephemeral-storage 0 (0%) 0 (0%)
・・・
#動作確認
まず、負荷をかけていない状態のCPU/メモリの使用量を確認します。
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8s-master 473m 23% 961Mi 34%
k8s-worker01 261m 13% 416Mi 15%
k8s-worker02 274m 13% 458Mi 16%
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 2m 10Mi
no-resource-quota-77d577889b-nhkvg 2m 10Mi
resource-quota-679594c947-j857k 3m 10Mi
resource-quota-679594c947-ls75g 3m 10Mi
requests(下限)はあらかじめ確保されているのかと思いましたが、負荷がない状態では、リソース制御をしている/していないともに変わらないですね。
##CPU
まずはCPUの動作を確認します。
リソース制御していないコンテナにログインして負荷をかけます。
$ kubectl exec -it no-resource-quota-77d577889b-mjfj6 /bin/bash
root@no-resource-quota-77d577889b-mjfj6:/# yes >/dev/null &
[1] 16
root@no-resource-quota-77d577889b-mjfj6:/# yes >/dev/null &
[2] 17
別ターミナルでリソースの使用量を確認します。
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 1556m 11Mi
no-resource-quota-77d577889b-nhkvg 2m 10Mi
resource-quota-679594c947-j857k 2m 10Mi
resource-quota-679594c947-ls75g 2m 10Mi
$ kubectl top node
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
k8s-master 436m 21% 1112Mi 40%
k8s-worker01 2000m 100% 496Mi 18%
k8s-worker02 281m 14% 537Mi 19%
worker01のCPUを使い切ってますね。
リソース制御しているコンテナのrequestsの値を確保はしていないです。
リソース制御しているコンテナ(nginx)にも同様にログインして負荷をかけます。
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 1548m 11Mi
no-resource-quota-77d577889b-nhkvg 2m 10Mi
resource-quota-679594c947-j857k 202m 10Mi
resource-quota-679594c947-ls75g 2m 10Mi
コンテナに設定したlimitsの値(200m)になっていますね。
リソース制御していないコンテナにかけている負荷を以下のようにしてプロセスをkillします。
root@no-resource-quota-77d577889b-mjfj6:/# jobs
[1]- Running yes > /dev/null &
[2]+ Running yes > /dev/null &
root@no-resource-quota-77d577889b-mjfj6:/# kill %1 %2
コンテナの負荷を確認します。
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 2m 10Mi
no-resource-quota-77d577889b-nhkvg 2m 10Mi
resource-quota-679594c947-j857k 201m 10Mi
resource-quota-679594c947-ls75g 2m 10Mi
リソース制御しているコンテナの負荷はlimitsの値のままで制御されていますね。
##メモリ
各コンテナにログインして、以下のように負荷をかけました。
root@no-resource-quota-77d577889b-mjfj6:/# /dev/null < $(yes) &
少し経つとプロセスがkillされてしまって、CPUのように同時に確認できませんでした。
おそらく、メモリを使い切るとプロセスがkillされてしまうのかなと。
正確には確認できませんでしたが、limitsがかかっていそうなことは確認できました。
- リソース制御していないコンテナに負荷をかけたとき
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 1076m 1660Mi
no-resource-quota-77d577889b-nhkvg 2m 10Mi
resource-quota-679594c947-j857k 2m 10Mi
resource-quota-679594c947-ls75g 2m 10Mi
- リソース制御しているコンテナに負荷をかけたとき
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
no-resource-quota-77d577889b-mjfj6 3m 10Mi
no-resource-quota-77d577889b-nhkvg 3m 10Mi
resource-quota-679594c947-j857k 202m 130Mi
resource-quota-679594c947-ls75g 3m 10Mi
#まとめ
概ねCPU/メモリのリソース制御の動作を確認できました。
requests(下限)は最初からその値が確保されているのではなく、負荷がかかったときにその値を保証するようですね。