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

#はじめに
今回はコンテナのリソース制御の動作を確認したいと思います。
コンピュータリソースとして制御できるものは、CPU、メモリ、GPUがあります。

>[Compute Resource Quota](https://kubernetes.io/docs/concepts/policy/resource-quotas/#compute-resource-quota)

GPUは用意できないので、CPU、メモリのみ確認します。

#設定

リソース制御はコンテナごとに定義します。CPU、メモリごとに「requests」と「limits」で値を指定します。
requestsはリソースの下限、limitsは上限です。

CPUは「1(v)CPU=1000m」として値を指定します。実際のCPUのクロック周波数とは関係ないので、注意が必要です。
1コアを指定したい場合は、「1000m」とします。

今回は以下のマニフェストを用意しました。

```nginx_redis-quota.yaml
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（下限）は最初からその値が確保されているのではなく、負荷がかかったときにその値を保証するようですね。