このチュートリアルでは、KEDA を使用して GKE ワークロードを Pod 0 にスケールダウンする方法について説明します。Deployment を 0 Pod にスケーリングすると、非アクティブな期間(週末や勤務時間外など)や、定期的なジョブなどの断続的なワークロードでリソースを節約できます。
目標
このチュートリアルでは、次のユースケースについて説明します。
- Pub/Sub ワークロードをゼロにスケーリングする: Pub/Sub トピックでキューに登録されているメッセージ数に比例して Pod の数をスケーリングします。キューが空になると、ワークロードは自動的にゼロ Pod にスケールダウンします。
- LLM ワークロードをゼロにスケールします。GPU を使用するノードに LLM モデルサーバーをデプロイします。サービスがアイドル状態になると、ワークロードは自動的にゼロ Pod にスケールダウンします。
料金
このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。
- GKE
- GPU resources used by GKE
- Pub/Sub
料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。
このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。
始める前に
このチュートリアルでは、Cloud Shell を使用してコマンドを実行します。Google Cloud Shell は、Google Cloud でホストされているリソースを管理するためのシェル環境です。これには、Google Cloud CLI、kubectl、Helm、Terraform コマンドライン ツールがプリインストールされています。Cloud Shell を使用しない場合は、Google Cloud CLI と Helm をインストールする必要があります。
-
このページにあるコマンドを実行するには、次のいずれかの開発環境で gcloud CLI を設定します。
Cloud Shell
gcloud CLI がすでに設定されているオンライン ターミナルを使用するには、Cloud Shell をアクティブにします。
このページの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。セッションが初期化されるまで数秒かかることがあります。
ローカルシェル
ローカル開発環境を使用する手順は次のとおりです。
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Resource Manager, Compute Engine, GKE, Pub/Sub APIs.
環境設定
Cloud Shell を使用して環境を設定するには、次の操作を行います。
環境変数を設定します。
export PROJECT_ID=PROJECT_ID export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format 'get(projectNumber)') export LOCATION=LOCATION
PROJECT_ID
は Google Cloud のプロジェクト ID に、LOCATION
は GKE クラスタを作成するリージョンまたはゾーンに置き換えます。チュートリアル全体を 1 つのセッションで完了しない場合や、なんらかの理由で環境変数が設定されていない場合は、このコマンドを再度実行して変数を再度設定してください。
クラスタ自動スケーリングと GKE 用 Workload Identity 連携を有効にして、Standard GKE クラスタを作成します。
gcloud container clusters create scale-to-zero \ --project=${PROJECT_ID} --location=${LOCATION} \ --machine-type=n1-standard-2 \ --enable-autoscaling --min-nodes=1 --max-nodes=5 \ --workload-pool=${PROJECT_ID}.svc.id.goog
KEDA をインストールする
KEDA は、Kubernetes HorizontalPodAutoscaler を補完するコンポーネントです。KEDA を使用すると、Deployment をゼロ Pod にスケールダウンし、ゼロ Pod から 1 Pod にスケールアップできます。Deployment は、クラスタ内のノード間で Pod の複数のレプリカを実行できる Kubernetes API です。標準の HorizontalPodAutoscaler アルゴリズムは、GKE が 1 つ以上の Pod を作成した後に適用されます。
GKE が Deployment を 0 個の Pod にスケーリングすると、実行中の Pod がないため、自動スケーリングは CPU 使用率などの Pod 指標に依存できません。その結果、KEDA では、Kubernetes External Metrics API の実装を使用して、クラスタの外部から指標を取得できます。この API を使用すると、Pub/Sub サブスクリプションの未処理メッセージ数などの指標に基づいて自動スケーリングできます。サポートされているすべての指標ソースの一覧については、KEDA のドキュメントをご覧ください。
Helm または kubectl
を使用して、クラスタに KEDA をインストールします。
Helm
次のコマンドを実行して KEDA Helm リポジトリを追加し、KEDA Helm チャートをインストールし、KEDA サービス アカウントに Cloud Monitoring への読み取りアクセス権を付与します。
helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm install keda kedacore/keda --create-namespace --namespace keda
gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
--role roles/monitoring.viewer \
--member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
このコマンドは、クラスタに GKE 用 Workload Identity 連携を設定することを要求する認可ルールも設定します。
kubectl
次のコマンドを実行して kubectl apply
を使用して KEDA をインストールし、KEDA サービス アカウントに Cloud Monitoring への読み取りアクセス権を付与します。
kubectl apply --server-side -f https://github.com/kedacore/keda/releases/download/v2.15.1/keda-2.15.1.yaml
gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
--role roles/monitoring.viewer \
--member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda/sa/keda-operator
このコマンドは、クラスタに GKE 用 Workload Identity 連携を設定することを要求する認可ルールも設定します。
すべての KEDA リソースが keda
Namespace に表示されていることを確認します。
kubectl get all -n keda
KEDA の設計とリソースの詳細については、KEDA のドキュメントをご覧ください。
Pub/Sub ワークロードをゼロにスケーリングする
このセクションでは、Pub/Sub サブスクリプションからのメッセージを処理し、各メッセージを処理して完了を確認するワークロードについて説明します。ワークロードは動的にスケーリングされます。未確認メッセージの数が増えると、自動スケーリングにより Pod がインスタンス化され、タイムリーな処理が保証されます。
0 にスケーリングすると、しばらくメッセージが受信されなかったときに Pod がインスタンス化されなくなります。これにより、Pod が長時間アイドル状態にならないため、リソースを節約できます。
Pub/Sub ワークロードをデプロイする
Pub/Sub トピックにキューに入れられたメッセージを処理するサンプル ワークロードをデプロイします。実際のワークロードをシミュレートするため、このサンプル プログラムは、メッセージを確認する前に 3 秒間待機します。ワークロードは、keda-pubsub-sa
サービス アカウントで実行するように構成されています。
次のコマンドを実行して Pub/Sub トピックとサブスクリプションを作成し、権限を構成して、keda-pubub
Namespace でワークロードを開始する Deployment を作成します。
gcloud pubsub topics create keda-echo
gcloud pubsub subscriptions create keda-echo-read --topic=keda-echo
gcloud projects add-iam-policy-binding projects/${PROJECT_ID} \
--role=roles/pubsub.subscriber \
--member=principal://iam.googleapis.com/projects/${PROJECT_NUMBER}/locations/global/workloadIdentityPools/${PROJECT_ID}.svc.id.goog/subject/ns/keda-pubsub/sa/keda-pubsub-sa
kubectl apply -f https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-with-workload-identity.yaml
ゼロへのスケーリングを構成する
Pub/Sub ワークロードをゼロにスケーリングするように構成するには、KEDA を使用して ScaledObject
リソースを定義し、デプロイメントのスケーリング方法を指定します。KEDA は、基盤となる HorizontalPodAutoscaler
(HPA)オブジェクトを自動的に作成して管理します。
想定される自動スケーリングの動作を記述する
ScaledObject
リソースを作成します。envsubst < https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-scaledobject.yaml | kubectl apply -f -
これにより、次のオブジェクトが作成されます。
apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: keda-pubsub namespace: keda-pubsub spec: maxReplicaCount: 5 scaleTargetRef: name: keda-pubsub triggers: - type: gcp-pubsub authenticationRef: name: keda-auth metadata: subscriptionName: "projects/${PROJECT_ID}/subscriptions/keda-echo-read"
ScaledObject
オブジェクトに基づいて KEDA が作成するHorizontalPodAutoscaler
(HPA)オブジェクトを調べます。kubectl get hpa keda-hpa-keda-pubsub -n keda-pubsub -o yaml
自動スケーリングの詳細については、Kubernetes のドキュメントをご覧ください。
KEDA が Pub/Sub サブスクリプションが空であることを認識し、Deployment をゼロ レプリカにスケーリングするまで待機します。
ワークロード オートスケーラーを調べます。
kubectl describe hpa keda-hpa-keda-pubsub -n keda-pubsub
コマンド レスポンスで、
ScalingActive
条件が false になっていることを確認します。関連するメッセージは、Horizontal Pod Autoscaler が KEDA が Deployment を 0 にスケーリングしたことを認識したことを示しています。この時点で、Deployment が 1 つの Pod にスケールバックされるまで、オペレーションは停止します。Name: keda-hpa-keda-pubsub Namespace: keda-pubsub Metrics: ( current / target ) "s0-gcp-ps-projects-[...]]" (target average value): 0 / 10 Min replicas: 1 Max replicas: 5 Deployment pods: 5 current / 5 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ScaleDownStabilized recent recommendations were higher than current one [...] ScalingActive False ScalingDisabled scaling is disabled since the replica count of the target is zero ScalingLimited True TooManyReplicas the desired replica count is more than the maximum replica count
スケールアップをトリガーする
Deployment をスケールアップするには:
Pub/Sub トピックにメッセージをキューに追加します。
for num in {1..20} do gcloud pubsub topics publish keda-echo --project=${PROJECT_ID} --message="Test" done
Deployment がスケールアップされていることを確認します。
kubectl get deployments -n keda-pubsub
出力で、[Ready] 列に 1 つのレプリカが表示されていることを確認します。
NAME READY UP-TO-DATE AVAILABLE AGE keda-pubsub 1/1 1 1 2d
KEDA は、キューが空でないことを確認した後、Deployment をスケールアップします。
LLM ワークロードをゼロにスケーリングする
このセクションでは、GPU が接続された Ollama サーバーをデプロイする大規模言語モデル(LLM)ワークロードについて説明します。Ollama を使用すると、Gemma や Lamma 2 などの一般的な LLM を実行できます。また、主に HTTP を介して機能を公開します。
KEDA-HTTP アドオンをインストールする
非アクティブな期間中に HTTP サービスをゼロ Pod にスケールダウンすると、リクエストを処理するバックエンドがないため、リクエストが失敗します。
このセクションでは、KEDA-HTTP アドオンを使用してこの問題を解決する方法について説明します。KEDA-HTTP は、ユーザー リクエストを受信してゼロスケーリングするように構成された Service に転送する HTTP プロキシを起動します。Service に Pod がない場合、プロキシは Service のスケールアップをトリガーし、Service が少なくとも 1 つの Pod にスケールアップするまでリクエストをバッファリングします。
Helm を使用して KEDA-HTTP アドオンをインストールします。詳細については、KEDA-HTTP のドキュメントをご覧ください。
helm repo add ollama-helm https://otwld.github.io/ollama-helm/
helm repo update
# Set the proxy timeout to 120s, giving Ollama time to start.
helm install http-add-on kedacore/keda-add-ons-http \
--create-namespace --namespace keda \
--set interceptor.responseHeaderTimeout=120s
Ollama LLM ワークロードをデプロイする
Ollama LLM ワークロードをデプロイするには:
GPU が接続された
g2-standard-4
ノードを含むノードプールを作成し、0 ~ 2 個のノードを提供するクラスタ自動スケーリングを構成します。gcloud container node-pools create gpu --machine-type=g2-standard-4 \ --location=${LOCATION} --cluster=scale-to-zero \ --min-nodes 0 --max-nodes 2 --num-nodes=1 --enable-autoscaling
公式の Ollama Helm チャート リポジトリを追加し、ローカル Helm クライアントのリポジトリを更新します。
helm repo add ollama-helm https://otwld.github.io/ollama-helm/ helm repo update
Helm チャートを使用して Ollama サーバーをデプロイします。
helm install ollama ollama-helm/ollama --create-namespace --namespace ollama \ -f https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/ollama/helm-values-ollama.yaml
helm-values-ollama.yaml
構成では、読み込む LLM モデル、GPU 要件、Ollama サーバーの TCP ポートを指定します。
ゼロへのスケーリングを構成する
ゼロにスケーリングするように Ollama ワークロードを構成するには、KEDA-HTTP が HTTPScaledObject
を使用します。
想定される自動スケーリングの動作を記述する
HTTPScaledObject
リソースを作成します。kubectl apply -f https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/tree/main/cost-optimization/gke-keda/ollama/keda-ollama-httpscaledobject.yaml
これにより、次のフィールドを定義する
HTTPScaledObject
オブジェクトが作成されます。scaleTargetRef
: KEDA-HTTP がリクエストを転送する Service を指定します。この例では、ホストollama.ollama
を持つすべてのリクエストが Ollama サーバーに転送されます。scaledownPeriod
: リクエストを受信していないときにスケールダウンする速度(秒単位)を指定します。replicas
: Ollama デプロイメントで維持する Pod の最小数と最大数を指定します。scalingMetric
: この例ではリクエスト レートなど、自動スケーリングの実行に使用される指標を指定します。その他の指標オプションについては、KEDA-HTTP のドキュメントをご覧ください。
kind: HTTPScaledObject apiVersion: http.keda.sh/v1alpha1 metadata: namespace: ollama name: ollama spec: hosts: - ollama.ollama scaleTargetRef: name: ollama kind: Deployment apiVersion: apps/v1 service: ollama port: 11434 replicas: min: 0 max: 2 scaledownPeriod: 3600 scalingMetric: requestRate: targetValue: 20
次のコマンドを実行して、KEDA-HTTP が前の手順で作成した
HTTPScaledObject
を正常に処理したことを確認します。kubectl get hpa,scaledobject -n ollama
出力には、
HorizontalPodAutoscaler
(KEDA によって作成)とScaledObject
(KEDA-HTTP によって作成)のリソースが表示されます。NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE horizontalpodautoscaler.autoscaling/keda-hpa-ollama Deployment/ollama 0/100 (avg) 1 2 1 2d NAME SCALETARGETKIND SCALETARGETNAME MIN MAX TRIGGERS AUTHENTICATION READY ACTIVE FALLBACK PAUSED AGE scaledobject.keda.sh/ollama apps/v1.Deployment ollama 0 2 external-push True False False Unknown 2d
Deployment が Pod を 0 にスケールダウンしていることを確認します。
scaledownPeriod
フィールドで設定した時間待ってから、次のコマンドを実行します。kubectl get deployments -n ollama
出力には、KEDA が Ollama Deployment をスケールダウンし、Pod が実行されていないことが示されます。
NAME READY UP-TO-DATE AVAILABLE AGE ollama 0/0 0 0 2d
スケールアップをトリガーする
Deployment のスケールアップを促すには、KEDA-HTTP アドオンによって設定されたプロキシを使用して Ollama サービスを呼び出します。これにより、リクエスト レート指標の値が増加し、最初の Pod の作成がトリガーされます。
プロキシは外部に公開されていないため、kubectl
ポート転送機能を使用してプロキシにアクセスします。
kubectl port-forward svc/keda-add-ons-http-interceptor-proxy -n keda 8080:8080 &
# Set the 'Host' HTTP header so that the proxy routes requests to the Ollama server.
curl -H "Host: ollama.ollama" \
http://localhost:8080/api/generate \
-d '{ "model": "gemma:7b", "prompt": "Hello!" }'
curl
コマンドは、プロンプト「Hello!」を Gemma モデルに送信します。レスポンスで返される回答トークンを観察します。API の仕様については、Ollama ガイドをご覧ください。
クリーンアップ
このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。
Pub/Sub サブスクリプションとトピックをクリーンアップします。
gcloud pubsub subscriptions delete keda-echo-read gcloud pubsub topics delete keda-echo
GKE クラスタを削除します。
gcloud container clusters delete scale-to-zero --location=${LOCATION}
次のステップ
- GKE で LLM 推論ワークロードを自動スケーリングする方法の詳細を確認する。
- KEDA の GitHub リポジトリとドキュメントを確認する。