Red Hat OpenShiftで特定の時間帯だけPodをスケールアウト、それ以外の時間は少ない数 (できれば0) にスケールインという運用をKedaで実現してみます。AWSだとAmazon EC2 Auto Scalingに相当する機能の検証です。
Kedaとは?
Kedaはイベント駆動でKubernetesのPodをスケールするソフトウェアです。CNCFのGuraduatedプロジェクトであり、Apache 2.0ライセンスのOSSです。
Kedaには多種多様なイベントに対応したスケーラー(トリガー)があり、スケーラーの1つに時間を指定する cronスケーラー があります。時間帯指定によるスケールはこの cronスケーラー で実現します。その他のスケーラーは以下のリンクを参照してください。
OpenShiftでKedaを使うには?
KedaはKubernetesのディストリビューションに依らずインストール可能です。インストール方法はHelmチャートやOperatorで実施します。
OpenShiftであればKedaをアップストリームとした Custom Metrics Autoscaler Operator が提供されています。本記事ではこのOperatorでKedaをインストールして検証します。
環境情報
- 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" で検索するとヒットします。
Operatorを選択して表示される設定画面に進み、設定値はデフォルト値のままでインストールすればOKです。自動的にOperatorを実行するプロジェクト openshift-keda
が作成されます。
インストールガイドではインストールモードに「クラスターのすべてのnamespace (All namespaces on the cluster)」を指定するように記載がありましたが選択できません。「クラスターの特定のnamespace」で問題ありませんでした。
インストール済み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).
以上。