Help us understand the problem. What is going on with this article?

KubernetesのPodとNodeのAuto Scalingについて

PodのHorizontal Pod Autoscaling(水平podオートスケーリング)

podのHorizontal pod autoscaling(水平podオートスケーリング)とは、podの負荷に応じて自動的にpodの数を増減させることを指す。
HorizontalPodAutoscalerリソースを定義することで水平オートスケーリングが可能になる。

まずDeployment, ReplicaSet, ReplicationController, StatefulSetはscaled resource objectと呼ばれる。
これらがauto scalingが可能なリソース。

HorizontalPodAutoscalerリソースの定義例:

apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: php-hpa
  namespace: default
spec:
  scaleTargetRef: # ここでautoscale対象となる`scaled resource object`を指定
    apiVersion: apps/v1
    kind: Deployment
    name: php-deploy
  minReplicas: 1 # 最小レプリカ数
  maxReplicas: 5 # 最大レプリカ数
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 50 # CPU使用率が常に50%になるように指定

autoscalingプロセスは以下の3つで行われる。

  • 指定したscaled resource objectによって管理されている全てのpodのメトリックを取得する
  • メトリックを定義されたターゲット値に近づけるためにはどのくらいのpodが必要か計算する
  • scaled resource objectのreplicas fieldを更新する。

ポイントとしては、auto scalingはtarget valueに近づくようにpod数が調整されるということ。
target valueが80なら 全体(全podの合計)のCPU使用率が80%になるように調整される。たとえば全体のCPU使用率が90%ならpod数は増えるし、50%ならpod数は減らされる。

スケールアウトのための計算方法は以下 (詳しくはAutoscaling Algorithmを参照)

必要なレプリカ数 = ceil(sum(Podの現在のCPU使用率) / targetAverageUtilization)

重要な点は、定期的(30秒に1回)にメトリックの取得をしているため、すぐにはスケーリングが行われないということ。少し時間がかかる。

  • スケールアウト(pod数を増やす)イベントは3分おきに発生する。
  • スケールイン(pod数を減らす)イベントは5分おきに発生する。

オートスケールされやすいようにCPUを100%使うようなpodを作成する

$ cat hpa-test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hpa-test-deploy
spec:
  replicas: 3
  template:
    metadata:
      name: hpa-app
      labels:
        app: hpa-app
    spec:
      containers:
      - image: busybox
        command: ["dd", "if=/dev/zero", "of=/dev/null"] # CPUを100%使うように
$ kubectl apply -f hpa-test-deploy.yaml
deployment "hpa-test-deploy" created

3つpodができていることを確認

$ kubectl get pod
NAME                               READY     STATUS    RESTARTS   AGE
hpa-test-deploy-69487b74dc-bfk6s   1/1       Running   0          9s
hpa-test-deploy-69487b74dc-rc4k2   1/1       Running   0          9s
hpa-test-deploy-69487b74dc-zs2j7   1/1       Running   0          9s

しばらくするとtopコマンドでメトリックスが取得可能状態になる

$ kubectl top pod
NAME                               CPU(cores)   MEMORY(bytes)
hpa-test-deploy-69487b74dc-rc4k2   945m         0Mi
hpa-test-deploy-69487b74dc-zs2j7   957m         0Mi
hpa-test-deploy-69487b74dc-bfk6s   950m         0Mi

CPU使用率を50%に保つHorizontalPodAutoscalerリソースを作る

$ cat hpa-test.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-test
  namespace: default
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: hpa-test-deploy
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      targetAverageUtilization: 50
$ kubectl apply -f hpa-test.yaml
horizontalpodautoscaler "hpa-test" created

すぐにはメトリックスを取得しないので最初はTARGETSの左がになる

$ kubectl get HorizontalPodAutoscaler hpa-test
NAME       REFERENCE                    TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
hpa-test   Deployment/hpa-test-deploy   <unknown> / 50%   1         5         0          27s

しばらくするとTARGETSの左にメトリックスが表示される

$ kubectl get HorizontalPodAutoscaler hpa-test
NAME       REFERENCE                    TARGETS      MINPODS   MAXPODS   REPLICAS   AGE
hpa-test   Deployment/hpa-test-deploy   966% / 50%   1         5         3          30s

describeしてみると、Events欄にSuccessfulRescaleと表示され、pod数が5つになったことが分かる

$ kubectl describe HorizontalPodAutoscaler hpa-test
Name:                                                  hpa-test
Namespace:                                             default
Labels:                                                <none>
Annotations:                                           kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"hpa-test","namespace":"default"},"spec":{"max...
CreationTimestamp:                                     Fri, 20 Apr 2018 22:38:53 +0900
Reference:                                             Deployment/hpa-test-deploy
Metrics:                                               ( current / target )
  resource cpu on pods  (as a percentage of request):  966% (966m) / 50%
Min replicas:                                          1
Max replicas:                                          5
Conditions:
  Type            Status  Reason            Message
  ----            ------  ------            -------
  AbleToScale     True    SucceededRescale  the HPA controller was able to update the target scale to 5
  ScalingActive   True    ValidMetricFound  the HPA was able to succesfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooManyReplicas   the desired replica count was more than the maximum replica count
Events:
  Type    Reason             Age   From                       Message
  ----    ------             ----  ----                       -------
  Normal  SuccessfulRescale  3s    horizontal-pod-autoscaler  New size: 5; reason: cpu resource utilization (percentage of request) above target

podの数を見てみると5つ(HorizontalPodAutoscalerで指定したMAXのpod replica数)になっていることが分かる

$ kubectl get pod
NAME                               READY     STATUS    RESTARTS   AGE
hpa-test-deploy-69487b74dc-6sp7l   1/1       Running   0          10s
hpa-test-deploy-69487b74dc-bfk6s   1/1       Running   0          2m
hpa-test-deploy-69487b74dc-d69mt   1/1       Running   0          10s
hpa-test-deploy-69487b74dc-rc4k2   1/1       Running   0          2m
hpa-test-deploy-69487b74dc-zs2j7   1/1       Running   0          2m

他のメトリックスによるAuto Scaling

custom metricsを用いてCPUメトリックス以外のメトリックスでオートスケーリングを行うことができる。
HorizontalPodAutoscalerリソースには以下の4種類を指定することができる。

  • Resource
    • Resource Requests, Resource Limitsのようなメトリックス
  • Pods
    • Podのメトリックス。例えばQueries Per Second(QPS) や message broker’s queueやコネクションの数。
  • Object
    • Podとは直接関係ないメトリックス。たとえばIngressのHit/sやlatency。
  • External
    • Kubernetes外のメトリックス(例: LBのQPS、Cloud Pus/Subの溜まっているメッセージ数)

どんなメトリックスがAuto Scalingに適しているか判断する

  • podのメモリ消費量はオートスケーリングメトリックスに向かない。 podが増えるほど全体のメモリ消費量は増え、使えるメモリ量が逆に減るからだ。
  • メトリックスの一つとして、Queries per Second (QPS)がある。(※Requests per Secondと同義か?)
  • オートスケーリングメトリックスとしてcustom metricsを使う前に、podが増減したらそのメトリックスがどのように振る舞うかよく考えること。

PodのVertical Pod Autoscaling(垂直podオートスケーリング)

Vertical Pod Autoscalerは、コンテナに割り当てるCPU、メモリのリソースの割り当てを自動的にスケールさせるリソースです。
必要とするリソース(CPU、メモリ)量があらかじめ推測しにくいアプリケーションに対して、実績に基づいてそれらしい値を決めたい場合に効果を発揮します。

猫でもわかる Vertical Pod Autoscaler がわかりやすいです。

Nodeの水平オートスケーリング

Kubernetesは、cloud providerが提供していれば、nodeのauto scalingもでき、Cluster Autoscalerという機能が担っている。
Cluster Autoscalerは、リソースが枯渇して既存のnodeにpodがschedulingできない場合に、nodeを追加する。
またリソース負荷が低いならnodeの削除も行う。
Cluster Autoscalerはnodeを追加する前にそのnodeにpodがscheduleできるかを確認する。じゃないとnodeを追加してもpodがscheduleできない事態になってしまう。

nodeを削除するとき(scale downするとき)system podsが実行されているかチェックし、されているならnodeの削除を行わない。ただしsystem podsがDaemonSetの場合を除く。DaemonSetは各nodeで実行されているためnodeからpodを削除しても問題ないため。
また unmanaged pod(replicasetやdeploymentによって管理されていないpod)やlocal storageを使っているpodが存在する場合もnodeを削除しない。
nodeを削除するさいには、nodeにunschedulableを設定する。これによりpodがscheduleされなくなる。
そしてnode上のpodが追い出される。
追い出されたpodはreplicasetやdeploymentの管理下なので他のnodeへ再scheduleされる。

Tips

  • kubectl cordon <node>でnodeにunschedulableを設定できる。unschedulableが設定されたnodeにはpodがscheduleされなくなる。
  • kubectl drain <node>でnodeにunschedulableを設定し、node上のpodを追い出す。
  • kubectl uncordon <node>を実行すればnodeのunschedulableを解除できる。

cluster scale down時にサービスの中断を抑える

nodeが突然死んだ場合はどうしようもないが、手動もしくはCluster Autoscalerでnodeの削除が行われる場合は、サービスを中断させないことができる。
PodDisruptionBudgetリソースを作成すればよい。
参考: https://qiita.com/tkusumi/items/946b0f31931d21a78058
PodDisruptionBudget とは Node を計画的に停止したい場合に、Pod の状況を見ながら退去 (evict) させる機能です」

まとめ

  • podの水平スケーリング(scale out)はHorizontalPodAutoscalerリソースを作成し、それをDeployment, ReplicaSetに指定し、対象CPU使用量を指定することで簡単にできる。
  • podのCPU使用量の他に、アプリケーションが提供するcustom metricsやclusterにdeployされている他のリソースのmetricsをもとにオートスケーリングすることができる。
  • (cloud providerから提供されていれば)cluster nodeもオートスケーリングできる。

参考

studyplus
学習管理アプリ「Studyplus」を開発・運営する会社です
https://info.studyplus.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away