TorchServe를 사용하여 GKE에서 확장 가능한 LLM 제공

이 튜토리얼에서는 TorchServe 프레임워크를 사용하여 확장 가능한 머신러닝(ML) 모델을 Google Kubernetes Engine(GKE) 클러스터에 배포하고 서빙하는 방법을 보여줍니다. 여기에서는 사전 학습된 PyTorch 모델을 사용하며, 이 모델은 사용자 요청에 따라 예측 결과를 생성합니다. 모델을 배포한 후에는 애플리케이션이 예측 요청을 보낼 수 있도록 예측 요청 URL이 제공됩니다. 이 방식은 모델과 웹 애플리케이션을 독립적으로 확장할 수 있도록 해줍니다. ML 워크로드 및 애플리케이션을 Autopilot 모드에서 배포하면, GKE가 워크로드 실행에 가장 적합한 머신 유형과 크기를 자동으로 선택합니다.

이 튜토리얼은 머신러닝(ML) 엔지니어, 플랫폼 관리자 및 운영자, 그리고 GKE Autopilot을 사용하여 노드 구성, 확장, 업그레이드 작업에 대한 관리 오버헤드를 줄이고자 하는 데이터 및 AI 전문가를 대상으로 합니다. Google Cloud 콘텐츠에서 참조하는 일반적인 역할 및 예시 태스크에 대해 자세히 알아보려면 일반 GKE 사용자 역할 및 태스크를 참조하세요.

이 페이지를 읽기 전에 GKE Autopilot 모드에 대한 기본적인 이해가 필요합니다.

튜토리얼 애플리케이션 정보

이 애플리케이션은 Fast Dash 프레임워크를 사용하여 생성된 작은 Python 웹 애플리케이션입니다. 이 애플리케이션을 사용하여 T5 모델에 예측 요청을 전송합니다. 이 애플리케이션은 사용자 텍스트 입력 및 언어 쌍을 캡처하여 모델로 정보를 전송합니다. 이 모델은 텍스트를 번역하고 결과를 애플리케이션으로 반환하여 사용자에게 결과를 표시합니다. Fast Dash에 관한 자세한 내용은 Fast Dash 문서를 참조하세요.

환경 준비

예시 저장소를 클론하고 튜토리얼 디렉터리를 엽니다.

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
cd kubernetes-engine-samples/ai-ml/t5-model-serving

클러스터 만들기

다음 명령어를 실행합니다.

gcloud container clusters create-auto ml-cluster \
    --release-channel=RELEASE_CHANNEL \
    --cluster-version=CLUSTER_VERSION \
    --location=us-central1

다음을 바꿉니다.

  • RELEASE_CHANNEL: 클러스터의 출시 채널입니다. rapid, regular, stable 중 하나여야 합니다. L4 GPU를 사용하려면 GKE 버전 1.28.3-gke.1203000 이상이 있는 채널을 선택합니다. 특정 채널에서 사용 가능한 버전을 확인하려면 출시 채널의 기본 및 사용 가능한 버전 보기를 참조하세요.
  • CLUSTER_VERSION: 사용할 GKE 버전입니다. 1.28.3-gke.1203000 이상이어야 합니다.

이 작업을 완료하려면 몇 분 정도 걸립니다.

Artifact Registry 저장소 만들기

  1. 클러스터와 동일한 리전에서 Docker 형식으로 새 Artifact Registry 표준 저장소를 만듭니다.

    gcloud artifacts repositories create models \
        --repository-format=docker \
        --location=us-central1 \
        --description="Repo for T5 serving image"
    
  2. 저장소 이름을 확인합니다.

    gcloud artifacts repositories describe models \
        --location=us-central1
    

    출력은 다음과 비슷합니다.

    Encryption: Google-managed key
    Repository Size: 0.000MB
    createTime: '2023-06-14T15:48:35.267196Z'
    description: Repo for T5 serving image
    format: DOCKER
    mode: STANDARD_REPOSITORY
    name: projects/PROJECT_ID/locations/us-central1/repositories/models
    updateTime: '2023-06-14T15:48:35.267196Z'
    

모델 패키징

이 섹션에서는 Cloud Build를 사용하여 단일 컨테이너 이미지에 모델과 서빙 프레임워크를 패키징하고 결과 이미지를 Artifact Registry 저장소에 푸시합니다.

  1. 컨테이너 이미지의 Dockerfile을 검토합니다.

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     https://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    ARG BASE_IMAGE=pytorch/torchserve:0.12.0-cpu
    
    FROM alpine/git
    
    ARG MODEL_NAME=t5-small
    ARG MODEL_REPO=https://huggingface.co/${MODEL_NAME}
    ENV MODEL_NAME=${MODEL_NAME}
    ENV MODEL_VERSION=${MODEL_VERSION}
    
    RUN git clone "${MODEL_REPO}" /model
    
    FROM ${BASE_IMAGE}
    
    ARG MODEL_NAME=t5-small
    ARG MODEL_VERSION=1.0
    ENV MODEL_NAME=${MODEL_NAME}
    ENV MODEL_VERSION=${MODEL_VERSION}
    
    COPY --from=0 /model/. /home/model-server/
    COPY handler.py \
         model.py \
         requirements.txt \
         setup_config.json /home/model-server/
    
    RUN  torch-model-archiver \
         --model-name="${MODEL_NAME}" \
         --version="${MODEL_VERSION}" \
         --model-file="model.py" \
         --serialized-file="pytorch_model.bin" \
         --handler="handler.py" \
         --extra-files="config.json,spiece.model,tokenizer.json,setup_config.json" \
         --runtime="python" \
         --export-path="model-store" \
         --requirements-file="requirements.txt"
    
    FROM ${BASE_IMAGE}
    
    ENV PATH /home/model-server/.local/bin:$PATH
    ENV TS_CONFIG_FILE /home/model-server/config.properties
    # CPU inference will throw a warning cuda warning (not error)
    # Could not load dynamic library 'libnvinfer_plugin.so.7'
    # This is expected behaviour. see: https://stackoverflow.com/a/61137388
    ENV TF_CPP_MIN_LOG_LEVEL 2
    
    COPY --from=1 /home/model-server/model-store/ /home/model-server/model-store
    COPY config.properties /home/model-server/
    

    이 Dockerfile은 다음과 같은 여러 단계의 빌드 프로세스를 정의합니다.

    1. Hugging Face 저장소에서 모델 아티팩트를 다운로드합니다.
    2. PyTorch Serving Archive 도구를 사용하여 모델을 패키징합니다. 이렇게 하면 추론 서버가 모델을 로드하는 데 사용하는 모델 보관 파일(.mar)이 생성됩니다.
    3. PyTorch Serve를 사용하여 최종 이미지를 빌드합니다.
  2. Cloud Build를 사용하여 이미지를 빌드하고 푸시합니다.

    gcloud builds submit model/ \
        --region=us-central1 \
        --config=model/cloudbuild.yaml \
        --substitutions=_LOCATION=us-central1,_MACHINE=gpu,_MODEL_NAME=t5-small,_MODEL_VERSION=1.0
    

    빌드 프로세스를 완료하려면 몇 분 정도 걸립니다. t5-small대형 모델을 사용하는 경우 빌드 프로세스에 상당한 시간이 걸릴 수 있습니다.

  3. 이미지가 저장소에 있는지 확인합니다.

    gcloud artifacts docker images list us-central1-docker.pkg.dev/PROJECT_ID/models
    

    PROJECT_ID를 Google Cloud프로젝트 ID로 바꿉니다.

    출력은 다음과 비슷합니다.

    IMAGE                                                     DIGEST         CREATE_TIME          UPDATE_TIME
    us-central1-docker.pkg.dev/PROJECT_ID/models/t5-small     sha256:0cd...  2023-06-14T12:06:38  2023-06-14T12:06:38
    

패키징된 모델을 GKE에 배포

이 튜토리얼에서는 이미지를 배포하기 위해 Kubernetes 배포를 사용합니다. 배포는 클러스터에서 노드 간에 배포되는 여러 포드 복제본을 실행할 수 있는 Kubernetes API 객체입니다.

예시 저장소에서 Kubernetes 매니페스트를 환경에 맞게 수정합니다.

  1. 추론 워크로드의 매니페스트를 검토합니다.

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     https://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: t5-inference
      labels:
        model: t5
        version: v1.0
        machine: gpu
    spec:
      replicas: 1
      selector:
        matchLabels:
          model: t5
          version: v1.0
          machine: gpu
      template:
        metadata:
          labels:
            model: t5
            version: v1.0
            machine: gpu
        spec:
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          securityContext:
            fsGroup: 1000
            runAsUser: 1000
            runAsGroup: 1000
          containers:
            - name: inference
              image: us-central1-docker.pkg.dev/PROJECT_ID/models/t5-small:1.0-gpu
              imagePullPolicy: IfNotPresent
              args: ["torchserve", "--start", "--foreground"]
              resources:
                limits:
                  nvidia.com/gpu: "1"
                  cpu: "3000m"
                  memory: 16Gi
                  ephemeral-storage: 10Gi
                requests:
                  nvidia.com/gpu: "1"
                  cpu: "3000m"
                  memory: 16Gi
                  ephemeral-storage: 10Gi
              ports:
                - containerPort: 8080
                  name: http
                - containerPort: 8081
                  name: management
                - containerPort: 8082
                  name: metrics
              readinessProbe:
                httpGet:
                  path: /ping
                  port: http
                initialDelaySeconds: 120
                failureThreshold: 10
              livenessProbe:
                httpGet:
                  path: /models/t5-small
                  port: management
                initialDelaySeconds: 150
                periodSeconds: 5
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: t5-inference
      labels:
        model: t5
        version: v1.0
        machine: gpu
    spec:
      type: ClusterIP
      selector:
        model: t5
        version: v1.0
        machine: gpu
      ports:
        - port: 8080
          name: http
          targetPort: http
        - port: 8081
          name: management
          targetPort: management
        - port: 8082
          name: metrics
          targetPort: metrics
    

  2. PROJECT_ID를 Google Cloud프로젝트 ID로 바꿉니다.

    sed -i "s/PROJECT_ID/PROJECT_ID/g" "kubernetes/serving-gpu.yaml"
    

    이렇게 하면 배포 사양의 컨테이너 이미지 경로가 Artifact Registry에 있는 T5 모델 이미지 경로와 일치합니다.

  3. Kubernetes 리소스를 만듭니다.

    kubectl create -f kubernetes/serving-gpu.yaml
    

모델이 성공적으로 배포되었는지 확인하려면 다음을 수행합니다.

  1. 배포 및 서비스의 상태를 가져옵니다.

    kubectl get -f kubernetes/serving-gpu.yaml
    

    출력에 다음과 같이 준비된 포드가 표시될 때까지 기다립니다. 이미지의 크기에 따라 첫 이미지 가져오기에 몇 분 정도 걸릴 수 있습니다.

    NAME                            READY   UP-TO-DATE    AVAILABLE   AGE
    deployment.apps/t5-inference    1/1     1             0           66s
    
    NAME                    TYPE        CLUSTER-IP        EXTERNAL-IP   PORT(S)                       AGE
    service/t5-inference    ClusterIP   10.48.131.86    <none>        8080/TCP,8081/TCP,8082/TCP    66s
    
  2. t5-inference 서비스의 로컬 포트를 엽니다.

    kubectl port-forward svc/t5-inference 8080
    
  3. 새 터미널 창을 열고 서비스에 테스트 요청을 보냅니다.

    curl -v -X POST -H 'Content-Type: application/json' -d '{"text": "this is a test sentence", "from": "en", "to": "fr"}' "http://localhost:8080/predictions/t5-small/1.0"
    

    테스트 요청이 실패하고 포드 연결이 닫히면 로그를 확인합니다.

    kubectl logs deployments/t5-inference
    

    출력이 다음과 비슷하면 TorchServe가 일부 모델 종속 항목을 설치하지 못한 것입니다.

    org.pytorch.serve.archive.model.ModelException: Custom pip package installation failed for t5-small
    

    이 문제를 해결하려면 배포를 다시 시작합니다.

    kubectl rollout restart deployment t5-inference
    

    배포 컨트롤러가 새 포드를 만듭니다. 이전 단계를 반복하여 새 포드에서 포트를 엽니다.

웹 애플리케이션을 사용하여 배포된 모델에 액세스

Fast Dash 웹 애플리케이션으로 배포된 모델에 액세스하려면 다음 단계를 완료하세요.

  1. Fast Dash 웹 애플리케이션을 빌드하고 Artifact Registry에서 컨테이너 이미지로 푸시합니다.

    gcloud builds submit client-app/ \
        --region=us-central1 \
        --config=client-app/cloudbuild.yaml
    
  2. 텍스트 편집기에서 kubernetes/application.yaml을 열고 image: 필드의 PROJECT_ID를 프로젝트 ID로 바꿉니다. 또는 다음 명령어를 실행합니다.

    sed -i "s/PROJECT_ID/PROJECT_ID/g" "kubernetes/application.yaml"
    
  3. Kubernetes 리소스를 만듭니다.

    kubectl create -f kubernetes/application.yaml
    

    배포 및 서비스가 완전히 프로비저닝되는 데 다소 시간이 걸릴 수 있습니다.

  4. 상태를 확인하려면 다음 명령어를 실행하세요.

    kubectl get -f kubernetes/application.yaml
    

    출력에 다음과 같이 준비된 포드가 표시될 때까지 기다립니다.

    NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/fastdash   1/1     1            0           1m
    
    NAME               TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    service/fastdash   NodePort   203.0.113.12    <none>        8050/TCP         1m
    
  5. 외부 IP 주소에 노출되지 않았지만 이제 웹 애플리케이션이 실행됩니다. 웹 애플리케이션에 액세스하려면 로컬 포트를 엽니다.

    kubectl port-forward service/fastdash 8050
    
  6. 브라우저에서 웹 인터페이스를 엽니다.

    • 로컬 셸을 사용하는 경우 브라우저를 열고 http://127.0.0.1:8050으로 이동합니다.
    • Cloud Shell을 사용하는 경우 웹 미리보기를 클릭한 다음 포트 변경을 클릭합니다. 포트를 8050으로 지정합니다.
  7. T5 모델에 요청을 보내려면 웹 인터페이스에서 TEXT, FROM LANG, TO LANG 필드에 값을 지정하고 제출을 클릭합니다. 사용 가능한 언어 목록은 T5 문서를 참조하세요.

모델에 자동 확장 사용 설정

이 섹션에서는 다음을 수행하여 Google Cloud Managed Service for Prometheus의 측정항목을 기반으로 모델에 자동 확장을 사용 설정하는 방법을 보여줍니다.

  1. 커스텀 측정항목 Stackdriver 어댑터 설치
  2. PodMonitoring 및 HorizontalPodAutoscaling 구성 적용

Google Cloud Managed Service for Prometheus는 버전 1.25 이상을 실행하는 Autopilot 클러스터에서 기본적으로 사용 설정됩니다.

커스텀 측정항목 Stackdriver 어댑터 설치

이 어댑터를 사용하면 클러스터가 Prometheus의 측정항목을 사용하여 Kubernetes 자동 확장 결정을 내릴 수 있습니다.

  1. 어댑터를 배포합니다.

    kubectl create -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
    
  2. 어댑터에서 사용할 IAM 서비스 계정을 만듭니다.

    gcloud iam service-accounts create monitoring-viewer
    
  3. IAM 서비스 계정에 프로젝트에 대한 monitoring.viewer 역할 및 iam.workloadIdentityUser 역할을 부여합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:monitoring-viewer@PROJECT_ID.iam.gserviceaccount.com" \
        --role roles/monitoring.viewer
    gcloud iam service-accounts add-iam-policy-binding monitoring-viewer@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:PROJECT_ID.svc.id.goog[custom-metrics/custom-metrics-stackdriver-adapter]"
    

    PROJECT_ID를 Google Cloud프로젝트 ID로 바꿉니다.

  4. IAM 서비스 계정을 가장하도록 어댑터의 Kubernetes ServiceAccount에 주석을 추가합니다.

    kubectl annotate serviceaccount custom-metrics-stackdriver-adapter \
        --namespace custom-metrics \
        iam.gke.io/gcp-service-account=monitoring-viewer@PROJECT_ID.iam.gserviceaccount.com
    
  5. 변경사항이 전파되도록 어댑터를 다시 시작합니다.

    kubectl rollout restart deployment custom-metrics-stackdriver-adapter \
        --namespace=custom-metrics
    

PodMonitoring 및 HorizontalPodAutoscaling 구성 적용

PodMonitoring은 특정 네임스페이스에서 측정항목 수집 및 대상 스크래핑을 사용 설정하는 Google Cloud Managed Service for Prometheus 커스텀 리소스입니다.

  1. TorchServe 배포와 동일한 네임스페이스에 PodMonitoring 리소스를 배포합니다.

    kubectl apply -f kubernetes/pod-monitoring.yaml
    
  2. HorizontalPodAutoscaler 매니페스트를 검토합니다.

    # Copyright 2023 Google LLC
    #
    # Licensed under the Apache License, Version 2.0 (the "License");
    # you may not use this file except in compliance with the License.
    # You may obtain a copy of the License at
    #
    #     https://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    
    apiVersion: autoscaling/v2
    kind: HorizontalPodAutoscaler
    metadata:
      name: t5-inference
    spec:
      scaleTargetRef:
        apiVersion: apps/v1
        kind: Deployment
        name: t5-inference
      minReplicas: 1
      maxReplicas: 5
      metrics:
      - type: Pods
        pods:
          metric:
            name: prometheus.googleapis.com|ts_queue_latency_microseconds|counter
          target:
            type: AverageValue
            averageValue: "30000"
    

    HorizontalPodAutoscaler는 요청 큐의 누적 기간을 기준으로 T5 모델 포드 수량을 확장합니다. 자동 확장은 마이크로초 단위로 누적 큐 기간을 표시하는 ts_queue_latency_microseconds 측정항목을 기반으로 합니다.

  3. HorizontalPodAutoscaler를 만듭니다.

    kubectl apply -f kubernetes/hpa.yaml
    

부하 생성기를 사용하여 자동 확장 확인

자동 확장 구성을 테스트하려면 서빙 애플리케이션의 부하를 생성합니다. 이 튜토리얼에서는 Locust 부하 생성기를 사용하여 모델의 예측 엔드포인트에 요청을 전송합니다.

  1. 부하 생성기를 만듭니다.

    kubectl apply -f kubernetes/loadgenerator.yaml
    

    부하 생성기 포드가 준비될 때까지 기다립니다.

  2. 부하 생성기 웹 인터페이스를 로컬로 노출합니다.

    kubectl port-forward svc/loadgenerator 8080
    

    오류 메시지가 표시되면 포드가 실행될 때 다시 시도합니다.

  3. 브라우저에서 부하 생성기 웹 인터페이스를 엽니다.

    • 로컬 셸을 사용하는 경우 브라우저를 열고 http://127.0.0.1:8080으로 이동합니다.
    • Cloud Shell을 사용하는 경우 웹 미리보기를 클릭한 다음 포트 변경을 클릭합니다. 포트 8080을 입력합니다.
  4. 차트 탭을 클릭하여 시간별 성능을 관측합니다.

  5. 새 터미널 창을 열고 수평형 포드 자동 확장 처리의 복제본 수를 관찰합니다.

    kubectl get hpa -w
    

    부하가 증가하면 복제본 수가 증가합니다. 확장에는 약 10분 정도 걸릴 수 있습니다. 새 복제본이 시작되면 Locust 차트의 성공적인 요청 수가 증가합니다.

    NAME           REFERENCE                 TARGETS           MINPODS   MAXPODS   REPLICAS   AGE
    t5-inference   Deployment/t5-inference   71352001470m/7M   1         5        1           2m11s
    

권장사항

  • 서빙에 사용할 기본 Docker 이미지와 동일한 버전으로 모델을 빌드합니다.
  • 모델에 특별한 패키지 종속 항목이 있거나 종속 항목 크기가 크면 기본 Docker 이미지의 커스텀 버전을 만듭니다.
  • 모델 종속 항목 패키지의 트리 버전을 확인합니다. 패키지 종속 항목 버전이 서로 지원되는지 확인합니다. 예를 들어 Panda 버전 2.0.3은 NumPy 버전 1.20.3 이상을 지원합니다.
  • GPU 노드에서 GPU를 많이 사용하는 모델을 실행하고, CPU에서 CPU를 많이 사용하는 모델을 실행합니다. 이렇게 하면 모델 서빙의 안정성이 개선되고 노드 리소스를 효율적으로 소비할 수 있습니다.

모델 성능 관찰

모델 성능을 모니터링하려면 Cloud Monitoring에 통합된 TorchServe 대시보드를 사용할 수 있습니다. 이 대시보드를 통해 토큰 처리량, 요청 지연 시간, 오류율 등의 주요 성능 측정항목을 확인할 수 있습니다.

TorchServe 대시보드를 사용하려면 GKE 클러스터에서 Google Cloud Managed Service for Prometheus를 사용 설정해야 합니다. 이 서비스는 GKE 클러스터의 TorchServe에서 측정항목을 수집합니다. TorchServe는 기본적으로 Prometheus 형식으로 측정항목을 노출하므로, 별도의 내보내기 도구를 설치할 필요가 없습니다.

이후에는 TorchServe 대시보드를 통해 측정항목을 확인할 수 있습니다. Google Cloud Managed Service for Prometheus를 사용하여 모델에서 측정항목을 수집하는 방법은 Cloud Monitoring 문서의 TorchServe 모니터링 가능성 가이드를 참조하세요.