Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

KEDAで実現するKubernetesのイベント駆動オートスケーリング

By Chimbu ChinnaduraiJun 26, 20236 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

Kubernetesはコンテナオーケストレーションを大きく変え、アプリケーションを大規模にデプロイ・運用できる環境を実現しました。なかでもオートスケーリングは、ワークロードの需要に応じてリソースを動的に調整する中核的な機能です。

一般的に使われるCPUやメモリベースの水平スケーリングだけでは、現代のアプリケーションが抱える複雑さを十分に捉えきれない場面が少なくありません。本記事では、Kubernetes Event-driven Autoscaling(KEDA)がこうした課題をどのように解決するかを掘り下げていきます。

**Kubernetes Event-driven Autoscaling(KEDA)とは**

Kubernetes Event-driven Autoscaling(KEDA)は、カスタムメトリクスや外部トリガーをきっかけとしたイベント駆動型スケーリングを可能にする、Kubernetes向けのオープンソースコンポーネントです。Kubernetes標準のHorizontal Pod Autoscaler(HPA)を拡張し、より柔軟できめ細かなオートスケーリングを実現します。

KEDAの主な特長は次のとおりです。

  • イベント駆動型のオートスケーリング:Kafkaトピックのメッセージ数やAzure Event Hubのイベント数といった外部イベントを起点に、アプリケーションをリアルタイムでスケールできます。
  • 豊富な組み込みスケーラー:主要なクラウドプラットフォーム、データベース、メッセージング、テレメトリ、CI/CDなどに対応するスケーラーが標準で用意されており、イベント駆動型オートスケーリングをすぐに導入できます。
  • 多様なworkloadsに対応:Deployment、Job、/scaleサブリソースを持つカスタムリソースなど幅広いworkloadsをサポートし、さまざまなアプリケーションで活用できます。
  • 高い拡張性:独自スケーラーの持ち込みやコミュニティ製スケーラーの利用が可能で、アプリケーション固有の要件にも柔軟に対応できます
  • コスト削減:不要なときはアプリケーションをゼロまでスケールダウンできるため、特に負荷の変動が大きいアプリケーションでクラウドコストを大きく抑えられます。
  • ベンダーニュートラル:あらゆるKubernetesクラスタで利用できるため、オンプレミス、クラウド、エッジのいずれの環境でも安心して採用できます。
  • シンプルな設定と運用:Kubernetesマニフェストによる宣言的な構成方式を採用しており、YAMLやJSONでスケーリングのルールやトリガーを定義できるため、設定や管理がシンプルです。

KEDAを実際に動かしてみる

ここからは、GKE上でKEDAを使い、Pub/Subのメッセージメトリクスをもとにオートスケーリングを行う方法を見ていきます。サンプルアプリケーションとKubernetesマニフェストはGitHubのリポジトリで公開しています。

前提条件

  • Workload Identityが有効化されたGKEクラスタ
  • HelmおよびKubectl

Pub/Subリソースのセットアップ

以下のコマンドを実行し、Pub/Subのトピックとサブスクリプションを作成します。

GCP_PROJECT_ID=$(gcloud config get-value project)
TOPIC_NAME=keda-demo-topic
SUBSCRIPTION_NAME=keda-demo-topic-subscription

# Create Topic
gcloud pubsub topics create $TOPIC_NAME --project $GCP_PROJECT_ID

# Create Subscription
gcloud pubsub subscriptions create $SUBSCRIPTION_NAME \
--topic $TOPIC_NAME \
--project $GCP_PROJECT_ID

KEDA向けWorkload Identityのセットアップ

GCP Workload Identityを使うと、GKEクラスタ上のworkloadsがIdentity and Access Management(IAM)サービスアカウントになりすまして、Google Cloudのサービスにアクセスできます。GKE上のworkloadsから安全かつ管理しやすい形でGoogle Cloudサービスを利用するには、Workload Identityの利用が推奨されています。

以下のコマンドを実行し、KEDA用のWorkload Identityを設定します。

KEDA_GCP_SERVICE_ACCOUNT=keda-operator
KEDA_NAMESPACE=keda
KEDA_K8S_SERVICE_ACCOUNT=keda-operator

#Create GCP service account
gcloud iam service-accounts create $KEDA_GCP_SERVICE_ACCOUNT \
--project=$GCP_PROJECT_ID

#Create IAM role bindings
gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
--member "serviceAccount:$KEDA_GCP_SERVICE_ACCOUNT@$GCP_PROJECT_ID.iam.gserviceaccount.com" \
--role "roles/monitoring.viewer"

#Allow kubernetes service account to impersonate GCP service account
gcloud iam service-accounts add-iam-policy-binding $KEDA_GCP_SERVICE_ACCOUNT@$GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:$GCP_PROJECT_ID.svc.id.goog[$KEDA_NAMESPACE/$KEDA_K8S_SERVICE_ACCOUNT]"

KEDAのインストール

KubernetesクラスタへのKEDAのインストール方法には、次のような選択肢があります。

本記事では、Helmチャートを使ってGKEクラスタにKEDAをデプロイします。

  • Helmリポジトリを追加・更新します。
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
  • 最新のKEDA Helmチャートをインストールします。
helm upgrade -install keda kedacore/keda \
--namespace keda \
--set 'serviceAccount.annotations.iam\.gke\.io\/gcp-service-account'="$KEDA_SERVICE_ACCOUNT@$GCP_PROJECT_ID.iam.gserviceaccount.com" \
--create-namespace \
--debug \
--wait

kedaのPodログを確認し、エラーなく稼働していることをチェックします。

KEDAのWebhookはポート9443で受け付けるため、コントロールプレーンからノードへの通信でポート9443が許可されている必要があります。GKEで自動生成されるファイアウォールルールはポート443と10250しか許可していないため、ポート9443を許可するルールを別途作成してください。

gcloudによるファイアウォールルール作成例:

gcloud compute firewall-rules create allow-api-server-to-keda-webhook \
--description="Allow kubernetes api server to keda webhook call on worker nodes TCP port 9443" \
--direction=INGRESS \
--priority=1000 \
--network=$VPC-NETWORK-NAME \
--action=ALLOW \
--rules=tcp:9443 \
--source-ranges=$CONTROL-PLANE-IP-RANGE \
--target-tags=$NETWORK-TAGS-ASSIGNED-TO-NODES

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

サンプルアプリケーションがPub/Subサブスクリプションからメッセージを受信できるよう、Workload Identityを設定します。

SAMPLE_APP_GCP_SERVICE_ACCOUNT=keda-demo
SAMPLE_APP_NAMESPACE=default
SAMPLE_APP_K8S_SERVICE_ACCOUNT=keda-demo

#Create GCP service account
gcloud iam service-accounts create $SAMPLE_APP_GCP_SERVICE_ACCOUNT \
--project=$GCP_PROJECT_ID

#Create IAM role bindings
gcloud projects add-iam-policy-binding $GCP_PROJECT_ID \
--member "serviceAccount:$SAMPLE_APP_GCP_SERVICE_ACCOUNT@$GCP_PROJECT_ID.iam.gserviceaccount.com" \
--role "roles/pubsub.subscriber"

#Allow kubernetes service account to impersonate GCP service account
gcloud iam service-accounts add-iam-policy-binding $SAMPLE_APP_GCP_SERVICE_ACCOUNT@$GCP_PROJECT_ID.iam.gserviceaccount.com \
    --role roles/iam.workloadIdentityUser \
    --member "serviceAccount:$GCP_PROJECT_ID.svc.id.goog[$KEDA_NAMESPACE/$KEDA_SERVICE_ACCOUNT]"

サンプルアプリケーションをGKEクラスタにデプロイします。

cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: ServiceAccount
metadata:
  annotations:
    iam.gke.io/gcp-service-account: keda-demo@$GCP_PROJECT_ID.iam.gserviceaccount.com
  name: keda-demo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: keda-demo
spec:
  selector:
    matchLabels:
      app: keda-demo
  replicas: 1
  template:
    metadata:
      labels:
        app: keda-demo
    spec:
      serviceAccountName: keda-demo
      containers:
      - image: simbu1290/keda-demo:v1
        name: consumer
        env:
        - name: PUB_SUB_PROJECT
          value: $GCP_PROJECT_ID
        - name: PUB_SUB_TOPIC
          value: "keda-demo-topic"
        - name: PUB_SUB_SUBSCRIPTION
          value: "keda-demo-topic-subscription"
EOF

KEDA Event Scalerのデプロイ

KEDAはさまざまなScaler(イベントソース)とシームレスに連携し、必要なスケーリング動作やパラメータをカスタムリソース(CRD)で指定します。KEDAはイベントソースを監視し、そのデータをHorizontal Pod Autoscaler(HPA)に渡すことで、リソースの迅速なスケールを実現します。

ここではGoogle Cloud Platform‎ Pub/Subのイベントスケーラーを使い、オートスケーリングをデモします。イベントソースと特定のworkloads(Deployment、StatefulSetなど)とのスケーリング関係は、ScaledObjectカスタムリソース定義で構成します。

TriggerAuthenticationを使うと、ScaledObjectやデプロイメントコンテナとは切り離して認証パラメータを定義できます。これにより、Pod Identityのような高度な認証方式や、認証情報の使い回しも可能になります。

以下のリソースをデプロイすると、サブスクリプション内の未承認メッセージ数に応じてKEDAがスケーリングを行います。

cat <<EOF | kubectl apply -f -
---
apiVersion: keda.sh/v1alpha1
kind: TriggerAuthentication
metadata:
  name: keda-demo-trigger-auth-gcp-credentials
spec:
  podIdentity:
    provider: gcp
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: keda-demo-pubsub-scaledobject
spec:
  scaleTargetRef:
    apiVersion: apps/v1 # Optional. Default: apps/v1
    kind: Deployment    # Optional. Default: Deployment
    name: keda-demo     # Mandatory. Must be in the same namespace as the ScaledObject
  pollingInterval: 5    # Optional. Default: 30 seconds
  minReplicaCount: 1    # Optional. Default: 0
  maxReplicaCount: 10   # Optional. Default: 100
  triggers:
  - type: gcp-pubsub
    authenticationRef:
      kind: TriggerAuthentication
      name: keda-demo-trigger-auth-gcp-credentials
    metadata:
      mode: "SubscriptionSize" # Optional - Default is SubscriptionSize - SubscriptionSize or OldestUnackedMessageAge
      value: "5" # Optional - Default is 5 for SubscriptionSize | Default is 10 for OldestUnackedMessageAge
      subscriptionName: "keda-demo-topic-subscription" # Mandatory
EOF

KEDAによって作成されたHPAリソースを確認してみましょう。

以下のスクリプトでトピックにテストメッセージを発行し、KEDAから渡されるメトリクスをもとにHPAが行うスケーリング動作を確認します。

#!/bin/bash

project_id=$GCP_PROJECT_ID
topic_name=$TOPIC_NAME

while true; do
    message="Hello, Pub/Sub!"
    gcloud pubsub topics publish ${topic_name} \
    --message "${message}" \
    --project ${project_id}
    sleep 1
done

KEDAによるスケーリングのデモです。

本記事では、GCP Pub/Subのメトリクスに連動してスケールするアプリケーションを例に、KEDAの機能を確認してきました。

KEDAは、Kubernetes環境におけるイベントベースのスケーリングを支える強力なツールです。メトリクスを柔軟にカスタマイズしつつ、リアルタイムなイベントに応じてアプリケーションを効率的にスケールできます。KEDAを活用すれば、コストとリソース管理を最適化しながら、workloadsの需要に動的に追従するアプリケーション運用を実現できます。