GKE 추론 게이트웨이로 LLM 제공


이 튜토리얼에서는 GKE 추론 게이트웨이를 사용하여 Google Kubernetes Engine (GKE)에 대규모 언어 모델 (LLM)을 배포하는 방법을 설명합니다. 이 튜토리얼에는 클러스터 설정, 모델 배포, GKE 추론 게이트웨이 구성, LLM 요청 처리 단계가 포함되어 있습니다.

이 튜토리얼은 GKE 추론 게이트웨이를 사용하여 GKE에서 LLM을 사용하여 LLM 애플리케이션을 배포하고 관리하려는 머신러닝 (ML) 엔지니어, 플랫폼 관리자 및 운영자, 데이터 및 AI 전문가를 대상으로 합니다.

이 페이지를 읽기 전에 다음 사항을 숙지하세요.

배경

이 섹션에서는 이 튜토리얼에서 사용되는 주요 기술을 설명합니다. 모델 제공 개념 및 용어, GKE 생성형 AI 기능이 모델 제공 성능을 향상하고 지원하는 방법에 관한 자세한 내용은 GKE의 모델 추론 정보를 참고하세요.

vLLM

vLLM은 GPU의 제공 처리량을 늘릴 수 있는 고도로 최적화된 오픈소스 LLM 제공 프레임워크로 다음과 같은 기능을 제공합니다.

  • PagedAttention으로 최적화된 Transformer구현
  • 전체 제공 처리량을 개선하는 연속적인 작업 일괄 처리
  • 여러 GPU에서 텐서 동시 로드 및 분산 제공

자세한 내용은 vLLM 문서를 참고하세요.

GKE 추론 게이트웨이

GKE 추론 게이트웨이는 LLM을 제공하기 위한 GKE의 기능을 향상시킵니다. 다음과 같은 기능으로 추론 워크로드를 최적화합니다.

  • 부하 측정항목을 기반으로 추론 최적화 부하 분산
  • LoRA 어댑터의 다중 워크로드 서비스를 지원합니다.
  • 간소화된 작업을 위한 모델 인식 라우팅

자세한 내용은 GKE 추론 게이트웨이 정보를 참고하세요.

목표

  1. 모델 액세스 권한 얻기
  2. 개발 환경 준비
  3. Google Cloud 리소스 만들기 및 구성
  4. InferenceModelInferencePool CRD를 설치합니다.
  5. 모델 서버 배포
  6. 추론 게이트웨이의 관측 가능성 구성

시작하기 전에

  • 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.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  • Make sure that billing is enabled for your Google Cloud project.

  • Enable the required API.

    Enable the API

  • Make sure that you have the following role or roles on the project: roles/container.admin, roles/iam.serviceAccountAdmin

    Check for the roles

    1. In the Google Cloud console, go to the IAM page.

      Go to IAM
    2. Select the project.
    3. In the Principal column, find all rows that identify you or a group that you're included in. To learn which groups you're included in, contact your administrator.

    4. For all rows that specify or include you, check the Role column to see whether the list of roles includes the required roles.

    Grant the roles

    1. In the Google Cloud console, go to the IAM page.

      IAM으로 이동
    2. 프로젝트를 선택합니다.
    3. 액세스 권한 부여를 클릭합니다.
    4. 새 주 구성원 필드에 사용자 식별자를 입력합니다. 일반적으로 Google 계정의 이메일 주소입니다.

    5. 역할 선택 목록에서 역할을 선택합니다.
    6. 역할을 추가로 부여하려면 다른 역할 추가를 클릭하고 각 역할을 추가합니다.
    7. 저장을 클릭합니다.

모델 액세스 권한 얻기

Llama3.1 모델을 GKE에 배포하려면 라이선스 동의 계약에 서명하고 Hugging Face 액세스 토큰을 생성합니다.

Llama3.1 모델을 사용하려면 동의 계약에 서명해야 합니다. 다음 안내를 따르세요.

  1. 동의 페이지에 액세스하여 Hugging Face 계정 사용에 대한 동의를 확인합니다.
  2. 모델 약관에 동의합니다.

액세스 토큰 생성

Hugging Face를 통해 모델에 액세스하려면 Hugging Face 토큰이 필요합니다.

아직 토큰이 없으면 다음 단계에 따라 새 토큰을 생성합니다.

  1. 내 프로필 > 설정 > 액세스 토큰을 클릭합니다.
  2. 새 토큰을 선택합니다.
  3. 원하는 이름과 Read 이상의 역할을 지정합니다.
  4. 토큰 생성을 선택합니다.
  5. 클립보드에 생성된 토큰을 복사합니다.

개발 환경 준비

이 튜토리얼에서는 Cloud Shell을 사용하여Google Cloud에서 호스팅되는 리소스를 관리합니다. Cloud Shell에는 kubectl gcloud CLI 등 이 튜토리얼에 필요한 소프트웨어가 사전 설치되어 있습니다.

Cloud Shell로 환경을 설정하려면 다음 단계를 따르세요.

  1. Google Cloud 콘솔에서 Google Cloud 콘솔Cloud Shell 활성화 아이콘 Cloud Shell 활성화를 클릭하여 Cloud Shell 세션을 시작합니다. 그러면 Google Cloud 콘솔 하단 창에서 세션이 시작됩니다.

  2. 기본 환경 변수를 설정합니다.

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    export REGION=REGION
    export CLUSTER_NAME=CLUSTER_NAME
    export HF_TOKEN=HF_TOKEN
    

    다음 값을 바꿉니다.

    • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
    • REGION: 사용하려는 가속기 유형을 지원하는 리전(예: H100 GPU의 경우 us-central1)입니다.
    • CLUSTER_NAME: 클러스터 이름입니다.
    • HF_TOKEN: 이전에 생성한 Hugging Face 토큰입니다.

Google Cloud 리소스 만들기 및 구성

필요한 리소스를 만들려면 다음 안내를 따르세요.

GKE 클러스터 및 노드 풀 만들기

GKE Autopilot 또는 Standard 클러스터의 GPU에서 LLM을 제공합니다. 완전 관리형 Kubernetes 환경을 위해서는 Autopilot을 사용하는 것이 좋습니다. 워크로드에 가장 적합한 GKE 작업 모드를 선택하려면 GKE 작업 모드 선택을 참조하세요.

Autopilot

Cloud Shell에서 다음 명령어를 실행합니다.

gcloud container clusters create-auto CLUSTER_NAME \
    --project=PROJECT_ID \
    --region=REGION \
    --release-channel=rapid \
    --cluster-version=1.32.3-gke.1170000

다음 값을 바꿉니다.

  • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
  • REGION: 사용하려는 가속기 유형을 지원하는 리전(예: H100 GPU의 경우 us-central1)입니다.
  • CLUSTER_NAME: 클러스터 이름입니다.

GKE는 배포된 워크로드의 요청에 따라 CPU 및 GPU 노드를 사용하여 Autopilot 클러스터를 만듭니다.

Standard

  1. Cloud Shell에서 다음 명령어를 실행하여 Standard 클러스터를 만듭니다.

    gcloud container clusters create CLUSTER_NAME \
        --project=PROJECT_ID \
        --region=REGION \
        --workload-pool=PROJECT_ID.svc.id.goog \
        --release-channel=rapid \
        --num-nodes=1 \
        --enable-managed-prometheus \
        --monitoring=SYSTEM,DCGM \
        --cluster-version=1.32.3-gke.1170000
    

    다음 값을 바꿉니다.

    • PROJECT_ID: Google Cloud 프로젝트 ID입니다.
    • REGION: 사용하려는 가속기 유형을 지원하는 리전(예: H100 GPU의 경우 us-central1)입니다.
    • CLUSTER_NAME: 클러스터 이름입니다.

    클러스터 만들기는 몇 분 정도 걸릴 수 있습니다.

  2. Llama-3.1-8B-Instruct 모델을 실행하는 데 적절한 디스크 크기로 노드 풀을 만들려면 다음 명령어를 실행합니다.

    gcloud container node-pools create gpupool \
        --accelerator type=nvidia-h100-80gb,count=2,gpu-driver-version=latest \
        --project=PROJECT_ID \
        --location=REGION \
        --node-locations=REGION-a \
        --cluster=CLUSTER_NAME \
        --machine-type=a3-highgpu-2g \
        --num-nodes=1 \
        --disk-type="pd-standard"
    

    GKE는 H100 GPU가 포함된 단일 노드 풀을 만듭니다.

  1. 측정항목을 스크래핑할 수 있는 승인을 설정하려면 inference-gateway-sa-metrics-reader-secret 보안 비밀을 만듭니다.

    kubectl apply -f - <<EOF
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: inference-gateway-metrics-reader
    rules:
    - nonResourceURLs:
      - /metrics
      verbs:
      - get
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: inference-gateway-sa-metrics-reader
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: inference-gateway-sa-metrics-reader-role-binding
      namespace: default
    subjects:
    - kind: ServiceAccount
      name: inference-gateway-sa-metrics-reader
      namespace: default
    roleRef:
      kind: ClusterRole
      name: inference-gateway-metrics-reader
      apiGroup: rbac.authorization.k8s.io
    ---
    apiVersion: v1
    kind: Secret
    metadata:
      name: inference-gateway-sa-metrics-reader-secret
      namespace: default
      annotations:
        kubernetes.io/service-account.name: inference-gateway-sa-metrics-reader
    type: kubernetes.io/service-account-token
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: inference-gateway-sa-metrics-reader-secret-read
    rules:
    - resources:
      - secrets
      apiGroups: [""]
      verbs: ["get", "list", "watch"]
      resourceNames: ["inference-gateway-sa-metrics-reader-secret"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: gmp-system:collector:inference-gateway-sa-metrics-reader-secret-read
      namespace: default
    roleRef:
      name: inference-gateway-sa-metrics-reader-secret-read
      kind: ClusterRole
      apiGroup: rbac.authorization.k8s.io
    subjects:
    - name: collector
      namespace: gmp-system
      kind: ServiceAccount
    EOF
    

Hugging Face 사용자 인증 정보용 Kubernetes 보안 비밀 만들기

Cloud Shell에서 다음을 수행합니다.

  1. 클러스터와 통신하려면 kubectl를 구성합니다.

      gcloud container clusters get-credentials CLUSTER_NAME \
          --location=REGION
    

    다음 값을 바꿉니다.

    • REGION: 사용하려는 가속기 유형을 지원하는 리전(예: H100 GPU의 경우 us-central1)입니다.
    • CLUSTER_NAME: 클러스터 이름입니다.
  2. Hugging Face 토큰이 포함된 Kubernetes 보안 비밀을 만듭니다.

      kubectl create secret generic HF_SECRET \
          --from-literal=token=HF_TOKEN \
          --dry-run=client -o yaml | kubectl apply -f -
    

    다음을 바꿉니다.

    • HF_TOKEN: 이전에 생성한 Hugging Face 토큰입니다.
    • HF_SECRET: Kubernetes 보안 비밀의 이름입니다. 예를 들면 hf-secret입니다.

InferenceModelInferencePool CRD 설치

이 섹션에서는 GKE 추론 게이트웨이에 필요한 커스텀 리소스 정의 (CRD)를 설치합니다.

CRD는 Kubernetes API를 확장합니다. 이를 통해 새 리소스 유형을 정의할 수 있습니다. GKE 추론 게이트웨이를 사용하려면 다음 명령어를 실행하여 GKE 클러스터에 InferencePoolInferenceModel CRD를 설치합니다.

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api-inference-extension/releases/download/v0.3.0/manifests.yaml

모델 서버 배포

이 예에서는 vLLM 모델 서버를 사용하여 Llama3.1 모델을 배포합니다. 배포 라벨은 app:vllm-llama3-8b-instruct입니다. 이 배포에서는 Hugging Face의 food-reviewcad-fabricator라는 두 개의 LoRA 어댑터도 사용합니다. 자체 모델 서버 및 모델 컨테이너, 제공 포트, 배포 이름으로 이 배포를 업데이트할 수 있습니다. 원하는 경우 배포에서 LoRA 어댑터를 구성하거나 기본 모델을 배포할 수 있습니다.

  1. nvidia-h100-80gb 가속기 유형에 배포하려면 다음 매니페스트를 vllm-llama3-8b-instruct.yaml로 저장합니다. 이 매니페스트는 모델 및 모델 서버가 포함된 Kubernetes 배포를 정의합니다.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: vllm-llama3-8b-instruct
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: vllm-llama3-8b-instruct
      template:
        metadata:
          labels:
            app: vllm-llama3-8b-instruct
        spec:
          containers:
            - name: vllm
              image: "vllm/vllm-openai:latest"
              imagePullPolicy: Always
              command: ["python3", "-m", "vllm.entrypoints.openai.api_server"]
              args:
              - "--model"
              - "meta-llama/Llama-3.1-8B-Instruct"
              - "--tensor-parallel-size"
              - "1"
              - "--port"
              - "8000"
              - "--enable-lora"
              - "--max-loras"
              - "2"
              - "--max-cpu-loras"
              - "12"
              env:
                # Enabling LoRA support temporarily disables automatic v1, we want to force it on
                # until 0.8.3 vLLM is released.
                - name: VLLM_USE_V1
                  value: "1"
                - name: PORT
                  value: "8000"
                - name: HUGGING_FACE_HUB_TOKEN
                  valueFrom:
                    secretKeyRef:
                      name: hf-token
                      key: token
                - name: VLLM_ALLOW_RUNTIME_LORA_UPDATING
                  value: "true"
              ports:
                - containerPort: 8000
                  name: http
                  protocol: TCP
              lifecycle:
                preStop:
                  # vLLM stops accepting connections when it receives SIGTERM, so we need to sleep
                  # to give upstream gateways a chance to take us out of rotation. The time we wait
                  # is dependent on the time it takes for all upstreams to completely remove us from
                  # rotation. Older or simpler load balancers might take upwards of 30s, but we expect
                  # our deployment to run behind a modern gateway like Envoy which is designed to
                  # probe for readiness aggressively.
                  sleep:
                    # Upstream gateway probers for health should be set on a low period, such as 5s,
                    # and the shorter we can tighten that bound the faster that we release
                    # accelerators during controlled shutdowns. However, we should expect variance,
                    # as load balancers may have internal delays, and we don't want to drop requests
                    # normally, so we're often aiming to set this value to a p99 propagation latency
                    # of readiness -> load balancer taking backend out of rotation, not the average.
                    #
                    # This value is generally stable and must often be experimentally determined on
                    # for a given load balancer and health check period. We set the value here to
                    # the highest value we observe on a supported load balancer, and we recommend
                    # tuning this value down and verifying no requests are dropped.
                    #
                    # If this value is updated, be sure to update terminationGracePeriodSeconds.
                    #
                    seconds: 30
                  #
                  # IMPORTANT: preStop.sleep is beta as of Kubernetes 1.30 - for older versions
                  # replace with this exec action.
                  #exec:
                  #  command:
                  #  - /usr/bin/sleep
                  #  - 30
              livenessProbe:
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                # vLLM's health check is simple, so we can more aggressively probe it.  Liveness
                # check endpoints should always be suitable for aggressive probing.
                periodSeconds: 1
                successThreshold: 1
                # vLLM has a very simple health implementation, which means that any failure is
                # likely significant. However, any liveness triggered restart requires the very
                # large core model to be reloaded, and so we should bias towards ensuring the
                # server is definitely unhealthy vs immediately restarting. Use 5 attempts as
                # evidence of a serious problem.
                failureThreshold: 5
                timeoutSeconds: 1
              readinessProbe:
                httpGet:
                  path: /health
                  port: http
                  scheme: HTTP
                # vLLM's health check is simple, so we can more aggressively probe it.  Readiness
                # check endpoints should always be suitable for aggressive probing, but may be
                # slightly more expensive than readiness probes.
                periodSeconds: 1
                successThreshold: 1
                # vLLM has a very simple health implementation, which means that any failure is
                # likely significant,
                failureThreshold: 1
                timeoutSeconds: 1
              # We set a startup probe so that we don't begin directing traffic or checking
              # liveness to this instance until the model is loaded.
              startupProbe:
                # Failure threshold is when we believe startup will not happen at all, and is set
                # to the maximum possible time we believe loading a model will take. In our
                # default configuration we are downloading a model from HuggingFace, which may
                # take a long time, then the model must load into the accelerator. We choose
                # 10 minutes as a reasonable maximum startup time before giving up and attempting
                # to restart the pod.
                #
                # IMPORTANT: If the core model takes more than 10 minutes to load, pods will crash
                # loop forever. Be sure to set this appropriately.
                failureThreshold: 3600
                # Set delay to start low so that if the base model changes to something smaller
                # or an optimization is deployed, we don't wait unnecessarily.
                initialDelaySeconds: 2
                # As a startup probe, this stops running and so we can more aggressively probe
                # even a moderately complex startup - this is a very important workload.
                periodSeconds: 1
                httpGet:
                  # vLLM does not start the OpenAI server (and hence make /health available)
                  # until models are loaded. This may not be true for all model servers.
                  path: /health
                  port: http
                  scheme: HTTP
    
              resources:
                limits:
                  nvidia.com/gpu: 1
                requests:
                  nvidia.com/gpu: 1
              volumeMounts:
                - mountPath: /data
                  name: data
                - mountPath: /dev/shm
                  name: shm
                - name: adapters
                  mountPath: "/adapters"
          initContainers:
            - name: lora-adapter-syncer
              tty: true
              stdin: true
              image: us-central1-docker.pkg.dev/k8s-staging-images/gateway-api-inference-extension/lora-syncer:main
              restartPolicy: Always
              imagePullPolicy: Always
              env:
                - name: DYNAMIC_LORA_ROLLOUT_CONFIG
                  value: "/config/configmap.yaml"
              volumeMounts: # DO NOT USE subPath, dynamic configmap updates don't work on subPaths
              - name: config-volume
                mountPath:  /config
          restartPolicy: Always
    
          # vLLM allows VLLM_PORT to be specified as an environment variable, but a user might
          # create a 'vllm' service in their namespace. That auto-injects VLLM_PORT in docker
          # compatible form as `tcp://<IP>:<PORT>` instead of the numeric value vLLM accepts
          # causing CrashLoopBackoff. Set service environment injection off by default.
          enableServiceLinks: false
    
          # Generally, the termination grace period needs to last longer than the slowest request
          # we expect to serve plus any extra time spent waiting for load balancers to take the
          # model server out of rotation.
          #
          # An easy starting point is the p99 or max request latency measured for your workload,
          # although LLM request latencies vary significantly if clients send longer inputs or
          # trigger longer outputs. Since steady state p99 will be higher than the latency
          # to drain a server, you may wish to slightly this value either experimentally or
          # via the calculation below.
          #
          # For most models you can derive an upper bound for the maximum drain latency as
          # follows:
          #
          #   1. Identify the maximum context length the model was trained on, or the maximum
          #      allowed length of output tokens configured on vLLM (llama2-7b was trained to
          #      4k context length, while llama3-8b was trained to 128k).
          #   2. Output tokens are the more compute intensive to calculate and the accelerator
          #      will have a maximum concurrency (batch size) - the time per output token at
          #      maximum batch with no prompt tokens being processed is the slowest an output
          #      token can be generated (for this model it would be about 100ms TPOT at a max
          #      batch size around 50)
          #   3. Calculate the worst case request duration if a request starts immediately
          #      before the server stops accepting new connections - generally when it receives
          #      SIGTERM (for this model that is about 4096 / 10 ~ 40s)
          #   4. If there are any requests generating prompt tokens that will delay when those
          #      output tokens start, and prompt token generation is roughly 6x faster than
          #      compute-bound output token generation, so add 20% to the time from above (40s +
          #      16s ~ 55s)
          #
          # Thus we think it will take us at worst about 55s to complete the longest possible
          # request the model is likely to receive at maximum concurrency (highest latency)
          # once requests stop being sent.
          #
          # NOTE: This number will be lower than steady state p99 latency since we stop       receiving
          #       new requests which require continuous prompt token computation.
              # NOTE: The max timeout for backend connections from gateway to model servers should
          #       be configured based on steady state p99 latency, not drain p99 latency
          #
          #   5. Add the time the pod takes in its preStop hook to allow the load balancers have
          #      stopped sending us new requests (55s + 30s ~ 85s)
          #
          # Because the termination grace period controls when the Kubelet forcibly terminates a
          # stuck or hung process (a possibility due to a GPU crash), there is operational safety
          # in keeping the value roughly proportional to the time to finish serving. There is also
          # value in adding a bit of extra time to deal with unexpectedly long workloads.
          #
          #   6. Add a 50% safety buffer to this time since the operational impact should be low
          #      (85s * 1.5 ~ 130s)
          #
          # One additional source of drain latency is that some workloads may run close to
          # saturation and have queued requests on each server. Since traffic in excess of the
          # max sustainable QPS will result in timeouts as the queues grow, we assume that failure
          # to drain in time due to excess queues at the time of shutdown is an expected failure
          # mode of server overload. If your workload occasionally experiences high queue depths
          # due to periodic traffic, consider increasing the safety margin above to account for
          # time to drain queued requests.
          terminationGracePeriodSeconds: 130
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-h100-80gb"
          volumes:
            - name: data
              emptyDir: {}
            - name: shm
              emptyDir:
                medium: Memory
            - name: adapters
              emptyDir: {}
            - name: config-volume
              configMap:
                name: vllm-llama3-8b-adapters
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: vllm-llama3-8b-adapters
    data:
      configmap.yaml: |
          vLLMLoRAConfig:
            name: vllm-llama3.1-8b-instruct
            port: 8000
            defaultBaseModel: meta-llama/Llama-3.1-8B-Instruct
            ensureExist:
              models:
              - id: food-review
                source: Kawon/llama3.1-food-finetune_v14_r8
              - id: cad-fabricator
                source: redcathode/fabricator
    ---
    kind: HealthCheckPolicy
    apiVersion: networking.gke.io/v1
    metadata:
      name: health-check-policy
      namespace: default
    spec:
      targetRef:
        group: "inference.networking.x-k8s.io"
        kind: InferencePool
        name: vllm-llama3-8b-instruct
      default:
        config:
          type: HTTP
          httpHealthCheck:
              requestPath: /health
              port: 8000
    
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f vllm-llama3-8b-instruct.yaml
    

InferencePool 리소스 만들기

InferencePool Kubernetes 커스텀 리소스는 공통 기본 LLM 및 컴퓨팅 구성으로 포드 그룹을 정의합니다.

InferencePool 맞춤 리소스에는 다음과 같은 주요 필드가 포함됩니다.

  • selector: 이 풀에 속하는 포드를 지정합니다. 이 선택기의 라벨은 모델 서버 Pod에 적용된 라벨과 정확하게 일치해야 합니다.
  • targetPort: 포드 내에서 모델 서버가 사용하는 포트를 정의합니다.

InferencePool 리소스를 사용하면 GKE 추론 게이트웨이가 트래픽을 모델 서버 포드로 라우팅할 수 있습니다.

Helm을 사용하여 InferencePool를 만들려면 다음 단계를 따르세요.

helm install vllm-llama3-8b-instruct \
  --set inferencePool.modelServers.matchLabels.app=vllm-llama3-8b-instruct \
  --set provider.name=gke \
  --set healthCheckPolicy.create=false \
  --version v0.3.0 \
  oci://registry.k8s.io/gateway-api-inference-extension/charts/inferencepool

배포와 일치하도록 다음 필드를 변경합니다.

  • inferencePool.modelServers.matchLabels.app: 모델 서버 Pod를 선택하는 데 사용되는 라벨의 키입니다.

이 명령어는 모델 서버 배포를 논리적으로 나타내고 Selector가 선택한 포드 내의 모델 엔드포인트 서비스를 참조하는 InferencePool 객체를 만듭니다.

게재 중요도가 있는 InferenceModel 리소스 만들기

InferenceModel Kubernetes 커스텀 리소스는 LoRA 조정 모델을 비롯한 특정 모델과 서비스 중요성을 정의합니다.

InferenceModel 맞춤 리소스에는 다음과 같은 주요 필드가 포함됩니다.

  • modelName: 기본 모델 또는 LoRA 어댑터의 이름을 지정합니다.
  • Criticality: 모델의 게재 중요도를 지정합니다.
  • poolRef: 모델이 제공되는 InferencePool를 참조합니다.

InferenceModel를 사용하면 GKE 추론 게이트웨이가 모델 이름과 중요도를 기반으로 모델 서버 포드로 트래픽을 라우팅할 수 있습니다.

InferenceModel를 만들려면 다음 단계를 따르세요.

  1. 다음 샘플 매니페스트를 inferencemodel.yaml로 저장합니다.

    apiVersion: inference.networking.x-k8s.io/v1alpha2
    kind: InferenceModel
    metadata:
      name: inferencemodel-sample
    spec:
      modelName: MODEL_NAME
      criticality: CRITICALITY
      poolRef:
        name: INFERENCE_POOL_NAME
    

    다음을 바꿉니다.

    • MODEL_NAME: 기본 모델 또는 LoRA 어댑터의 이름입니다. 예를 들면 food-review입니다.
    • CRITICALITY: 선택한 게재 중요도입니다. Critical, Standard 또는 Sheddable 중에서 선택합니다. 예를 들면 Standard입니다.
    • INFERENCE_POOL_NAME: 이전 단계에서 만든 InferencePool의 이름입니다. 예를 들면 vllm-llama3-8b-instruct입니다.
  2. 샘플 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f inferencemodel.yaml
    

다음 예에서는 vllm-llama3-8b-instruct InferencePool에서 Standard 서비스 중요도로 food-review LoRA 모델을 구성하는 InferenceModel 객체를 만듭니다. InferenceModel 객체는 Critical 우선순위 수준으로 제공되도록 기본 모델을 구성합니다.

apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceModel
metadata:
  name: food-review
spec:
  modelName: food-review
  criticality: Standard
  poolRef:
    name: vllm-llama3-8b-instruct
  targetModels:
  - name: food-review
    weight: 100

---
apiVersion: inference.networking.x-k8s.io/v1alpha2
kind: InferenceModel
metadata:
  name: llama3-base-model
spec:
  modelName: meta-llama/Llama-3.1-8B-Instruct
  criticality: Critical
  poolRef:
    name: vllm-llama3-8b-instruct

게이트웨이 만들기

게이트웨이 리소스는 Kubernetes 클러스터로의 외부 트래픽 진입점 역할을 합니다. 수신 연결을 수락하는 리스너를 정의합니다.

GKE 추론 게이트웨이는 gke-l7-rilbgke-l7-regional-external-managed 게이트웨이 클래스를 지원합니다. 자세한 내용은 GKE 문서의 게이트웨이 클래스를 참고하세요.

게이트웨이를 만들려면 다음 단계를 따르세요.

  1. 다음 샘플 매니페스트를 gateway.yaml로 저장합니다.

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: GATEWAY_NAME
    spec:
      gatewayClassName: gke-l7-regional-external-managed
      listeners:
        - protocol: HTTP # Or HTTPS for production
          port: 80 # Or 443 for HTTPS
          name: http
    

    GATEWAY_NAME를 게이트웨이 리소스의 고유한 이름으로 바꿉니다. 예를 들면 inference-gateway입니다.

  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f gateway.yaml
    

HTTPRoute 리소스 만들기

이 섹션에서는 HTTPRoute 리소스를 만들어 게이트웨이가 수신 HTTP 요청을 InferencePool로 라우팅하는 방식을 정의합니다.

HTTPRoute 리소스는 GKE 게이트웨이가 수신 HTTP 요청을 백엔드 서비스(InferencePool)로 라우팅하는 방법을 정의합니다. 일치 규칙 (예: 헤더 또는 경로)과 트래픽을 전달해야 하는 백엔드를 지정합니다.

HTTPRoute를 만들려면 다음 단계를 따르세요.

  1. 다음 샘플 매니페스트를 httproute.yaml로 저장합니다.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: HTTPROUTE_NAME
    spec:
      parentRefs:
      - name: GATEWAY_NAME
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: PATH_PREFIX
        backendRefs:
        - name: INFERENCE_POOL_NAME
          group: inference.networking.x-k8s.io
          kind: InferencePool
    

    다음을 바꿉니다.

    • HTTPROUTE_NAME: HTTPRoute 리소스의 고유한 이름입니다. 예를 들면 my-route입니다.
    • GATEWAY_NAME: 만든 Gateway 리소스의 이름입니다. 예를 들면 inference-gateway입니다.
    • PATH_PREFIX: 수신 요청을 일치시키는 데 사용하는 경로 접두사입니다. 예를 들어 /는 모두 일치합니다.
    • INFERENCE_POOL_NAME: 트래픽을 라우트하려는 InferencePool 리소스의 이름입니다. 예를 들면 vllm-llama3-8b-instruct입니다.
  2. 매니페스트를 클러스터에 적용합니다.

    kubectl apply -f httproute.yaml
    

추론 요청 보내기

GKE 추론 게이트웨이를 구성한 후에는 배포된 모델에 추론 요청을 보낼 수 있습니다.

추론 요청을 보내려면 다음 단계를 따르세요.

  • 게이트웨이 엔드포인트를 검색합니다.
  • 올바른 형식의 JSON 요청을 구성합니다.
  • curl을 사용하여 /v1/completions 엔드포인트에 요청을 전송합니다.

이렇게 하면 입력 프롬프트와 지정된 매개변수를 기반으로 텍스트를 생성할 수 있습니다.

  1. 게이트웨이 엔드포인트를 가져오려면 다음 명령어를 실행합니다.

    IP=$(kubectl get gateway/GATEWAY_NAME -o jsonpath='{.status.addresses[0].address}')
    PORT=PORT_NUMBER # Use 443 for HTTPS, or 80 for HTTP
    

    다음을 바꿉니다.

    • GATEWAY_NAME: 게이트웨이 리소스의 이름입니다.
    • PORT_NUMBER: 게이트웨이에서 구성한 포트 번호입니다.
  2. curl를 사용하여 /v1/completions 엔드포인트에 요청을 전송하려면 다음 명령어를 실행합니다.

    curl -i -X POST https://${IP}:${PORT}/v1/completions \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer $(gcloud auth print-access-token)' \
    -d '{
        "model": "MODEL_NAME",
        "prompt": "PROMPT_TEXT",
        "max_tokens": MAX_TOKENS,
        "temperature": "TEMPERATURE"
    }'
    

    다음을 바꿉니다.

    • MODEL_NAME: 사용할 모델 또는 LoRA 어댑터의 이름입니다.
    • PROMPT_TEXT: 모델의 입력 프롬프트입니다.
    • MAX_TOKENS: 응답에서 생성할 최대 토큰 수입니다.
    • TEMPERATURE: 출력의 무작위성을 제어합니다. 확정적인 출력에는 0 값을 사용하고, 더 창의적인 출력에는 더 큰 숫자를 사용합니다.

다음 동작에 유의하세요.

  • 요청 본문: 요청 본문에는 stoptop_p와 같은 추가 매개변수가 포함될 수 있습니다. 전체 옵션 목록은 OpenAI API 사양을 참고하세요.
  • 오류 처리: 클라이언트 코드에 적절한 오류 처리를 구현하여 응답에서 발생할 수 있는 오류를 처리합니다. 예를 들어 curl 응답에서 HTTP 상태 코드를 확인합니다. 200이 아닌 상태 코드는 일반적으로 오류를 나타냅니다.
  • 인증 및 승인: 프로덕션 배포의 경우 인증 및 승인 메커니즘으로 API 엔드포인트를 보호합니다. 요청에 적절한 헤더 (예: Authorization)를 포함합니다.

추론 게이트웨이의 관측 가능성 구성

GKE 추론 게이트웨이는 추론 워크로드의 상태, 성능, 동작에 대한 관측 가능성을 제공합니다. 이를 통해 문제를 파악하고 해결하고, 리소스 활용을 최적화하고, 애플리케이션의 안정성을 보장할 수 있습니다. Cloud Monitoring의 측정항목 탐색기를 통해 이러한 관측 가능성 측정항목을 볼 수 있습니다.

GKE 추론 게이트웨이의 관측 가능성을 구성하려면 관측 가능성 구성을 참고하세요.

배포된 리소스 삭제

이 가이드에서 만든 리소스의 비용이 Google Cloud 계정에 청구되지 않도록 하려면 다음 명령어를 실행합니다.

gcloud container clusters delete CLUSTER_NAME \
    --region=REGION

다음 값을 바꿉니다.

  • REGION: 사용하려는 가속기 유형을 지원하는 리전(예: H100 GPU의 경우 us-central1)입니다.
  • CLUSTER_NAME: 클러스터 이름입니다.

다음 단계