Ponz Dev Log

ゆるくてマイペースな開発日記

OpenShiftで特定の時間だけPodをスケールアウト/スケールインする

Red Hat OpenShiftで特定の時間帯だけPodをスケールアウト、それ以外の時間は少ない数 (できれば0) にスケールインという運用をKedaで実現してみます。AWSだとAmazon EC2 Auto Scalingに相当する機能の検証です。

Kedaとは?

Kedaはイベント駆動でKubernetesのPodをスケールするソフトウェアです。CNCFのGuraduatedプロジェクトであり、Apache 2.0ライセンスのOSSです。

keda.sh

Kedaには多種多様なイベントに対応したスケーラー(トリガー)があり、スケーラーの1つに時間を指定する cronスケーラー があります。時間帯指定によるスケールはこの cronスケーラー で実現します。その他のスケーラーは以下のリンクを参照してください。

keda.sh

OpenShiftでKedaを使うには?

KedaはKubernetesディストリビューションに依らずインストール可能です。インストール方法はHelmチャートやOperatorで実施します。

OpenShiftであればKedaをアップストリームとした Custom Metrics Autoscaler Operator が提供されています。本記事ではこのOperatorでKedaをインストールして検証します。

access.redhat.com

環境情報

  • Red Hat OpenShift 4.13 (on OpenShift Local)
  • Custom Metrics Autoscaler Operator 2.10.1-267

検証における注意事項

執筆時点のバージョンのCustom Metrics Autoscaler Operatorでは cronスケーラー は公式のサポート対象には含まれていません。あくまでアップストリームのKedaに含まれているので使用可能という理解です。 実運用では最新のサポート状況をご確認いただき、動作検証を十分に行うことを推奨します。

カスタムメトリクスオートスケーラーは現在、Prometheus、CPU、メモリー、および Apache Kafka トリガーのみをサポートしています。

Custom Metrics Autoscaler Operatorのインストール

Custom Metrics Autoscaler OperatorをOpenShiftのWebコンソールからインストールします。 管理者ビューのOperatorHubから "Custom Metrics" や "Keda" で検索するとヒットします。

OperatorHubでの検索結果

Operator説明画面

Operatorを選択して表示される設定画面に進み、設定値はデフォルト値のままでインストールすればOKです。自動的にOperatorを実行するプロジェクト openshift-keda が作成されます。 インストールガイドではインストールモードに「クラスターのすべてのnamespace (All namespaces on the cluster)」を指定するように記載がありましたが選択できません。「クラスターの特定のnamespace」で問題ありませんでした。

Operator設定画面

インストール済みOperatorで「Installed」と表示されたらOperatorのインストール作業は完了です。 APIグループ keda.sh のカスタムリソースが利用可能となっています。

$ oc api-resources --api-group keda.sh
NAME                            SHORTNAMES               APIVERSION         NAMESPACED   KIND
clustertriggerauthentications   cta,clustertriggerauth   keda.sh/v1alpha1   false        ClusterTriggerAuthentication
kedacontrollers                                          keda.sh/v1alpha1   true         KedaController
scaledjobs                      sj                       keda.sh/v1alpha1   true         ScaledJob
scaledobjects                   so                       keda.sh/v1alpha1   true         ScaledObject
triggerauthentications          ta,triggerauth           keda.sh/v1alpha1   true         TriggerAuthentication

コントローラーの作成

スケーラーの設定を投入する前に、Kedaの各種スケーラーを処理するコントローラーを作成します。コントローラーは KedaController リソースで作成します。 以下の keda-controller.yaml を作成して適用します。内容はOpenShift Webコンソールで作成するときのデフォルト値をそのまま使っています。

$ cat <<EOF | tee -a keda-controller.yaml
apiVersion: keda.sh/v1alpha1
kind: KedaController
metadata:
  name: keda
  namespace: openshift-keda
spec:
  admissionWebhooks:
    logEncoder: console
    logLevel: info
  metricsServer:
    logLevel: '0'
  operator:
    logEncoder: console
    logLevel: info
  watchNamespace: ''
EOF

$ oc apply -f keda-controller.yaml
kedacontroller.keda.sh/keda created

$ oc get kedacontrollers -n openshift-keda
NAME   AGE
keda   5s

サンプルアプリケーションをデプロイ

スケールを試すサンプルアプリケーションを準備します。本記事ではNginxのサンプルを使用します。 oc new-app コマンドでNginxのビルダーイメージからコンテナイメージをビルドしてデプロイまで実施します。

$ oc new-app --name nginx nginx:1.20-ubi9~https://github.com/sclorg/nginx-ex 
warning: Cannot check if git requires authentication.
--> Found image ea20902 (5 weeks old) in image stream "openshift/nginx" under tag "1.20-ubi9" for "nginx:1.20-ubi9"

    Nginx 1.20 
    ---------- 
    Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and IMAP protocols, with a strong focus on high concurrency, performance and low memory usage. The container image provides a containerized packaging of the nginx 1.20 daemon. The image can be used as a base image for other applications based on nginx 1.20 web server. Nginx server image can be extended using source-to-image tool.

    Tags: builder, nginx, nginx-120

    * A source build using source code from https://github.com/sclorg/nginx-ex will be created
      * The resulting image will be pushed to image stream tag "nginx:latest"
      * Use 'oc start-build' to trigger a new build

--> Creating resources ...
    imagestream.image.openshift.io "nginx" created
    buildconfig.build.openshift.io "nginx" created
    deployment.apps "nginx" created
    service "nginx" created
--> Success
    Build scheduled, use 'oc logs -f buildconfig/nginx' to track its progress.
    Application is not exposed. You can expose services to the outside world by executing one or more of the commands below:
     'oc expose service/nginx' 
    Run 'oc status' to view your app.

この時点ではレプリカ数は1です。

$ oc get po,deploy
NAME                        READY   STATUS      RESTARTS   AGE
pod/nginx-1-build           0/1     Completed   0          3m26s
pod/nginx-7ffdc8d89-tmz6z   1/1     Running     0          49s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           3m26s

スケーラー設定

本記事の本題です。Kedaではスケーラーを用いたPodのスケール設定を ScaledObject または ScaledJob リソースで定義します。 常時起動してリクエストを受け付けるアプリケーションであれば ScaledObject 、特定のメトリクスに反応して単発起動するアプリケーションであれば ScaledJob と使い分けます。 本記事ではWebサーバーであるNginxを使っているので ScaledObject リソースでスケーラーを設定します。

ScaledObject リソースを設定例を次に示します。

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: nginx
  namespace: ponzmild-dev
spec:
  scaleTargetRef:
    kind: Deployment
    name: nginx
  minReplicaCount: 0
  maxReplicaCount: 3
  triggers:
  - type: cron
    metadata:
      timezone: Asia/Tokyo
      start: 00 21 * * *
      end: 30 21 * * *
      desiredReplicas: "3"

この ScaledObject では以下の内容を定義しています。 cron式の時間をタイムゾーンで指定可能なのは嬉しいですね。UTCに変換するために9時間引く手間が省けます。

  • 最小レプリカ数 = 0 (デフォルト値)
  • 指定時間のみレプリカ数 = 3
  • スケールする時間帯は Asia/Tokyo タイムゾーンの 21:00 から 21:30 まで。

スケーラーの設定を keda-scaled-object-nginx.yaml に保存してOpenShiftに適用します。

$ oc apply -f keda-scaled-object-nginx.yaml
scaledobject.keda.sh/nginx created

稼働確認

ScaledObject リソースを作成直後 (20:45)

ScaledObject リソースを作成した時点からスケールする様子を確認します。 リソース作成時点ではcron式で時間帯以外と判定されているのでレプリカ数が1から0にスケールインしています。

$ oc get deploy
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   0/0     0            0           8m47s

$ oc get hpa
NAME             REFERENCE          TARGETS             MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-nginx   Deployment/nginx   <unknown>/1 (avg)   1         3         0          16s

$ oc get so
NAME    SCALETARGETKIND      SCALETARGETNAME   MIN   MAX   TRIGGERS   AUTHENTICATION   READY   ACTIVE   FALLBACK   AGE
nginx   apps/v1.Deployment   nginx             0     3     cron                        True    False    Unknown    53s

イベントログを参照するとスケールインしたことが記録されています。

$ oc get events --namespace ponzmild-dev | tail -10
2m         Normal    KEDAScalersStarted           scaledobject/nginx                       Started scalers watch
2m         Normal    ScaledObjectReady            scaledobject/nginx                       ScaledObject is ready for scaling
2m         Normal    KEDAScaleTargetDeactivated   scaledobject/nginx                       Deactivated apps/v1.Deployment ponzmild-dev/nginx from 1 to 0
2m         Normal    ScalingReplicaSet            deployment/nginx                         Scaled down replica set nginx-7ffdc8d89 to 0 from 1

スケール開始 (21:00)

cron式で指定した21:00を迎えるとスケーラーの定義通りPodレプリカ数が3にスケールアウトしています。ScaledObjectに紐づくHPAが3に設定していますね。

$ oc get po,deploy,hpa,so
NAME                        READY   STATUS      RESTARTS   AGE
pod/nginx-1-build           0/1     Completed   0          32m
pod/nginx-7ffdc8d89-5jwvc   1/1     Running     0          19m
pod/nginx-7ffdc8d89-mjtmw   1/1     Running     0          19m
pod/nginx-7ffdc8d89-tq8wb   1/1     Running     0          19m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   3/3     3            3           32m

NAME                                                 REFERENCE          TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/keda-hpa-nginx   Deployment/nginx   1/1 (avg)   1         3         3          23m

NAME                         SCALETARGETKIND      SCALETARGETNAME   MIN   MAX   TRIGGERS   AUTHENTICATION   READY   ACTIVE   FALLBACK   AGE
scaledobject.keda.sh/nginx   apps/v1.Deployment   nginx             0     3     cron                        True    True     False      23m

また、Kedaの仕組みとして最初にレプリカ数を0→1に変更、続いてレプリカ数を1→3と順番にスケールアウトしていることがイベントログからわかります。

5m         Normal    KEDAScaleTargetActivated     scaledobject/nginx                       Scaled apps/v1.Deployment ponzmild-dev/nginx from 0 to 1
5m         Normal    ScalingReplicaSet            deployment/nginx                         Scaled up replica set nginx-7ffdc8d89 to 3 from 1

スケール終了 (21:35ごろ)

cron式の指定時間を終えるとレプリカ数は0にスケールインします。

$ oc get po,deploy,hpa,so
NAME                READY   STATUS      RESTARTS   AGE
pod/nginx-1-build   0/1     Completed   0          47m

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   0/0     0            0           47m

NAME                                                 REFERENCE          TARGETS             MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/keda-hpa-nginx   Deployment/nginx   <unknown>/1 (avg)   1         3         0          39m

NAME                         SCALETARGETKIND      SCALETARGETNAME   MIN   MAX   TRIGGERS   AUTHENTICATION   READY   ACTIVE   FALLBACK   AGE
scaledobject.keda.sh/nginx   apps/v1.Deployment   nginx             0     3     cron                        True    False    False      39m

イベントにも一気に0にスケールしたことが記録されています。

$ oc get events --namespace ponzmild-dev | tail -10
73s         Normal    KEDAScaleTargetDeactivated   scaledobject/nginx                       Deactivated apps/v1.Deployment ponzmild-dev/nginx from 3 to 0
73s         Normal    ScalingReplicaSet            deployment/nginx                         Scaled down replica set nginx-7ffdc8d89 to 0 from 3

ちなみにスケールインが実行されたのはend時間に指定した 21:30 ではなく 21:35 でした。これはScaledObjectの cooldownperiod でスケールインの猶予時間がデフォルト5分で指定されているからです。実運用ではこの猶予時間を適切に設定する必要がありそうです。

Scaling Deployments, StatefulSets & Custom Resources | KEDA

The period to wait after the last trigger reported active before scaling the resource back to 0. By default, it’s 5 minutes (300 seconds).


以上。