【Kubernetes】Horizontal Pod Autoscalerやってみる

2022.10.22
2024.03.24
Kubernetes
Horizontal Pod Autoscaler

はじめに

KubernetesのHPA(Horizontal Pod Autoscaler)について、ざっくりまとめて実際に試してみたいと思います。

APIバージョンはautoscaling/v2を想定しています。

Horizontal Pod Autoscalerとは

Horizontal Pod Autoscalerは、DeploymentやStatefulSetなどのPod数を、メトリクスをもとに自動的にスケールさせることができます。

Horizontal Pod Autoscaling

Horizontal Pod Autoscaling

In Kubernetes, a HorizontalPodAutoscaler automatically updates a workload resource (such as a Deployment or StatefulSet), with the aim of automatically scaling the workload to match demand. Horizontal scaling means that the response to increased load is to deploy more Pods. This is different from vertical scaling, which for Kubernetes would mean assigning more resources (for example: memory or CPU) to the Pods that are already running for the workload.

使えるメトリクス

  • リソースメトリクス(metrics.k8s.io)
    • metrics-serverから取得できるCPUやメモリなどのメトリクス
  • カスタムメトリクス(custom.metrics.k8s.io)
    • メトリクスサーバーで独自に定義したメトリクス
  • 外部メトリクス(external.metrics.k8s.io)
    • Kubernetes外部のメトリクス

マニフェスト

HPAのマニフェストの例は下記の通りです。

1apiVersion: autoscaling/v2
2kind: HorizontalPodAutoscaler
3metadata:
4  name: hpa-sample
5spec:
6  scaleTargetRef: # スケール対象
7    apiVersion: apps/v1
8    kind: Deployment
9    name: deployment-sample
10  minReplicas: 1 # 最小レプリカ数
11  maxReplicas: 10 # 最大レプリカ数
12  metrics: # スケール条件
13  - type: Resource
14    resource:
15      name: cpu
16      target:
17        type: Utilization
18        averageUtilization: 50 # CPUの利用率が50% (resource requestを100%とする)
19  behavior:
20    scaleDown:
21      stabilizationWindowSeconds: 300 # スケールインするまでの待ち時間
22      policies:
23      - type: Percent # 15秒ごとに100%分のレプリカをスケールイン(最小までスケールイン)
24        value: 100 # 現在動いているレプリカ数を100%
25        periodSeconds: 15
26    scaleUp:
27      stabilizationWindowSeconds: 0 # スケールアウトするまでの待ち時間(0は即時)
28      policies:
29      - type: Percent # 15秒ごとに100%分のレプリカをスケールアウト
30        value: 100 # 現在動いているレプリカ数を100%
31        periodSeconds: 15
32      - type: Pods # 15秒ごとに4レプリカをスケールアウト
33        value: 4
34        periodSeconds: 15
35      selectPolicy: Max # 追加するレプリカ数が多い方を採用

レプリカ数の計算方法

必要なレプリカ数の計算方法は下記の通りです。少数は切り上げになります。

1必要なレプリカ数 = 現在のレプリカ数 * ( 現在のメトリクス / ターゲットメトリクス )

試してみる

ローカルでリソースメトリクスを利用したシンプルなHPAを試してみたいと思います。

メトリクスサーバーの導入

まずはmetrics-serverを導入します。

下記からcomponents.yamlを取得します。

Releases · kubernetes-sigs/metrics-server

Releases · kubernetes-sigs/metrics-server

Scalable and efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines. - kubernetes-sigs/metrics-server

Docker Desktopで導入する場合、このままではPodが起動しないので下記のcomponents.yamlの下記の部分に--kubelet-insecure-tlsを追記します。

1      -- 省略 --
2
3    protocol: TCP
4    targetPort: https
5  selector:
6    k8s-app: metrics-server
7---
8apiVersion: apps/v1
9kind: Deployment
10metadata:
11  labels:
12    k8s-app: metrics-server
13  name: metrics-server
14  namespace: kube-system
15spec:
16  selector:
17    matchLabels:
18      k8s-app: metrics-server
19  strategy:
20    rollingUpdate:
21      maxUnavailable: 0
22  template:
23    metadata:
24      labels:
25        k8s-app: metrics-server
26    spec:
27      containers:
28      - args:
29        - --cert-dir=/tmp
30        - --secure-port=4443
31        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
32        - --kubelet-use-node-status-port
33        - --metric-resolution=15s
34        - --kubelet-insecure-tls # 追記する
35        image: k8s.gcr.io/metrics-server/metrics-server:v0.5.2
36        imagePullPolicy: IfNotPresent
37        livenessProbe:
38          failureThreshold: 3
39
40      -- 省略 --

metrics-serverをデプロイします。

1kubectl apply -f components.yaml

下記のようにPodが実行されていれば完了です。

1❯ kubectl -n kube-system get pod | grep metrics-server
2metrics-server-658867cdb7-j7r8p          1/1     Running   0          4m35s

デモアプリのデプロイ

デモアプリには、下記で使われているk8s.gcr.io/hpa-exampleイメージを利用します。こちらはCPU負荷の高い演算を行うイメージになっています。

Horizontal Pod Autoscalerウォークスルー

Horizontal Pod Autoscalerウォークスルー

Horizontal Pod Autoscalerは、Deployment、ReplicaSetまたはStatefulSetといったレプリケーションコントローラー内のPodの数を、観測されたCPU使用率(もしくはベータサポートの、アプリケーションによって提供されるその他のメトリクス)に基づいて自動的にスケールさせます。 このドキュメントはphp-apacheサーバーに対しHorizontal Pod Autoscalerを有効化するという例に沿ってウォークスルーで説明していきます。Horizontal Pod Autoscalerの動作についてのより詳細な情報を知りたい場合は、Horizontal Pod Autoscalerユーザーガイドをご覧ください。 始める前に この例ではバージョン1.2以上の動作するKubernetesクラスターおよびkubectlが必要です。 Metrics APIを介してメトリクスを提供するために、Metrics serverによるモニタリングがクラスター内にデプロイされている必要があります。 Horizontal Pod Autoscalerはメトリクスを収集するためにこのAPIを利用します。metrics-serverをデプロイする方法を知りたい場合はmetrics-server ドキュメントをご覧ください。 Horizontal Pod Autoscalerで複数のリソースメトリクスを利用するためには、バージョン1.6以上のKubernetesクラスターおよびkubectlが必要です。カスタムメトリクスを使えるようにするためには、あなたのクラスターがカスタムメトリクスAPIを提供するAPIサーバーと通信できる必要があります。 最後に、Kubernetesオブジェクトと関係のないメトリクスを使うにはバージョン1.10以上のKubernetesクラスターおよびkubectlが必要で、さらにあなたのクラスターが外部メトリクスAPIを提供するAPIサーバーと通信できる必要があります。 詳細についてはHorizontal Pod Autoscaler user guideをご覧ください。 php-apacheの起動と公開 Horizontal Pod Autoscalerのデモンストレーションのために、php-apacheイメージをもとにしたカスタムのDockerイメージを使います。 このDockerfileは下記のようになっています。 FROM php:5-apache COPY index.php /var/www/html/index.php RUN chmod a+rx index.php これはCPU負荷の高い演算を行うindex.phpを定義しています。 <?php $x = 0.0001; for ($i = 0; $i <= 1000000; $i++) { $x += sqrt($x); } echo "OK!"; ?> まず最初に、イメージを動かすDeploymentを起動し、Serviceとして公開しましょう。 下記の設定を使います。 application/php-apache.yaml apiVersion: apps/v1 kind: Deployment metadata: name: php-apache spec: selector: matchLabels: run: php-apache template: metadata: labels: run: php-apache spec: containers: - name: php-apache image: registry.

deployment.yamlは下記の通りです。

1apiVersion: apps/v1
2kind: Deployment
3metadata:
4  name: php-apache
5spec:
6  selector:
7    matchLabels:
8      run: php-apache
9  replicas: 1
10  template:
11    metadata:
12      labels:
13        run: php-apache
14    spec:
15      containers:
16      - name: php-apache
17        image: k8s.gcr.io/hpa-example
18        ports:
19        - containerPort: 80
20        resources:
21          limits:
22            cpu: 500m
23          requests:
24            cpu: 200m

Serviceも用意します。

service.yamlは下記の通りです。

1apiVersion: v1
2kind: Service
3metadata:
4  name: php-apache
5  labels:
6    run: php-apache
7spec:
8  ports:
9  - port: 80
10  selector:
11    run: php-apache

アプリをデプロイします。

1kubectl apply -f deployment.yaml
2kubectl apply -f service.yaml

HPAの作成

次にHPAを作成します。

hpa.yamlは下記の通りです。スケールしているのを確認したいので、スケールインとスケールアウトの設定を緩やかにしています。

1apiVersion: autoscaling/v2
2kind: HorizontalPodAutoscaler
3metadata:
4  name: php-apache-hpa
5spec:
6  scaleTargetRef:
7    apiVersion: apps/v1
8    kind: Deployment
9    name: php-apache
10  minReplicas: 1
11  maxReplicas: 10
12  metrics:
13  - type: Resource
14    resource:
15      name: cpu
16      target:
17        type: Utilization
18        averageUtilization: 30
19  behavior:
20    scaleDown:
21      stabilizationWindowSeconds: 30
22      policies:
23      - type: Percent
24        value: 50
25        periodSeconds: 30
26    scaleUp:
27      stabilizationWindowSeconds: 0
28      policies:
29      - type: Percent
30        value: 40
31        periodSeconds: 30
32      - type: Pods
33        value: 2
34        periodSeconds: 30
35      selectPolicy: Max

HPAを作成します。

1kubectl apply -f hpa.yaml

作成したHPAを確認すると、ターゲットのメトリクスに対して、現状のどのくらいなのかを確認できます。(現状は負荷をかけていないので0%です)

1❯ kubectl get hpa
2NAME             REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
3php-apache-hpa   Deployment/php-apache   0%/50%    1         10        1          65s

負荷をかけてみる

負荷をかけるリクエストを送り続けるPodを起動して、負荷をかけてみます。

1kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://php-apache; done"

HPAを確認すると、ターゲットを超えていることがわかります。

1❯ kubectl get hpa
2NAME             REFERENCE               TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
3php-apache-hpa   Deployment/php-apache   251%/30%   1         10        1          14m

スケールアウトはすぐに反映され、レプリカ数が増えて行くのが確認できます。

1❯ kubectl get deploy -w
2NAME         READY   UP-TO-DATE   AVAILABLE   AGE
3php-apache   1/1     1            1           12m
4php-apache   1/3     1            1           14m
5php-apache   2/3     3            2           14m
6php-apache   3/3     3            3           14m
7php-apache   3/5     3            3           15m
8php-apache   3/5     5            3           15m
9php-apache   4/5     5            4           15m
10php-apache   5/5     5            5           15m
11php-apache   5/7     5            5           16m
12php-apache   5/7     7            5           16m
13php-apache   6/7     7            6           16m
14php-apache   7/7     7            7           16m
15php-apache   7/10    7            7           17m
16php-apache   7/10    10           7           17m
17php-apache   8/10    10           8           17m
18php-apache   9/10    10           9           17m
19php-apache   10/10   10           10          17m

負荷を止めてみる

負荷をかけていたPodを停止させて、負荷を止めます。

HPAを確認するとターゲットのメトリクスが少なくなったことが確認できます。

1❯ kubectl get hpa -w
2NAME             REFERENCE               TARGETS   MINPODS   MAXPODS   REPLICAS   AGE
3php-apache-hpa   Deployment/php-apache   31%/30%   1         10        10         19m
4php-apache-hpa   Deployment/php-apache   0%/30%    1         10        10         20m

負荷を止めてからしばらくすると、レプリカ数が減っていくことも確認できます。

1❯ kubectl get deploy -w
2NAME         READY   UP-TO-DATE   AVAILABLE   AGE
3
4...
5
6php-apache   5/5     5            5           20m
7php-apache   5/2     5            5           21m
8php-apache   2/2     2            2           21m
9php-apache   2/1     2            2           22m
10php-apache   1/1     1            1           22m

参考

Support

\ この記事が役に立ったと思ったら、サポートお願いします! /

buy me a coffee
Share

Profile

author

Masa

都内のIT企業で働くエンジニア
自分が学んだことをブログでわかりやすく発信していきながらスキルアップを目指していきます!

buy me a coffee