이 튜토리얼에서는 KEDA를 사용하여 GKE 워크로드를 0개 포드로 확장하는 방법을 보여줍니다. 배포를 0개 포드로 확장하면 비활성 기간 (예: 주말 및 근무 시간 외) 또는 주기적 작업과 같은 간헐적인 워크로드에 리소스를 절약할 수 있습니다.
목표
이 튜토리얼에서는 다음 사용 사례를 설명합니다.
- Pub/Sub 워크로드를 0으로 확장: Pub/Sub 주제에 큐에 추가된 메시지 수에 비례하여 포드 수를 확장합니다. 대기열이 비어 있으면 워크로드가 자동으로 0개 Pod로 축소됩니다.
- LLM 워크로드를 0으로 조정합니다. GPU가 있는 노드에 LLM 모델 서버를 배포합니다. 서비스가 유휴 상태이면 워크로드가 자동으로 0개 포드로 축소됩니다.
비용
이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.
- GKE
- GPU resources used by GKE
- Pub/Sub
프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요.
이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.
시작하기 전에
이 튜토리얼에서는 Cloud Shell을 사용하여 명령어를 실행합니다. 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 클러스터를 만들어야 하는 리전 또는 영역으로 바꿉니다.단일 세션에서 전체 튜토리얼을 따르지 않거나 어떠한 이유로든 환경 변수가 설정되지 않은 경우 이 명령어를 다시 실행하여 변수를 다시 설정해야 합니다.
클러스터 자동 확장 및 GKE용 워크로드 아이덴티티 제휴가 사용 설정된 표준 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 수평형 포드 자동 확장 처리를 보완하는 구성요소입니다. KEDA를 사용하면 배포를 0개 포드로 확장하고 0개 포드에서 1개 포드로 확장할 수 있습니다. 배포는 클러스터의 노드 간에 분산된 포드의 여러 복제본을 실행할 수 있는 Kubernetes API 객체입니다. 표준 수평형 포드 자동 확장 처리 알고리즘은 GKE가 하나 이상의 포드를 만든 후에 적용됩니다.
GKE에서 배포를 0개 포드로 확장하면 실행 중인 포드가 없으므로 자동 확장은 CPU 사용률과 같은 포드 측정항목을 사용할 수 없습니다. 따라서 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용 워크로드 아이덴티티 제휴로 설정해야 하는 승인 규칙도 설정합니다.
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용 워크로드 아이덴티티 제휴로 설정해야 하는 승인 규칙도 설정합니다.
모든 KEDA 리소스가 keda
네임스페이스 아래에 표시되는지 확인합니다.
kubectl get all -n keda
KEDA 설계 및 리소스에 관한 자세한 내용은 KEDA 문서를 참고하세요.
Pub/Sub 워크로드를 0으로 확장
이 섹션에서는 Pub/Sub 구독의 메시지를 처리하고 각 메시지를 처리하고 완료를 확인하는 워크로드를 설명합니다. 워크로드가 동적으로 확장됩니다. 확인되지 않은 메시지의 수가 증가하면 자동 확장이 더 많은 포드를 인스턴스화하여 적시에 처리합니다.
0으로 확장하면 일정 시간 동안 메시지가 수신되지 않을 때 포드가 인스턴스화되지 않습니다. 이렇게 하면 Pod가 장시간 유휴 상태로 유지되지 않으므로 리소스가 절약됩니다.
Pub/Sub 워크로드 배포
Pub/Sub 주제에 대기열에 추가된 메시지를 처리하는 샘플 워크로드를 배포합니다. 실제 워크로드를 시뮬레이션하기 위해 이 샘플 프로그램은 메시지를 확인하기 전에 3초 동안 기다립니다. 워크로드는 keda-pubsub-sa
서비스 계정으로 실행되도록 구성됩니다.
다음 명령어를 실행하여 Pub/Sub 주제와 구독을 만들고 권한을 구성한 후 keda-pubub
네임스페이스 아래에서 워크로드를 시작하는 배포를 만듭니다.
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://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-with-workload-identity.yaml
Scale-to-zero 구성
Pub/Sub 워크로드를 0으로 확장되도록 구성하려면 KEDA를 사용하여 ScaledObject
리소스를 정의하여 배포 확장 방법을 지정합니다.
그러면 KEDA가 기본 HorizontalPodAutoscaler
(HPA) 객체를 자동으로 만들고 관리합니다.
예상되는 자동 확장 동작을 설명하는
ScaledObject
리소스를 만듭니다.curl https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/cloud-pubsub/deployment/keda-pubsub-scaledobject.yaml | envsubst | 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"
KEDA가
ScaledObject
객체를 기반으로 만드는HorizontalPodAutoscaler
(HPA) 객체를 검사합니다.kubectl get hpa keda-hpa-keda-pubsub -n keda-pubsub -o yaml
Kubernetes 문서에서 자동 확장에 대해 자세히 알아보세요.
KEDA가 Pub/Sub 구독이 비어 있음을 확인하고 배포를 0개 복제본으로 확장할 때까지 기다립니다.
워크로드 자동 확장 처리를 검사합니다.
kubectl describe hpa keda-hpa-keda-pubsub -n keda-pubsub
명령어 응답에서
ScalingActive
조건이 false임을 확인합니다. 관련 메시지는 수평형 포드 자동 확장 처리가 KEDA가 배포를 0으로 확장했음을 인식했음을 나타냅니다. 이때 배포가 다시 1개 포드로 확장될 때까지 작동을 중지합니다.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
확장 트리거
배포를 확장하도록 자극하려면 다음 단계를 따르세요.
Pub/Sub 주제에 메시지를 큐에 추가합니다.
for num in {1..20} do gcloud pubsub topics publish keda-echo --project=${PROJECT_ID} --message="Test" done
배포가 확장되고 있는지 확인합니다.
kubectl get deployments -n keda-pubsub
출력에서 'Ready'(준비됨) 열에 복제본 1개가 표시됩니다.
NAME READY UP-TO-DATE AVAILABLE AGE keda-pubsub 1/1 1 1 2d
KEDA는 대기열이 비어 있지 않은 것을 관찰한 후 배포를 확장합니다.
LLM 워크로드를 0으로 조정
이 섹션에서는 GPU가 연결된 Ollama 서버를 배포하는 대규모 언어 모델 (LLM) 워크로드를 설명합니다. Ollama를 사용하면 Gemma 및 Lamma 2와 같은 인기 있는 LLM을 실행할 수 있으며 주로 HTTP를 통해 기능을 노출합니다.
KEDA-HTTP 부가기능 설치
비활성 상태인 동안 HTTP 서비스를 0개 Pod로 확장하면 요청을 처리할 백엔드가 없으므로 요청 실패가 발생합니다.
이 섹션에서는 KEDA-HTTP 부가기능을 사용하여 이 문제를 해결하는 방법을 보여줍니다. KEDA-HTTP는 사용자 요청을 수신하고 0으로 확장되도록 구성된 서비스로 전달하는 HTTP 프록시를 시작합니다. 서비스에 포드가 없으면 프록시가 서비스를 트리거하여 확장하고 서비스가 하나 이상의 포드로 확장될 때까지 요청을 버퍼링합니다.
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://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/helm-values-ollama.yaml
helm-values-ollama.yaml
구성은 로드할 LLM 모델, GPU 요구사항, Ollama 서버의 TCP 포트를 지정합니다.
Scale-to-zero 구성
Ollama 워크로드를 0으로 확장되도록 구성하기 위해 KEDA-HTTP는 HTTPScaledObject
를 사용합니다.
예상되는 자동 확장 동작을 설명하는
HTTPScaledObject
리소스를 만듭니다.kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/kubernetes-engine-samples/refs/heads/main/cost-optimization/gke-keda/ollama/keda-ollama-httpscaledobject.yaml
그러면 다음 필드를 정의하는
HTTPScaledObject
객체가 생성됩니다.scaleTargetRef
: KEDA-HTTP가 요청을 전달해야 하는 서비스를 지정합니다. 이 예시에서는 호스트가ollama.ollama
인 모든 요청이 Ollama 서버로 라우팅됩니다.scaledownPeriod
: 요청이 수신되지 않을 때 얼마나 빨리 축소할지 초 단위로 지정합니다.replicas
: Ollama 배포를 위해 유지할 포드의 최소 및 최대 수를 지정합니다.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
배포가 0개의 포드로 확장되었는지 확인합니다.
scaledownPeriod
필드에 설정된 시간 동안 기다린 후 다음 명령어를 실행합니다.kubectl get deployments -n ollama
출력은 KEDA가 Ollama 배포를 축소했으며 실행 중인 포드가 없음을 보여줍니다.
NAME READY UP-TO-DATE AVAILABLE AGE ollama 0/0 0 0 2d
확장 트리거
배포가 확장되도록 하려면 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
명령어는 Gemma 모델에 'Hello!' 프롬프트를 전송합니다. 응답에서 반환되는 답변 토큰을 확인합니다. 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 저장소 및 문서 살펴보기