LoginSignup
5
3

More than 3 years have passed since last update.

【KubernetesでPodをスケーリングさせる】その2 - オートスケーリング

Last updated at Posted at 2019-06-12

概要

KubernetesでPodをオートスケーリングをしてみる。
ここではMinikube環境を利用したが、その他の環境の場合は適宜読み替えてください。

手動でスケーリングさせる方法はこちら
【KubernetesでPodをスケーリングさせる】その1 - 手動スケーリング

Nodeをスケーリングさせることもできるが、ここでは触れない。
参考:Kuberentes クラスタのオートスケール

目次

環境

  • CentOS 7.6
  • Minikube v1.1.1
  • Kubernetes v1.14.3

関連記事

Deploymentの仕組み

KubernetesのDeploymentについて事前に理解しておくことを推奨。
Deploymentの仕組み

事前準備

metrics-serverのインストール

metrics-serverを入れないと、以下のコマンドなどが利用できず、リソースのチェックができない。

$ sudo kubectl top node
error: metrics not available yet

オートスケーリングをする際にもリソースのチェックをするため、metrics-serverが必要となる。
minikubeのaddonで用意されているので、有効化する。

$ sudo minikube addons enable metrics-server
✅  metrics-server was successfully enabled

minikubeを利用していない場合は、以下を参考に入れる。

ちなみにHeapsterはKubernetes 1.11で非推奨になったらしい。
https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#support-for-metrics-apis

Fetching metrics from Heapster is deprecated as of Kubernetes 1.11.

これでkubectl topコマンドが利用できるようになった。
metrics-serverインストール直後ではerror: metrics not available yetとなる可能性があるので、その場合は少し待つ。

$ sudo kubectl top node
NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
minikube   92m          1%     2276Mi          14%
# podが存在していない場合は何も返ってこない
$ sudo kubectl top pods
NAME                               CPU(cores)   MEMORY(bytes)
http-deployment-545bd7d765-9ghmf   0m           39Mi

各種定義

Deployment

deployment.yml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: http-deployment
spec:
  selector:
    matchLabels:
      ########################################################
      # deploymentの.spec.selector.matchLabels.appの値と、
      # 後述のservice.ymlの.spec.selector.appの値を合わせることで、
      # serviceからdeploymentにリクエストを流すことが可能となる。
      ########################################################
      app: http-app
  # podの設定
  # ここでは触れないが、このPodTemlateの部分に変更があったときに、ローリングアップデートが実行される
  template:
    metadata:
      labels:
        app: http-app
    spec:
      containers:
        # Dockerコンテナ名
        - name: http-container
          # 利用するDockerイメージ
          image: php:7.0-apache
          # localイメージ利用。ただし、localに指定したイメージが存在しない場合はレポジトリを参照する
          imagePullPolicy: IfNotPresent
          # Podのリソース定義
          resources:
            # PodをDeployする際に、必要とするリソースを指定できる仕組み。枠外(*1)を参照
            requests:
              memory: 64Mi
              cpu: 250m
            # 該当のPodのリソース使用量の上限を設定することができる。枠外(*2)を参照
            limits:
              memory: 128Mi
              cpu: 500m
          ports:
            # service.ymlで定義する外部公開用port設定の箇所と名前を合わせることでbindされる
            # nameは15文字以内でないとエラーになる
            - name: ha-inner-port
              # コンテナ内のport
              containerPort: 80
          # mountするディレクトリ:コンテナ側の設定
          volumeMounts:
            - name: documentroot
              mountPath: /var/www/html
      # mountするディレクトリ:ホストOS側の設定
      volumes:
        - name: documentroot
          hostPath:
            path: /home/username/containers/web/html

(*1)Resource Requestsとは

  • PodをDeployする際に、必要とするリソースを指定できる仕組み
  • Podの利用上限リソースを定義するものではない(そちらはResource Limitを利用する)
  • 指定したリソースが確保されるわけではなく、PodをDeployする際に必要なリソースがあるか確認し、不足していればDeployされない
  • nodeのリソースはチェックせず、Resource Requestsで指定したリソースしか見ないので、nodeのリソースが不足していてもDeployしようとする。その際は、該当のPodはPending状態となる

(*2)Resource Limitsとは

  • 該当のPodのリソース使用量の上限を設定することができる
  • nodeのリソースに空きがあっても、該当のPodではResource Limitsの内容で制限される
  • nodeのリソース上限を超えた設定ができる
    • CPUの場合、処理遅延が起きるだけで、特に問題はない
    • メモリの場合、コンテナのプロセスがKillされる
      • Podの設定で、restart policyがAlways、もしくはOnFailureが設定されていた場合は、コンテナは自動で再起動される
      • PodのStatusがCrashLoopBackOffになっている場合は、コンテナ再起動が繰り返されている可能性があるので要注意。PodのRESTARTSで再起動回数が分かる
    • Resource Limitsを指定しない場合、リソース上限は無制限となる

参考:KubernetesのResource RequestsとResource Limitsについて

Service

service.yml
kind: Service
apiVersion: v1
metadata:
  # service名
  name: http-service
spec:
  selector:
    ########################################################
    # 前述のdeploymentの.spec.selector.matchLabels.appの値と、
    # service.ymlの.spec.selector.appの値を合わせることで、
    # serviceからdeploymentにリクエストを流すことが可能となる。
    ########################################################
    app: http-app
  ports:
    - name: ha-outer-port
      # 外部公開するport
      port: 8080
      # deployment.ymlで定義したport名と合わせることでbindされる
      targetPort: ha-inner-port
  type: NodePort

HorizontalPodAutoscaler

オートスケーリングの定義をする。

2019/06現在、apiVersionの最新はautoscaling/v1だが、autoscaling/v2beta1と書式が異なるので、両方書いておく。

参考:API version

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

autoscaling/v2beta1

autoscaling.yml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
  name: http-autoscaling
  namespace: default
spec:
  # オートスケーリング対象を定義
  scaleTargetRef:
    kind: Deployment
    apiVersion: apps/v1
    # 対象のdeployment名を定義する
    name: http-deployment
  # 最小レプリカ数
  minReplicas: 1
  # 最大レプリカ数
  maxReplicas: 5
  # スケーリングをする条件
  metrics:
  - type: Resource
    resource:
      name: cpu
      # CPU使用率が常に10%になるように指定。超えたらオートスケーリングする。
      targetAverageUtilization: 10

autoscaling/v1

CPU使用率の定義方法が異なる。
v1ではmetricsは利用できないため、v2beta1の書式でcreateを実行すると、以下のエラーが出る。

$ sudo kubectl create -f autoscaling.yml
error: error validating "autoscaling.yml": error validating data: ValidationError(HorizontalPodAutoscaler.spec): unknown field "metrics" in io.k8s.api.autoscaling.v1.HorizontalPodAutoscalerSpec; if you choose to ignore these errors, turn validation off with --validate=false
autoscaling.yml
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: http-autoscaling
  namespace: default
spec:
  # オートスケーリング対象を定義
  scaleTargetRef:
    kind: Deployment
    apiVersion: apps/v1
    # 対象のdeployment名を定義する
    name: http-deployment
  # 最小レプリカ数
  minReplicas: 1
  # 最大レプリカ数
  maxReplicas: 5
  # スケーリングをする条件
  # すべてのPodの平均CPU使用率の目標値(%の値を設定する)
  targetCPUUtilizationPercentage: 10

その他のAPI Resource(kind)については以下を参照

作成

$ sudo kubectl create -f deployment.yml -f service.yml -f autoscaling.yml
deployment.extensions/http-deployment created
service/http-service created
horizontalpodautoscaler.autoscaling/http-autoscaling created

確認

作成されたことを確認。

$ sudo kubectl get all
NAME                                   READY   STATUS    RESTARTS   AGE
pod/http-deployment-545bd7d765-hmqnh   1/1     Running   0          4s

NAME                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
service/http-service   NodePort    10.108.236.223   <none>        8080:31212/TCP   4s
service/kubernetes     ClusterIP   10.96.0.1        <none>        443/TCP          31h

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/http-deployment   1/1     1            1           4s

NAME                                         DESIRED   CURRENT   READY   AGE
replicaset.apps/http-deployment-545bd7d765   1         1         1       4s

NAME                                                   REFERENCE                    TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/http-autoscaling   Deployment/http-deployment   <unknown>/10%   1         5         0          4s

負荷のかかるプログラムを作成

以下のPHPプログラムを実行して負荷をかけ、オートスケーリングをさせる。
deployment.ymlのvolumesで定義した、コンテナにマウントした領域に設置する。

/home/username/containers/web/html/autoscaling.php
<?php
$max = 1*1000*1000*1000;

$x = 0;
for ($i=0; $i<=$max; $i++) {
    $x += $i;
}

echo $x . "\n";
echo "done\n";

負荷のかかるプログラムを実行

実行前にPodの数を確認。Podは1つしかない。

$ sudo kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
http-deployment-545bd7d765-hmqnh   1/1     Running   0          18s

プログラムを実行する。

$ curl $(sudo minikube service http-service --url)/autoscaling.php
500000000500000000
done

プログラムを実行後の状況を確認

autoscaling.ymlで定義した、最大レプリカ数 maxReplicas: 5 の通り、Podの数が5つになった。
リソースのチェックは30秒ごとに行っているらしいので、スケールアウトされるまでは少しタイムラグがある。

$ sudo kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
http-deployment-545bd7d765-9wlg7   1/1     Running   0          77s
http-deployment-545bd7d765-bcgqs   1/1     Running   0          77s
http-deployment-545bd7d765-cgnn2   1/1     Running   0          77s
http-deployment-545bd7d765-hmqnh   1/1     Running   0          3m19s
http-deployment-545bd7d765-ww2h2   1/1     Running   0          62s

プログラムが停止後、しばらくしたらPodの数が最小レプリカ数 minReplicas: 1の通り、Podが1つに戻った。

$ sudo kubectl get pod
NNAME                               READY   STATUS    RESTARTS   AGE
http-deployment-545bd7d765-hmqnh   1/1     Running   0          11m

オートスケーリングのアルゴリズムについては以下を参照

Autoscaling Algorithm

TargetNumOfPods = ceil(sum(CurrentPodsCPUUtilization) / Target)

手動でスケーリングさせる方法はこちら

参考

5
3
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
5
3