【Kubernetes】Horizontal Pod Autoscalerやってみる
はじめに
KubernetesのHPA(Horizontal Pod Autoscaler)について、ざっくりまとめて実際に試してみたいと思います。
APIバージョンはautoscaling/v2
を想定しています。
Horizontal Pod Autoscalerとは
Horizontal Pod Autoscalerは、DeploymentやStatefulSetなどのPod数を、メトリクスをもとに自動的にスケールさせることができます。
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
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は、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
参考
- Horizontal Pod Autoscalerウォークスルー | Kubernetes
- HorizontalPodAutoscaler Walkthrough | Kubernetes
- Horizontal Pod Autoscaling | Kubernetes
- kubernetes-sigs/metrics-server: Scalable and efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines.
- design-proposals-archive/monitoring_architecture.md at main · kubernetes/design-proposals-archive
- kubectl top pod responding with "Metrics not available for pod xxx" · Issue #1061 · kubernetes-sigs/metrics-server