HorizontalPodAutoscalerを外部指標を使わずにコンテナ単位で機能させる

# はじめに

KubernetesのHorizontalPodAutoscaler(以下HPA)は皆さん利用しているでしょうか。
アクセス量の上昇など、CPUやメモリの負荷上昇に耐えられるように構築するにはオートスケーリングは必須の機能です。

Kubernetes v1.27よりこの機能が強化され、コンテナ単位の指標使ったオートスケーリングを行うことが可能となりました。
外部指標を用いることなく、です。

:::note info
方法だけ見たい方は[こちら](#v127からのhpa)
:::

# これまでのHPA

これまでのHPAは、Pod単位のCPUやメモリに対する指標に対してのオートスケーリングでした。
Podにつき1つのコンテナであれば問題はないのですが、複数のコンテナがある場合には不向きです。

nginxとfluentdで構成されたマルチコンテナ構成のDeploymentがあるとします。

```deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app-deployment
spec:
  template:
    metadata:
      labels:
        app: test-app-deployment
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        resources:
          limits:
            cpu: 300m
            memory: 300Mi
          requests:
            cpu: 300m
            memory: 300Mi
      - name: fluentd
        image: fluentd:latest
        resources:
          limits:
            cpu: 700m
            memory: 700Mi
          requests:
            cpu: 700m
            memory: 700Mi
```

合計で `cpu: 1000m, memory: 1000Mi` のリソース量です。

これに対してHPAを設定します。
CPU利用率が60%を超えるとPodが増えるようにしてみましょう。

```hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: test-app-hpa
spec:
  scaleTargetRef:
    kind: Deployment
    apiVersion: apps/v1
    name: test-app-deployment
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
```

アクセス量の増大により負荷が高まり、nginxとfluentdの負荷が高まってきました。

| コンテナ名 | cpu limit | cpu usage | cpu rate |
|:-:|:-:|:-:|:-:|
| nginx | 300m | 250m | 0.833... |
| fluntd | 700m | 250m | 0.357... |

nginxはギリギリの状態です。
この状態でオートスケーリングが動作し、Podの数が増えるでしょうか。

**答えはNOです。**

Pod単位で計算されるため、CPU limitの合計値が1000mであるのに対し、CPU利用量の合計値は500mに留まっています。
50%の利用率では指標を上回らないため、Podの数が増えることはありません。
このまま負荷が増大すれば、遠からずPodは落ちてしまい、サービスが停止することになるでしょう。

少し極端な例ではありますが、複数のコンテナのHPAを行うことの難しさはわかってもらえたかと思います。
これまではこれを解決するためには外部指標を用意するほかありませんでした。

# v1.27からのHPA

流石にこの状況は煩わしいと思ったのでしょう。
HPAContainerMetricsという機能がHPAに生えました。

実のところv1.20からalpha機能として存在していたのですが、v1.27よりbeta機能となり、対応するフィーチャーゲートがデフォルトで有効になりました。

https://kubernetes.io/blog/2023/05/02/hpa-container-resource-metric/

v1.27以降のKubernetesであれば利用できますし、GKEでもデフォルトで有効化されているのを確認しています。

HPAContainerMetricsに対応したHPAは次のようになります。

```hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: test-app-hpa
spec:
  scaleTargetRef:
    kind: Deployment
    apiVersion: apps/v1
    name: test-app-deployment
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: ContainerResource
    containerResource:
      name: cpu
      container: resty
      target:
        type: Utilization
        averageUtilization: 60
  - type: ContainerResource
    containerResource:
      name: cpu
      container: fluentd
      target:
        type: Utilization
        averageUtilization: 60
```

この形で先ほどの例を考えてみましょう。

| コンテナ名 | cpu limit | cpu usage | cpu rate |
|:-:|:-:|:-:|:-:|
| nginx | 300m | 250m | 0.833... |
| fluntd | 700m | 250m | 0.357... |

nginxのCPU利用率は 250m / 300m = 0.833... となり、60%を超えています。
よって、Podの増加がトリガーされます！

もちろんmemoryも指定できます。以前よりも格段に柔軟なオートスケーリングを構築できるようになりました。
その他パラメータの細かいことは公式ドキュメントを確認しましょう。

https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.27/#horizontalpodautoscaler-v2-autoscaling

なお、GKEではUIがまだ対応していません。(2024/04/16現在)
エラーになっているように見えますが、HPA自体は問題なく機能します。
この辺りを理解した上で利用しましょう。
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147093/1ebebf47-9145-9e53-5eb6-1fe4c01ba4de.png)


# おわりに

v1.20の頃にalpha版で存在を確認してからずっと待ち望んでいた機能でした！
いつの間にか使えるようになっていたので驚きましたが、これによってやりたかったことが簡単に解決できるようになりそうです。
外部指標は便利ですが、それなりに下準備も必要なので、サッとできるようになるのは嬉しいですね。

---

インティメート・マージャーでは、新卒から中途採用まで幅広く採用募集中です！
記事を読んで弊社に興味を持ってくれた方は、下記より採用情報をチェックしていただけるとうれしいです！

https://recruit.intimatemerger.com/