【Kubernetes】Horizontal Pod Autoscalerやってみる

スポンサーリンク

はじめに

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

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

Horizontal Pod Autoscalerとは

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

Horizontal Pod Autoscaling
InKubernetes,aHorizontalPodAutoscalerautomaticallyupdatesaworkloadresource(suchasaDeploymentorStatefulSet),withtheaimofautomaticallyscalingtheworkloadtomatchdem...

使えるメトリクス

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

マニフェスト

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

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-sample
spec:
  scaleTargetRef: # スケール対象
    apiVersion: apps/v1
    kind: Deployment
    name: deployment-sample
  minReplicas: 1 # 最小レプリカ数
  maxReplicas: 10 # 最大レプリカ数
  metrics: # スケール条件
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50 # CPUの利用率が50% (resource requestを100%とする)
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300 # スケールインするまでの待ち時間
      policies:
      - type: Percent # 15秒ごとに100%分のレプリカをスケールイン(最小までスケールイン)
        value: 100 # 現在動いているレプリカ数を100%
        periodSeconds: 15
    scaleUp:
      stabilizationWindowSeconds: 0 # スケールアウトするまでの待ち時間(0は即時)
      policies:
      - type: Percent # 15秒ごとに100%分のレプリカをスケールアウト
        value: 100 # 現在動いているレプリカ数を100%
        periodSeconds: 15
      - type: Pods # 15秒ごとに4レプリカをスケールアウト
        value: 4
        periodSeconds: 15
      selectPolicy: Max # 追加するレプリカ数が多い方を採用

レプリカ数の計算方法

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

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

試してみる

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

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

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

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

Releases · kubernetes-sigs/metrics-server
ScalableandefficientsourceofcontainerresourcemetricsforKubernetesbuilt-inautoscalingpipelines.-kubernetes-sigs/metrics-server

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

      -- 省略 --

    protocol: TCP
    targetPort: https
  selector:
    k8s-app: metrics-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    k8s-app: metrics-server
  name: metrics-server
  namespace: kube-system
spec:
  selector:
    matchLabels:
      k8s-app: metrics-server
  strategy:
    rollingUpdate:
      maxUnavailable: 0
  template:
    metadata:
      labels:
        k8s-app: metrics-server
    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls # 追記する
        image: k8s.gcr.io/metrics-server/metrics-server:v0.5.2
        imagePullPolicy: IfNotPresent
        livenessProbe:
          failureThreshold: 3

      -- 省略 --

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

kubectl apply -f components.yaml

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

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

デモアプリのデプロイ

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

Horizontal Pod Autoscalerウォークスルー
HorizontalPodAutoscalerは、Deployment、ReplicaSetまたはStatefulSetといったレプリケーションコントローラ内のPodの数を、観測されたCPU使用率(もしくはベータサポートの、アプリケーションによって提供されるその他のメトリクス)に基づいて自動的にスケールさせます。このド...

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: php-apache
spec:
  selector:
    matchLabels:
      run: php-apache
  replicas: 1
  template:
    metadata:
      labels:
        run: php-apache
    spec:
      containers:
      - name: php-apache
        image: k8s.gcr.io/hpa-example
        ports:
        - containerPort: 80
        resources:
          limits:
            cpu: 500m
          requests:
            cpu: 200m

Serviceも用意します。

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

apiVersion: v1
kind: Service
metadata:
  name: php-apache
  labels:
    run: php-apache
spec:
  ports:
  - port: 80
  selector:
    run: php-apache

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

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

HPAの作成

次にHPAを作成します。

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

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: php-apache-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: php-apache
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 30
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 30
      policies:
      - type: Percent
        value: 50
        periodSeconds: 30
    scaleUp:
      stabilizationWindowSeconds: 0
      policies:
      - type: Percent
        value: 40
        periodSeconds: 30
      - type: Pods
        value: 2
        periodSeconds: 30
      selectPolicy: Max

HPAを作成します。

kubectl apply -f hpa.yaml

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

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

負荷をかけてみる

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

kubectl 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を確認すると、ターゲットを超えていることがわかります。

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

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

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

負荷を止めてみる

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

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

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

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

❯ kubectl get deploy -w
NAME         READY   UP-TO-DATE   AVAILABLE   AGE

...

php-apache   5/5     5            5           20m
php-apache   5/2     5            5           21m
php-apache   2/2     2            2           21m
php-apache   2/1     2            2           22m
php-apache   1/1     1            1           22m

参考

タイトルとURLをコピーしました