[Kubernetes]リソース制御の動作を確認する 2

#はじめに
[前回](https://qiita.com/dingtianhongjie/items/9401d6e4b8ec6e14fae1)はリソース制御の基本的な動作を確認しました。
今回は前回に続いて、こういう場合はどうなるんだろう？ということを実際に確認してみたいと思います。
なお、今回はCPUだけに絞って検証していきます。

#リソース不足の場合
今回の検証環境のworkerノードは2vCPU（2000m）搭載しています。
ここにNginxとRedis 2つのコンテナを持つPodをデプロイしますが、requestsとlimitsを以下の図のように設定します。
requests（下限）の合計が2200mとなり、workerノードのリソースを超えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/65027f52-0e05-5b62-6721-638c69bd3e88.png)

このPodをデプロイします。マニフェストは[前回](https://qiita.com/dingtianhongjie/items/9401d6e4b8ec6e14fae1)と同様で、requestsとlimitsの値が異なるだけです。

```
$ kubectl apply -f nginx_redis-quota.yaml
deployment.apps/resource-quota created
$ kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
no-resource-quota-77d577889b-2lsck   2/2     Running   0          45s
no-resource-quota-77d577889b-mlgvr   2/2     Running   0          46s
resource-quota-6bfdcb475d-5hqn5      0/2     Pending   0          9s
resource-quota-6bfdcb475d-fjk29      0/2     Pending   0          9s
```

PodがPendingとなりました。詳細を確認します。

```
$ kubectl describe pod resource-quota-6bfdcb475d-5hqn5
Name:           resource-quota-6bfdcb475d-5hqn5
・・・
Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  36s (x2 over 36s)  default-scheduler  0/3 nodes are available: 3 Insufficient cpu.
```

CPUが足りなくてスケジューリングできていませんね。
前回確認した結果だとrequestsの値は、無負荷状態では確保されていなかったですが、requestsの合計値がノードのvCPUを超えるとスケジューリングできないようですね。

#リソース競合の場合
requestsとlimitsの値を変更して、「requestsの合計 ＜ vCPU ＜ limitsの合計」としました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/4014f7e1-2115-aafe-dc1c-31124c639bd7.png)

```
$ kubectl apply -f nginx_redis-quota.yaml
deployment.apps/resource-quota configured
$ kubectl get pod
NAME                                 READY   STATUS    RESTARTS   AGE
no-resource-quota-77d577889b-2lsck   2/2     Running   0          32m
no-resource-quota-77d577889b-mlgvr   2/2     Running   0          32m
resource-quota-7549bdf4df-845dw      2/2     Running   0          19s
resource-quota-7549bdf4df-r9rc6      2/2     Running   0          10s
```

設定値を確認しておきます。

```
$ 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-resource-quota-77d577889b-mlgvr    0 (0%)        0 (0%)        0 (0%)           0 (0%)         40m
  default                     resource-quota-7549bdf4df-845dw       1500m (75%)   2500m (125%)  300Mi (10%)      500Mi (18%)    8m24s
  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                1850m (92%)  2600m (130%)
  memory             400Mi (14%)  600Mi (21%)
  ephemeral-storage  0 (0%)       0 (0%)
```

Requestsの設定値は92％ですが、Limitsは130％とvCPUの値を超えていますね。

##動作確認
各コンテナにログインして、CPUに負荷をかけてCPUの使用率を確認します。
ただ、Pod単位でしか負荷がわからないので、Podを作り直すことにしました。以下のように1Pod/1コンテナにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492530/9177b907-730c-64a8-f3a4-ba8793086453.png)

リソース制御しているPodはReplicaSetをスケールしても良かったんですが、設定値が異なる場合にどのようになるのか確認したかったので、別のDeploymentにしました。

```
$ kubectl get pod -o wide
NAME                                 READY   STATUS    RESTARTS   AGE   IP               NODE           NOMINATED NODE   READINESS GATES
no-resource-quota-77d577889b-2lsck   2/2     Running   2          23h   192.168.69.252   k8s-worker02   <none>           <none>
no-resource-quota-77d577889b-mlgvr   2/2     Running   2          23h   192.168.79.77    k8s-worker01   <none>           <none>
resource-quota1-557b598fc9-2lqqg     1/1     Running   1          17h   192.168.79.66    k8s-worker01   <none>           <none>
resource-quota1-557b598fc9-8bcdr     1/1     Running   1          17h   192.168.69.205   k8s-worker02   <none>           <none>
resource-quota2-565c7b64fc-8tr5r     1/1     Running   1          17h   192.168.79.76    k8s-worker01   <none>           <none>
resource-quota2-565c7b64fc-qtng4     1/1     Running   1          17h   192.168.69.251   k8s-worker02   <none>           <none>
```

まずはrequests:500m/limits:1000mのPodに負荷をかけます。

```
$ kubectl exec -it resource-quota1-557b598fc9-2lqqg /bin/bash
root@resource-quota1-557b598fc9-2lqqg:/# yes >/dev/null &
[1] 12
root@resource-quota1-557b598fc9-2lqqg:/# yes >/dev/null &
[2] 13
```

CPU使用率を確認します。

```
$ kubectl top pod
NAME                                 CPU(cores)   MEMORY(bytes)
no-resource-quota-77d577889b-2lsck   2m           11Mi
no-resource-quota-77d577889b-mlgvr   2m           11Mi
resource-quota1-557b598fc9-2lqqg     992m         2Mi
resource-quota1-557b598fc9-8bcdr     0m           1Mi
resource-quota2-565c7b64fc-8tr5r     0m           1Mi
resource-quota2-565c7b64fc-qtng4     0m           1Mi
```

ほぼlimitsの値になってますね。

次にrequests:1000m/limits:1500mのPodに同様に負荷をかけ、CPU使用率を確認します。

```
$ kubectl top pod
NAME                                 CPU(cores)   MEMORY(bytes)
no-resource-quota-77d577889b-2lsck   1m           11Mi
no-resource-quota-77d577889b-mlgvr   1m           11Mi
resource-quota1-557b598fc9-2lqqg     625m         2Mi
resource-quota1-557b598fc9-8bcdr     0m           1Mi
resource-quota2-565c7b64fc-8tr5r     1251m        2Mi
resource-quota2-565c7b64fc-qtng4     0m           1Mi
```

どちらもrequestsを超えて同じような比率でリソースを分け合っていますね。
なお、この時点でノードのvCPUは使い切っています。

```
$ kubectl top node
NAME           CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
k8s-master     209m         10%    1007Mi          36%
k8s-worker01   2000m        100%   484Mi           17%
k8s-worker02   129m         6%     525Mi           19%
```

さらに、制限をかけていないPodにログインして同様に負荷をかけ、CPU使用率を確認します。

```
$ kubectl top pod
NAME                                 CPU(cores)   MEMORY(bytes)
no-resource-quota-77d577889b-2lsck   2m           11Mi
no-resource-quota-77d577889b-mlgvr   4m           11Mi
resource-quota1-557b598fc9-2lqqg     626m         2Mi
resource-quota1-557b598fc9-8bcdr     0m           1Mi
resource-quota2-565c7b64fc-8tr5r     1280m        2Mi
resource-quota2-565c7b64fc-qtng4     0m           1Mi
```

5分ほど待ってみましたが、制限をかけていないPod（no-resource-quota-77d577889b-mlgvr）は使用率がほとんど上がりませんでした。

#まとめ
[前回](https://qiita.com/dingtianhongjie/items/9401d6e4b8ec6e14fae1)は、「リソース制御をしていないPod -> リソース制御をしているPod」の順に負荷をかけました。リソース制御をしていないPodだけでCPUを使い切っている状態でリソース制御しているPodに負荷をかけると、requests（下限）ではなく、limits（上限）までPodはCPUを割り当てられました。
ということは、リソースの割り当ては早い順ではなく、リソース制御の設定値（requestsだけでなくlimitsも）が優先されて、リソース制御していないPodは他のPodの上限値まで割り当てたあとの余りのリソースが割り当てられるということになりますね。