PodのLimits決めについての試行錯誤

## 初めに
EKS(k8s)で環境を作成する際、podを作成したのは良いが、高負荷時にPodの水平スケールをさせるHPAの設定をするうえで、そもそも作成したPodが使ってよいCPUとメモリのリミットの値をいくつにすればよいか大変悩みました。
この記事ではその時のリミットの割り出し方を自分の為の備忘録的なものとして記載しました。

私は、EKS及びKuberneteusの初学者です。
その為、下記に記載した内容は他にも良い方法があったりそもそも考慮が足りてない点も多々あるかと思いますがよろしくお願いします。
## １. ノード1台当たりの使用できるリソース把握

方法は下記のコマンドを使用して調べる。

```bash
kubectl get node <node名> -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEMORY:.status.allocatable.memory,STORAGE:.status.allocatable.ephemeral-storage
```

今回の場合は、以下の数値が求められた。
```bash
kubectl get node ip-XX-XXX-XXX-XXX.ap-northeast-1.compute.internal -o custom-columns=NAME:.metadata.name,CPU:.status.allocatable.cpu,MEMORY:.status.allocatable.memory,STORAGE:.status.allocatable.ephemeral-storage
NAME                                                CPU     MEMORY      STORAGE
ip-XX-XXX-XXX-XXX.ap-northeast-1.compute.internal   1930m   7230336Ki   60762444084
```
つまりノード一台当たりのk8sで使える量は以下である。
<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>1930m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>7062Mi(7230336Ki)</td>
    </tr>
</table>

ノード1台で使用されているkube-systemとCloudwatch系の使用率はtopコマンドで調査した結果概ね以下の値。
<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>36m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>517Mi</td>
    </tr>
</table>

その為、1ノードあたり自由に使える値は以下となる。
<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>1894m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>6545Mi</td>
    </tr>
</table>

## ２. Podで使用されている必要最低限のリソース量を把握

deployment内にてリソースリクエストとリミットを設定していなければ、現状でpodが立ち上がってる自然な状態がPodが動作に必要な最低限のリソースと言える。
```bash
kubectl top po -A
```

今回の場合は以下の数値が求められた
```bash
kubectl top po 
NAME                     CPU(cores)   MEMORY(bytes)              
XXXXXXXXXXXX-pod         12m          131Mi           
XXXXXXXXXXXX-pod         12m          150Mi           
XXXXXXXXXXXX-pod         11m          149Mi    
```

上記を参考にすると、必要最低限のリソースは若干高めに見積もって概ね以下の値程度だと考えられる。
つまり以下の値よりも小さい値を設定してしまうとPodの動作に支障をきたす。
<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>15m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>150Mi</td>
    </tr>
</table>

## ３. pod数、想定される負荷、1つのpodでどれだけ処理したいかを把握。
■Pod数
ノードは3台稼働がk8sとしての基本な為、podが各ノードに均等に配置され冗長化されるためにも3podは最低でもあるべきであると考える。
※参考にさせていただきました。

https://qiita.com/ntoreg/items/ec6f1eca87ba5c5c0399

■想定される負荷
仮に1日100万アクセスしてくるWEBページを作成する場合
100万を1日から1秒まで割り11.6 rps（リクエスト/秒）と考えておく。

■1つのpodでどれだけさばきたいか
想定されているアクセス数は1日当たり100万人、1秒あたり11.6人。
つまり3podある場合はpod1つにつき1秒当たり3.9人処理出来る必要がある。


ここまでの情報を整理すると以下となる。
<table>
<tr>
<td><strong>3ノードの合計pod数</strong></td>
<td>3</td>
</tr>
<td><strong>秒間当たりのアクセス数</strong></td>
<td>11.6人</td>
</tr>
<tr>  
<td><strong>1podでさばきたい数</strong></td>
<td>3.9 rps</td>
</tr>    
</table>

## ４. Podあたりのリミットを決める
項番1での調査から今回使用するノードは1ノードあたり以下の許容量がある。

<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>1894m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>6545Mi</td>
    </tr>
</table>

上記を踏まえてpod1つ当たりのリミットは1ノードの１割程度としておく。
<table>
    <tr>
      <td><strong>CPU</strong></td>
      <td>200m</td>
    </tr>
      <td><strong>メモリ</strong></td>
      <td>600Mi</td>
    </tr>
</table>

理由としては以下の点が考えることが出来る。

①障害でノードが1つダウンした場合に、生きている残りの2ノードにpodが割り振られるがその際のリミットの使用量を元からいたpodのリミットと合わせても2割程度とできる為ノード自体に与える影響が少ない。
②仮にHPAでオートスケールしてpod数が2倍になって6つpodができた後にさらにリミットに張り付いても3ノード全体の使用率としては2割程度となる為、他環境への影響を抑えられる。
③ほかの用途での使用も考えてノードのスペックをフルには使いたくないという理由もある。

## ５. 負荷検証
設定したリミットで問題がないかを調べる試験を行う。

以下はその段取りである。
①pod数を1つにする。
②項番4で決めた値でリミットをdeploymentに記載する。
③秒間3.9人がアクセスしてきた想定のリソース利用状況を調べる。これにより、基準となるリソース使用量を把握できる。
④過剰に負荷をかけ設定したリミットで処理できる限界を調べる。この作業を行うことで1つのpodで処理できる最大アクセス数が割り出せる。

上記の試験の結果、以下の情報を知ることが出来る。
・想定される平常時の負荷状況
・１つのPodの処理の限界

これらを踏まえたうえで、ようやくHPAの設定などを考えることが出来ると思われる。

## まとめ
Kuberneteusは便利ではありますが学習コストが高い為、ハードルが高めな印象です。
しかし学習しないと始まらない為、今後も精進してまいります。