35
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Kuberentes の水平オートスケール

Last updated at Posted at 2018-05-28

この記事は HPA v1(v2beta1) ベースとなっており、現在(2021/12)では非推奨の方法となっております。最新の内容は https://qiita.com/shmurata/items/e6bd8c56f3e4f9a8e384 にまとめていますのでこちらを参照ください

この記事ではKuberentesのオートスケール機能の一つであるHorizontal Pod Autoscalerについてまとめていきます。

Horizontal Pod Autoscaler

Horizontal Pod AutoscalerはReplicationControllerまたはDeployment, ReplicaSetのPodの数を自動的にスケールします。スケールの判定に利用するメトリクスはCPUやカスタムメトリクスを利用することができます。
Horizontal Pod AutoscalerはKubernetes APIオブジェクトとコントローラとして実装されています。このコントローラは定期的にユーザによって設定されたしきい値とメトリクスの値を比較しReplica数を調整します。

Horizontal Pod Autoscalerの動き

Horizontal Pod Autoscalerのコントローラ(HorizontalPodAutoscalerController)はControllerManagerにあるコントローラの一つとして実装されていて、デフォルトではコントロールループ(メトリクスの値を収集してReplica数を調整する処理のループ)は30秒間隔で周期しています。この間隔はControllerManagerの--horizontal-pod-autoscaler-sync-periodフラグで変更することができます。
このコントローラが扱うメトリクスはPod一つの単位で生成されるメトリクス(例:PodのCPU使用率)と全体で一つのメトリクス(例:アプリケーション全体のリクエスト数)があります。Pod一つの単位で生成されるメトリクス(per-pod metrics)には注意が必要で、この場合は一部のPodのメトリクスが取得できない場合は考慮しなければいけません。
HorizontalPodAutoscalerControllerはRequestが設定されていない場合はなんのアクションもしません。詳細は
autoscalerアルゴリズムに記載されています。

HorizontalPodAutoscalerControllerがメトリクスを収集する方法は2種類あります。一つは直接Heapsterにアクセスして取得する方法で、もう一つはREST clientでアクセスする方法です。直接HeapsterにアクセスするときにはAPIサーバのServiceProxySubResourceを通してアクセスします。このときHeapsterはkube-system名前空間で動作するようにデプロイされている必要があります。REST clientでのアクセスについては後述するカスタムメトリクスについてのところで記載します。

API version

HorizontalPodAutoscalerはautoscaling API Groupのオブジェクトです。2018/5/9時点ではCPU使用率のautoscalingのみがstableとなっていてautoscaling/v1で提供されています。メモリ使用率によるスケールやカスタムメトリクスでのスケールはautoscaling/v2beta1で提供されています。autoscaling/v2 のリリース時期については現在はまだ未確定のようです。

利用方法

Heapsterが既にデプロイされている環境なら以下のHorizontalPodAutoscalerオブジェクトを作成するだけで利用することができます。

apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: WebFrontend
  namespace: default
spec:
  # オートスケールさせるターゲットを設定
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: WebFrontend
  # downscaleする最小値
  minReplicas: 2
  # upscaleする最大値
  maxReplicas: 5
  # すべてのPodの平均CPU使用率の目標値(%の値を設定する)
  targetCPUUtilizationPercentage: 70

ここで重要なのはHorizontalPodAutoscalerControllerはメトリクスを収集してすべてのPodの平均値が指定した値(targetCPUUtilizationPercentage)に近づくようにReplicasを調整するということです。つまり上記の設定であれば平均CPU使用率が70%を超えていたらupscaleし、70%に届かない場合はdownscaleします。Pod数の計算式は以下になります。

TargetNumOfPods = ceil(sum(CurrentPodsCPUUtilization) / targetCPUUtilizationPercentage)

利用する上での注意事項

ReplicationControllerの場合はローリングアップデートするとHorizontalPodAutoScalerの対象から外れる

現在は殆ど使っている人はいないと思いますがHorizontalPodAutoScalerをReplicationControllerで利用している場合には注意が必要です。kubectl rolling-updateコマンドなどでReplicationControllerのローリングアップデートを行うと新たなオブジェクトが作成されるためHolizontalPodAutoScalerの対象に新しいオブジェクトはバインドされません。HorizontalPodAutoscalerを利用する場合はDeploymentを利用しましょう。

スラッシングが発生する場合はControllerManagerのパラメータを調整する

メトリクスは動的に評価される値のため頻繁にupscale/downscaleされることがあります。これをスラッシングというらしいです。これを緩和するためにControllerManagerには--horizontal-pod-autoscaler-downscale-delay--horizontal-pod-autoscaler-upscale-delayというパラメータがあります。これらのパラメータはdownscaleまたはupscaleが行われた場合に同じ処理を再度行う際に設定した時間待ってから処理するというものです。downscaleはデフォルト5分、upscaleはデフォルト3分となっています。このパラメータは長くするとその分upscale/downscaleが遅れることになるので調整する場合は注意が必要です。

v2からサポートされる機能

マルチメトリクス

複数のメトリクスによるオートスケールが可能になりました。複数設定した場合な各メトリクスに基づいて評価し最大のReplicasが採用されます。
複数設定するには以下のように設定します。

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
spec:
  scaleTargetRef:
    kind: Deployment
    name: WebFrontend
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 80
  - type: Object
    object:
      target:
        kind: Service
        name: Frontend
      metricName: hits-per-second
      targetValue: 1k

各値の詳細などはこちらに定義があるので参照してください。

カスタムメトリクス

カスタムメトリクスによるオートスケーリングが可能になりました。
これを利用するためには次の設定をしなければなりません。

  • API aggregationの設定
    • APIサーバを経由して任意のサービスにアクセスするための機能です
    • 設定の方法などはこちらを参照してください
  • ControllerManagerを設定する
    • --horizontal-pod-autoscaler-use-rest-clientsをtrueにする

minikubeであれば上記は設定済みですので、特に設定などは不要です。カスタムメトリクスサーバは https://github.com/kubernetes-incubator/custom-metrics-apiserver にサンプルがあり、これをベースに作成すると良さそうですが、今回は予め用意されたサンプルを利用して設定してみます。

内容が若干古いですが https://docs.bitnami.com/kubernetes/how-to/configure-autoscaling-custom-metrics/ にカスタムメトリクスの設定方法が記載されていたのでこの方法を参考にサンプルアプリケーションのカスタムメトリクスによるオートスケーリングを試してみます。

# サンプルのマニフェストが含まれるリポジトリを取得
$ git clone git@github.com:luxas/kubeadm-workshop.git
$ cd kubeadm-workshop

# Prometheusのデプロイ
# この例ではPrometheusのメトリクスを利用してオートスケーリングするためPrometheusを用意します
$ kubectl apply -f demos/monitoring/prometheus-operator.yaml
$ kubectl apply -f demos/monitoring/sample-prometheus-instance.yaml.yaml

# カスタムメトリクスサーバのデプロイ
$ kubectl apply -f demos/monitoring/custom-metrics.yaml

# 確認
$ kubectl api-versions
# custom.metrics.k8s.io/v1beta1 が登録されている
$ kubectl get --raw apis/custom.metrics.k8s.io/v1beta1
{"kind":"APIResourceList","apiVersion":"v1","groupVersion":"custom.metrics.k8s.io/v1beta1","resources":[{"name":"namespaces/scrape_duration_seconds","singularName":"","namespaced":false,"kind":"MetricValueList","verbs":["get"]},{"name":"services/scrape_duration_seconds","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"jobs.batch/scrape_samples_post_metric_relabeling","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"namespaces/up","singularName":"","namespaced":false,"kind":"MetricValueList","verbs":["get"]},{"name":"jobs.batch/http_requests","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"namespaces/http_requests","singularName":"","namespaced":false,"kind":"MetricValueList","verbs":["get"]},{"name":"jobs.batch/scrape_duration_seconds","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"services/scrape_samples_post_metric_relabeling","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"services/scrape_samples_scraped","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"namespaces/scrape_samples_scraped","singularName":"","namespaced":false,"kind":"MetricValueList","verbs":["get"]},{"name":"pods/scrape_samples_scraped","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"pods/http_requests","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"services/http_requests","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"pods/scrape_duration_seconds","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"namespaces/scrape_samples_post_metric_relabeling","singularName":"","namespaced":false,"kind":"MetricValueList","verbs":["get"]},{"name":"pods/scrape_samples_post_metric_relabeling","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"jobs.batch/scrape_samples_scraped","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"jobs.batch/up","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"pods/up","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]},{"name":"services/up","singularName":"","namespaced":true,"kind":"MetricValueList","verbs":["get"]}]}

# サンプルアプリケーションのデプロイ
$ kubectl apply -f demos/monitoring/sample-metrics-app.yaml

# hpa を確認
$ kubectl get hpa
NAME                     REFERENCE                       TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
sample-metrics-app-hpa   Deployment/sample-metrics-app   866m/100   2         10        2          2h

HPAの中身は以下のように設定されています。

kind: HorizontalPodAutoscaler
apiVersion: autoscaling/v2beta1
metadata:
  name: sample-metrics-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: sample-metrics-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Object
    object:
      target:
        kind: Service
        name: sample-metrics-app
      metricName: http_requests
      targetValue: 100

これはsample-metrics-appサービスのQPSが1Podあたり100QPSになるようにオートスケールが実施されるという設定になります。
実際に負荷をかけてみると以下のようにオートスケールが実施されました。

NAME                     REFERENCE                       TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
sample-metrics-app-hpa   Deployment/sample-metrics-app   603/100   2         10        6          2h

参考

35
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?