KEDAを使ってGPUワークロードをゼロにスケールさせる
2024-09-27
#はじめに
今回は、KEDAを使ってGPUワークロードをゼロにスケールさせる方法について紹介します。
GPUは、機械学習やディープラーニングなどのワークロードを高速に処理するために利用されます。しかし、GPUはコストが高いため、常に利用されているわけではありません。そのため、GPUワークロードをゼロにスケールさせることで、コストを削減することができます。KEDAを利用してこの課題に取り組みたいと思います。
#目次
#KEDAとは
KEDA is a Kubernetes-based Event Driven Autoscaler. With KEDA, you can drive the scaling of any container in Kubernetes based on the number of events needing to be processed.
KEDA is a single-purpose and lightweight component that can be added into any Kubernetes cluster. KEDA works alongside standard Kubernetes components like the Horizontal Pod Autoscaler and can extend functionality without overwriting or duplication. With KEDA you can explicitly map the apps you want to use event-driven scale, with other apps continuing to function. This makes KEDA a flexible and safe option to run alongside any number of any other Kubernetes applications or frameworks.
以下、翻訳。
KEDAはKubernetesベースのEvent Driven Autoscalerです。KEDAを使えば、処理が必要なイベントの数に基づいてKubernetesの任意のコンテナのスケーリングを駆動できます。
KEDAは、あらゆるKubernetesクラスタに追加できる単一目的の軽量コンポーネントです。KEDAはHorizontal Pod Autoscalerのような標準的なKubernetesコンポーネントと一緒に動作し、上書きや重複なしに機能を拡張することができます。KEDAを使えば、イベントドリブンスケールを使いたいアプリを明示的にマッピングし、他のアプリはそのまま機能させることができます。このためKEDAは、他のあらゆるKubernetesアプリケーションやフレームワークと並行して実行できる、柔軟で安全なオプションとなります。
KEDAは、イベント駆動のオートスケーラーとのことです。同じようなソリューションとしては、上記の通りHPAがありますが、HPAはCPU利用率やメモリ利用率などのリソース利用率に基づいてスケールアウトを行います。また、HPAでは、ゼロにスケールする方法はありません。一方、KEDAはイベントに基づいて、スケールすることができます。そして、ゼロにスケールすることもできます。サーバーレスのようなアーキテクチャで利用されるようなものですね。
似たようなソリューションとしては、Knativeがあります。
Knativeは、GoogleのCloud Runというサーバーレスのサービスで利用されている技術です。
Knativeでは、主にHTTPイベントを扱いますが、KEDAは、Scaler
と呼ばれるリソースによって、様々なイベントやカスタムメトリクスに基づいたスケーリングができます。
次のリンクにKEDAが扱えるScalerの一覧があります。
https://keda.sh/docs/2.15/scalers/
#背景
最近いくつかのGPUワークロードを扱う機会がありました。その中で、自宅のマシンだとGPUが1台しかないので、一つのワークロードでGPUリソースを専有してしまうと、他のワークロードでは、GPUリソースを取得できずに待ち状態になってしまいます。そのため、GPUワークロードをより効率的に利用する方法を模索していました。
そこで、KEDAを使ってGPUワークロードをゼロにスケールさせる方法を検討しました。
#KEDA HTTP add-onとは
KEDAが扱えるScaler
には、HTTPがありません。KEDA HTTP add-on
を使うことで、HTTPリクエストに基づいたスケーリングができるようになります。
詳細は、こちらのThe Design of HTTP Add-onを参照してください。KEDA HTTP add-on
は、Project statusがBetaなので、本番環境での利用には注意が必要です。
今回は、ollamaをserveしてHTTPリクエストに基づいたスケーリングを試してみたいと思います。
#実装
下記のドキュメントを参考に実装を進めます。
https://github.com/kedacore/http-add-on/blob/main/docs/install.md
https://github.com/kedacore/http-add-on/blob/main/docs/walkthrough.md
#KEDAのインストール
helmfileを使ってKEDAをインストールします。
repositories:
- name: kedacore
url: https://kedacore.github.io/charts
releases:
- name: kedacore
chart: kedacore/keda
namespace: keda
version: 2.15.1
#KEDA HTTP add-onのインストール
helmfileを使ってKEDA HTTP add-onをインストールします。
repositories:
- name: kedacore
url: https://kedacore.github.io/charts
releases:
- name: http-add-on
chart: kedacore/keda-add-ons-http
namespace: keda
version: 0.8.0
この時点でkeda namespaceに以下のPodが作成されていることを確認します。
❯ k get po -n keda
NAME READY STATUS RESTARTS AGE
keda-add-ons-http-controller-manager-5cf6648b77-8n8pw 2/2 Running 0 2m47s
keda-add-ons-http-external-scaler-5bb5f74bfc-cpqhg 1/1 Running 0 2m47s
keda-add-ons-http-external-scaler-5bb5f74bfc-m8zqh 1/1 Running 0 2m47s
keda-add-ons-http-external-scaler-5bb5f74bfc-s894b 1/1 Running 0 2m47s
keda-add-ons-http-interceptor-7fdc6b7cb7-5zsxw 1/1 Running 0 2m47s
keda-add-ons-http-interceptor-7fdc6b7cb7-pb6tb 1/1 Running 0 2m30s
keda-add-ons-http-interceptor-7fdc6b7cb7-vj6fw 1/1 Running 0 2m30s
keda-admission-webhooks-86597c4884-lsx6v 1/1 Running 0 2m48s
keda-operator-7f84d94549-zcrh5 1/1 Running 0 2m48s
keda-operator-metrics-apiserver-8458849cc8-g2tfl 1/1 Running 0 2m48s
#HTTPScaledObjectの作成
以前の記事で作成したollamaのHelmに追加のHTTPScaledObjectを作成します。
クラスタ内部からアクセスしたいので、ホストにはollama-proxy.ollama.svc.cluster.local
を指定しています。
- httpscaledobject.yaml
apiVersion: http.keda.sh/v1alpha1
kind: HTTPScaledObject
metadata:
name: {{ include "ollama.fullname" . }}
labels:
{{- include "ollama.labels" . | nindent 4 }}
spec:
hosts:
- ollama-proxy.ollama.svc.cluster.local
pathPrefixes:
- /
scaleTargetRef:
name: {{ include "ollama.fullname" . }}
kind: Deployment
apiVersion: apps/v1
service: {{ include "ollama.fullname" . }}
port: {{ .Values.service.port }}
replicas:
min: 0
max: 1
scaledownPeriod: 300
scalingMetric:
requestRate:
granularity: 1s
targetValue: 100
window: 1m
ollamaのServiceとは別に、ollama-proxyというExternalNameのServiceを作成します。
これは、kedaのkeda-add-ons-http-interceptor-proxy.keda.svc.cluster.local
に名前解決されます。
- externalservice.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "ollama.fullname" . }}-proxy
labels:
{{- include "ollama.labels" . | nindent 4 }}
spec:
type: ExternalName
externalName: keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local
#動作確認
クラスタ内からollama-proxy.ollama.svc.cluster.local
にアクセスすると、ゼロからスケールアウトして、HTTPレスポンスが返ってきます。2回叩いてみましたが、初回はPod起動するのに時間がかかり、3秒強といったところです。2回目は、すぐにレスポンスが返ってきました。初回の遅延をどう評価するかは、ユースケース次第だと思いますが、AIの推論など、そもそも遅延が長い場合や、ユーザが直接触らないようなEmbeddingの計算などでは、問題ないかもしれません。
> time curl ollama-proxy.ollama.svc.cluster.local:8080
Ollama is running
real 0m 3.41s
user 0m 0.00s
sys 0m 0.00s
> time curl ollama-proxy.ollama.svc.cluster.local:8080
Ollama is running
real 0m 0.00s
user 0m 0.00s
sys 0m 0.00s
scaledownPeriod
で指定した300秒が経過すると、ゼロにスケールインされます。
これで他のGPUワークロードがGPUリソースを利用できるようになります。
❯ k get all -n ollama
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/ollama ClusterIP 10.43.172.18 <none> 11434/TCP 114m
service/ollama-proxy ExternalName <none> keda-add-ons-http-interceptor-proxy.keda.svc.cluster.local <none> 89m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/ollama 0/0 0 0 114m
NAME DESIRED CURRENT READY AGE
replicaset.apps/ollama-8657894646 0 0 0 114m
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/keda-hpa-ollama Deployment/ollama <unknown>/100 (avg) 1 1 0 114m
#参考リンク
#まとめ
今回は、KEDAを使ってGPUワークロードをゼロにスケールさせる方法について紹介しました。
KEDAは、イベント駆動のオートスケーラーで、HTTPリクエストに基づいたスケーリングも可能です。
KEDA HTTP add-onを使うことで、HTTPリクエストに基づいたスケーリングができるようになります。
GPUワークロードに限らず、イベント駆動でスケーリングしたい場合には、KEDAを使ってみると良いかもしれません。