Mengoptimalkan penggunaan resource GKE untuk workload inferensi dan pelatihan AI/ML campuran


Tutorial ini menunjukkan cara membagikan resource akselerator secara efisien antara workload penayangan inferensi dan pelatihan dalam satu cluster Google Kubernetes Engine (GKE). Dengan mendistribusikan beban kerja campuran di satu cluster, Anda dapat meningkatkan pemanfaatan resource, menyederhanakan pengelolaan cluster, mengurangi masalah akibat batasan jumlah akselerator, dan meningkatkan efektivitas biaya secara keseluruhan.

Dalam tutorial ini, Anda akan membuat Deployment inferensi prioritas tinggi menggunakan model bahasa besar (LLM) Gemma 2 untuk inferensi dan framework inferensi Hugging Face TGI (Text Generation Interface), beserta Tugas fine-tuning LLM prioritas rendah. Kedua workload berjalan di satu cluster yang menggunakan GPU NVIDIA L4. Anda menggunakan Kueue, sistem antrean pekerjaan berbasis Kubernetes open source, untuk mengelola dan menjadwalkan beban kerja. Kueue memungkinkan Anda memprioritaskan tugas penayangan dan menghentikan sementara Tugas pelatihan dengan prioritas lebih rendah untuk mengoptimalkan pemanfaatan resource. Saat permintaan penayangan menurun, Anda mengalokasikan ulang akselerator yang dibebaskan untuk melanjutkan tugas pelatihan. Anda menggunakan Kueue dan class prioritas untuk mengelola kuota resource selama proses.

Tutorial ini ditujukan untuk Engineer machine learning (ML), Admin dan operator platform, serta Spesialis Data dan AI yang ingin melatih dan menghosting model machine learning (ML) di cluster GKE, dan yang juga ingin mengurangi biaya dan overhead pengelolaan, terutama saat berurusan dengan sejumlah kecil akselerator. Untuk mempelajari lebih lanjut peran umum dan contoh tugas yang kami referensikan dalam konten, lihat Peran dan tugas pengguna GKE Enterprise umum. Google Cloud

Sebelum membaca halaman ini, pastikan Anda memahami hal-hal berikut:

Tujuan

Pada akhir panduan ini, Anda akan dapat melakukan langkah-langkah berikut:

  • Konfigurasi Deployment penayangan prioritas tinggi.
  • Siapkan Tugas pelatihan berprioritas lebih rendah.
  • Terapkan strategi pendahuluan untuk mengatasi berbagai permintaan.
  • Mengelola alokasi resource antara tugas pelatihan dan penyaluran menggunakan Kueue.

Sebelum memulai

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

    Enable the APIs

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

    Enable the APIs

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

      Buka IAM
    2. Pilih project.
    3. Klik Berikan akses.
    4. Di kolom Akun utama baru, masukkan ID pengguna Anda. Biasanya berupa alamat email untuk Akun Google.

    5. Di daftar Pilih peran, pilih peran.
    6. Untuk memberikan peran tambahan, klik Tambahkan peran lain, lalu tambahkan setiap peran tambahan.
    7. Klik Simpan.
  • Buat akun Hugging Face, jika Anda belum memilikinya.
  • Pastikan project Anda memiliki kuota yang cukup untuk GPU L4. Untuk mempelajari lebih lanjut, lihat Tentang GPU dan Kuota alokasi.

Menyiapkan lingkungan

Di bagian ini, Anda akan menyediakan resource yang diperlukan untuk men-deploy TGI dan model untuk workload inferensi dan pelatihan.

Mendapatkan akses ke model

Untuk mendapatkan akses ke model Gemma untuk deployment ke GKE, Anda harus menandatangani perjanjian izin lisensi terlebih dahulu, lalu membuat token akses Hugging Face.

  1. Tandatangani perjanjian izin lisensi. Akses halaman izin model, verifikasi izin menggunakan akun Hugging Face Anda, dan setujui persyaratan model.
  2. Buat token akses. Untuk mengakses model melalui Hugging Face, Anda memerlukan token Hugging Face. Ikuti langkah-langkah berikut untuk membuat token baru jika Anda belum memilikinya:

    1. Klik Profil Anda > Setelan > Token Akses.
    2. Pilih New Token.
    3. Tentukan Nama pilihan Anda dan Peran minimal Read.
    4. Pilih Generate a token.
    5. Salin token yang dihasilkan ke papan klip Anda.

Meluncurkan Cloud Shell

Dalam tutorial ini, Anda akan menggunakan Cloud Shell untuk mengelola resource yang dihosting di Google Cloud. Cloud Shell telah diinstal dengan software yang Anda perlukan untuk tutorial ini, termasuk kubectl, gcloud CLI, dan Terraform.

Untuk menyiapkan lingkungan Anda dengan Cloud Shell, ikuti langkah-langkah berikut:

  1. Di konsol Google Cloud , luncurkan sesi Cloud Shell dengan mengklik Ikon aktivasi Cloud Shell Activate Cloud Shell di konsolGoogle Cloud . Tindakan ini akan meluncurkan sesi di panel bawah konsol Google Cloud .

  2. Tetapkan variabel lingkungan default:

    gcloud config set project PROJECT_ID
    export PROJECT_ID=$(gcloud config get project)
    

    Ganti PROJECT_ID dengan Google Cloud project ID Anda.

  3. Clone kode contoh dari GitHub. Di Cloud Shell jalankan perintah berikut:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/
    cd kubernetes-engine-samples/ai-ml/mix-train-and-inference
    export EXAMPLE_HOME=$(pwd)
    

Membuat cluster GKE

Anda dapat menggunakan cluster Autopilot atau Standard untuk workload campuran. Sebaiknya gunakan cluster Autopilot untuk mendapatkan pengalaman Kubernetes yang terkelola sepenuhnya. Untuk memilih mode operasi GKE yang paling sesuai untuk workload Anda, lihat Memilih mode operasi GKE.

Autopilot

  1. Tetapkan variabel lingkungan default di Cloud Shell:

    export HF_TOKEN=HF_TOKEN
    export REGION=REGION
    export CLUSTER_NAME="llm-cluster"
    export PROJECT_NUMBER=$(gcloud projects list \
        --filter="$(gcloud config get-value project)" \
        --format="value(PROJECT_NUMBER)")
    export MODEL_BUCKET="model-bucket-$PROJECT_ID"
    

    Ganti nilai berikut:

    • HF_TOKEN: token Hugging Face yang Anda buat sebelumnya.
    • REGION: region yang mendukung jenis akselerator yang ingin Anda gunakan, misalnya, us-central1 untuk GPU L4.

    Anda dapat menyesuaikan variabel MODEL_BUCKET—ini merepresentasikan bucket Cloud Storage tempat Anda menyimpan bobot model terlatih.

  2. Buat cluster Autopilot:

    gcloud container clusters create-auto ${CLUSTER_NAME} \
        --project=${PROJECT_ID} \
        --region=${REGION} \
        --release-channel=rapid
    
  3. Buat bucket Cloud Storage untuk tugas penyesuaian:

    gcloud storage buckets create gs://${MODEL_BUCKET} \
        --location ${REGION} \
        --uniform-bucket-level-access
    
  4. Untuk memberikan akses ke bucket Cloud Storage, jalankan perintah ini:

    gcloud storage buckets add-iam-policy-binding "gs://$MODEL_BUCKET" \
        --role=roles/storage.objectAdmin \
        --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/llm/sa/default \
        --condition=None
    
  5. Untuk mendapatkan kredensial autentikasi untuk cluster, jalankan perintah ini:

    gcloud container clusters get-credentials llm-cluster \
        --region=$REGION \
        --project=$PROJECT_ID
    
  6. Buat namespace untuk Deployment Anda. Di Cloud Shell, jalankan perintah berikut:

    kubectl create ns llm
    

Standar

  1. Tetapkan variabel lingkungan default di Cloud Shell:

    export HF_TOKEN=HF_TOKEN
    export REGION=REGION
    export CLUSTER_NAME="llm-cluster"
    export GPU_POOL_MACHINE_TYPE="g2-standard-24"
    export GPU_POOL_ACCELERATOR_TYPE="nvidia-l4"
    export PROJECT_NUMBER=$(gcloud projects list \
        --filter="$(gcloud config get-value project)" \
        --format="value(PROJECT_NUMBER)")
    export MODEL_BUCKET="model-bucket-$PROJECT_ID"
    

    Ganti nilai berikut:

    • HF_TOKEN: token Hugging Face yang Anda buat sebelumnya.
    • REGION: region yang mendukung jenis akselerator yang ingin Anda gunakan, misalnya, us-central1 untuk GPU L4.

    Anda dapat menyesuaikan variabel ini:

    • GPU_POOL_MACHINE_TYPE: seri mesin node pool yang ingin Anda gunakan di region yang dipilih. Nilai ini bergantung pada jenis akselerator yang Anda pilih. Untuk mempelajari lebih lanjut, lihat Batasan penggunaan GPU di GKE. Misalnya, tutorial ini menggunakan g2-standard-24 dengan dua GPU yang terpasang per node. Untuk mengetahui daftar GPU yang tersedia dan paling baru, lihat GPU untuk Beban Kerja Compute.
    • GPU_POOL_ACCELERATOR_TYPE: jenis akselerator yang didukung di region yang Anda pilih. Misalnya, tutorial ini menggunakan nvidia-l4. Untuk mengetahui daftar GPU yang tersedia terbaru, lihat GPU untuk Workload Compute.
    • MODEL_BUCKET: bucket Cloud Storage tempat Anda menyimpan bobot model terlatih.
  2. Buat cluster Standard:

    gcloud container clusters create ${CLUSTER_NAME} \
        --project=${PROJECT_ID} \
        --region=${REGION} \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --release-channel=rapid \
        --machine-type=e2-standard-4 \
        --addons GcsFuseCsiDriver \
        --num-nodes=1
    
  3. Buat node pool GPU untuk workload inferensi dan fine-tuning:

    gcloud container node-pools create gpupool \
        --accelerator type=${GPU_POOL_ACCELERATOR_TYPE},count=2,gpu-driver-version=latest \
        --project=${PROJECT_ID} \
        --location=${REGION} \
        --node-locations=${REGION}-a \
        --cluster=${CLUSTER_NAME} \
        --machine-type=${GPU_POOL_MACHINE_TYPE} \
        --num-nodes=3
    
  4. Buat bucket Cloud Storage untuk tugas penyesuaian:

    gcloud storage buckets create gs://${MODEL_BUCKET} \
        --location ${REGION} \
        --uniform-bucket-level-access
    
  5. Untuk memberikan akses ke bucket Cloud Storage, jalankan perintah ini:

    gcloud storage buckets add-iam-policy-binding "gs://$MODEL_BUCKET" \
        --role=roles/storage.objectAdmin \
        --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/$PROJECT_ID.svc.id.goog/subject/ns/llm/sa/default \
        --condition=None
    
  6. Untuk mendapatkan kredensial autentikasi untuk cluster, jalankan perintah ini:

    gcloud container clusters get-credentials llm-cluster \
        --region=$REGION \
        --project=$PROJECT_ID
    
  7. Buat namespace untuk Deployment Anda. Di Cloud Shell, jalankan perintah berikut:

    kubectl create ns llm
    

Buat Secret Kubernetes untuk kredensial Hugging Face

Untuk membuat Secret Kubernetes yang berisi token Hugging Face, jalankan perintah berikut:

kubectl create secret generic hf-secret \
    --from-literal=hf_api_token=$HF_TOKEN \
    --dry-run=client -o yaml | kubectl apply --namespace=llm --filename=-

Mengonfigurasi Kueue

Dalam tutorial ini, Kueue adalah pengelola resource pusat, yang memungkinkan pembagian GPU yang efisien antara workload pelatihan dan inferensi Anda. Kueue mencapai hal ini dengan menentukan persyaratan resource ("flavor"), memprioritaskan workload melalui antrean (dengan tugas penayangan yang diprioritaskan daripada pelatihan), dan mengalokasikan resource secara dinamis berdasarkan permintaan dan prioritas. Tutorial ini menggunakan jenis resource Workload untuk mengelompokkan workload inferensi dan penyesuaian, masing-masing.

Fitur preemptive Kueue memastikan bahwa workload penayangan berprioritas tinggi selalu memiliki resource yang diperlukan dengan menjeda atau mengeluarkan Tugas pelatihan berprioritas lebih rendah saat resource langka.

Untuk mengontrol Deployment server inferensi dengan Kueue, aktifkan integrasi pod dan konfigurasi managedJobsNamespaceSelector untuk mengecualikan namespace kube-system dan kueue-system.

  1. Di direktori /kueue, lihat kode di kustomization.yaml. Manifest ini menginstal pengelola resource Kueue dengan konfigurasi kustom.

    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    resources:
    - https://github.com/kubernetes-sigs/kueue/releases/download/v0.12.3/manifests.yaml
    patches:
    - path: patch.yaml
      target:
        version: v1
        kind: ConfigMap
        name: kueue-manager-config
    
  2. Di direktori /kueue, lihat kode di patch.yaml. ConfigMap ini menyesuaikan Kueue untuk mengecualikan pengelolaan Pod di namespace kube-system dan kueue-system.

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: kueue-manager-config
    data:
      controller_manager_config.yaml: |
        apiVersion: config.kueue.x-k8s.io/v1beta1
        kind: Configuration
        health:
          healthProbeBindAddress: :8081
        metrics:
          bindAddress: :8080
        # enableClusterQueueResources: true
        webhook:
          port: 9443
        leaderElection:
          leaderElect: true
          resourceName: c1f6bfd2.kueue.x-k8s.io
        controller:
          groupKindConcurrency:
            Job.batch: 5
            Pod: 5
            Workload.kueue.x-k8s.io: 5
            LocalQueue.kueue.x-k8s.io: 1
            ClusterQueue.kueue.x-k8s.io: 1
            ResourceFlavor.kueue.x-k8s.io: 1
        clientConnection:
          qps: 50
          burst: 100
        #pprofBindAddress: :8083
        #waitForPodsReady:
        #  enable: false
        #  timeout: 5m
        #  blockAdmission: false
        #  requeuingStrategy:
        #    timestamp: Eviction
        #    backoffLimitCount: null # null indicates infinite requeuing
        #    backoffBaseSeconds: 60
        #    backoffMaxSeconds: 3600
        #manageJobsWithoutQueueName: true
        managedJobsNamespaceSelector:
          matchExpressions:
            - key: kubernetes.io/metadata.name
              operator: NotIn
              values: [ kube-system, kueue-system ]
        #internalCertManagement:
        #  enable: false
        #  webhookServiceName: ""
        #  webhookSecretName: ""
        integrations:
          frameworks:
          - "batch/job"
          - "kubeflow.org/mpijob"
          - "ray.io/rayjob"
          - "ray.io/raycluster"
          - "jobset.x-k8s.io/jobset"
          - "kubeflow.org/paddlejob"
          - "kubeflow.org/pytorchjob"
          - "kubeflow.org/tfjob"
          - "kubeflow.org/xgboostjob"
          - "kubeflow.org/jaxjob"
          - "workload.codeflare.dev/appwrapper"
          - "pod"
        #  - "deployment" # requires enabling pod integration
        #  - "statefulset" # requires enabling pod integration
        #  - "leaderworkerset.x-k8s.io/leaderworkerset" # requires enabling pod integration
        #  externalFrameworks:
        #  - "Foo.v1.example.com"
        #fairSharing:
        #  enable: true
        #  preemptionStrategies: [LessThanOrEqualToFinalShare, LessThanInitialShare]
        #admissionFairSharing:
        #  usageHalfLifeTime: "168h" # 7 days
        #  usageSamplingInterval: "5m"
        #  resourceWeights: # optional, defaults to 1 for all resources if not specified
        #    cpu: 0    # if you want to completely ignore cpu usage
        #    memory: 0 # ignore completely memory usage
        #    example.com/gpu: 100 # and you care only about GPUs usage
        #resources:
        #  excludeResourcePrefixes: []
        #  transformations:
        #  - input: nvidia.com/mig-4g.5gb
        #    strategy: Replace | Retain
        #    outputs:
        #      example.com/accelerator-memory: 5Gi
        #      example.com/accelerator-gpc: 4
        #objectRetentionPolicies:
        #  workloads:
        #    afterFinished: null # null indicates infinite retention, 0s means no retention at all
        #    afterDeactivatedByKueue: null # null indicates infinite retention, 0s means no retention at all
    
  3. Di Cloud Shell, jalankan perintah berikut untuk menginstal Kueue:

    cd ${EXAMPLE_HOME}
    kubectl kustomize kueue |kubectl apply --server-side --filename=-
    

    Tunggu hingga Pod Kueue siap:

    watch kubectl --namespace=kueue-system get pods
    

    Output-nya akan terlihat seperti berikut:

    NAME                                        READY   STATUS    RESTARTS   AGE
    kueue-controller-manager-bdc956fc4-vhcmx    1/1     Running   0          3m15s
    
  4. Di direktori /workloads, lihat file flavors.yaml, cluster-queue.yaml, dan local-queue.yaml. Manifes ini menentukan cara Kueue mengelola kuota resource:

    ResourceFlavor

    Manifes ini menentukan ResourceFlavor default di Kueue untuk pengelolaan resource.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ResourceFlavor
    metadata:
      name: default-flavor
    

    ClusterQueue

    Manifes ini menyiapkan ClusterQueue Kueue dengan batas resource untuk CPU, memori, dan GPU.

    Tutorial ini menggunakan node dengan dua GPU Nvidia L4 yang terpasang, dengan jenis node yang sesuai, yaitu g2-standard-24, yang menawarkan 24 vCPU dan RAM 96 GB. Contoh kode menunjukkan cara membatasi penggunaan resource workload Anda hingga maksimum enam GPU.

    Kolom preemption dalam konfigurasi ClusterQueue mereferensikan PriorityClass untuk menentukan Pod mana yang dapat didahului saat resource langka.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: ClusterQueue
    metadata:
      name: "cluster-queue"
    spec:
      namespaceSelector: {} # match all.
      preemption:
        reclaimWithinCohort: LowerPriority
        withinClusterQueue: LowerPriority
      resourceGroups:
      - coveredResources: [ "cpu", "memory", "nvidia.com/gpu", "ephemeral-storage" ]
        flavors:
        - name: default-flavor
          resources:
          - name: "cpu"
            nominalQuota: 72
          - name: "memory"
            nominalQuota: 288Gi
          - name: "nvidia.com/gpu"
            nominalQuota: 6
          - name: "ephemeral-storage"
            nominalQuota: 200Gi
    

    LocalQueue

    Manifes ini membuat LocalQueue Kueue bernama lq di namespace llm.

    apiVersion: kueue.x-k8s.io/v1beta1
    kind: LocalQueue
    metadata:
      namespace: llm # LocalQueue under llm namespace 
      name: lq
    spec:
      clusterQueue: cluster-queue # Point to the ClusterQueue
    
  5. Lihat file default-priorityclass.yaml, low-priorityclass.yaml, dan high-priorityclass.yaml. Manifes ini menentukan objek PriorityClass untuk penjadwalan Kubernetes.

    Prioritas default

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: default-priority-nonpreempting
    value: 10
    preemptionPolicy: Never
    globalDefault: true
    description: "This priority class will not cause other pods to be preempted."
    

    Prioritas rendah

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: low-priority-preempting
    value: 20
    preemptionPolicy: PreemptLowerPriority
    globalDefault: false
    description: "This priority class will cause pods with lower priority to be preempted."
    

    Prioritas tinggi

    apiVersion: scheduling.k8s.io/v1
    kind: PriorityClass
    metadata:
      name: high-priority-preempting
    value: 30
    preemptionPolicy: PreemptLowerPriority
    globalDefault: false
    description: "This high priority class will cause other pods to be preempted."
    
  6. Buat objek Kueue dan Kubernetes dengan menjalankan perintah ini untuk menerapkan manifes yang sesuai.

    cd ${EXAMPLE_HOME}/workloads
    kubectl apply --filename=flavors.yaml
    kubectl apply --filename=default-priorityclass.yaml
    kubectl apply --filename=high-priorityclass.yaml
    kubectl apply --filename=low-priorityclass.yaml
    kubectl apply --filename=cluster-queue.yaml
    kubectl apply --filename=local-queue.yaml --namespace=llm
    

Men-deploy server inferensi TGI

Di bagian ini, Anda akan men-deploy container TGI untuk menyajikan model Gemma 2.

  1. Di direktori /workloads, lihat file tgi-gemma-2-9b-it-hp.yaml. Manifes ini menentukan Deployment Kubernetes untuk men-deploy runtime penyajian TGI dan model gemma-2-9B-it. Deployment adalah objek Kubernetes API yang memungkinkan Anda menjalankan beberapa replika Pod yang didistribusikan di antara node dalam cluster.

    Deployment memprioritaskan tugas inferensi dan menggunakan dua GPU untuk model. Model ini menggunakan paralelisme tensor, dengan menetapkan variabel lingkungan NUM_SHARD, untuk menyesuaikan model ke dalam memori GPU.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: tgi-gemma-deployment
      labels:
        app: gemma-server
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: gemma-server
      template:
        metadata:
          labels:
            app: gemma-server
            ai.gke.io/model: gemma-2-9b-it
            ai.gke.io/inference-server: text-generation-inference
            examples.ai.gke.io/source: user-guide
            kueue.x-k8s.io/queue-name: lq
        spec:
          priorityClassName: high-priority-preempting
          containers:
          - name: inference-server
            image: us-docker.pkg.dev/deeplearning-platform-release/gcr.io/huggingface-text-generation-inference-cu121.2-1.ubuntu2204.py310
            resources:
              requests:
                cpu: "4"
                memory: "30Gi"
                ephemeral-storage: "30Gi"
                nvidia.com/gpu: "2"
              limits:
                cpu: "4"
                memory: "30Gi"
                ephemeral-storage: "30Gi"
                nvidia.com/gpu: "2"
            env:
            - name: AIP_HTTP_PORT
              value: '8000'
            - name: NUM_SHARD
              value: '2'
            - name: MODEL_ID
              value: google/gemma-2-9b-it
            - name: HUGGING_FACE_HUB_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          nodeSelector:
            cloud.google.com/gke-accelerator: "nvidia-l4"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: llm-service
    spec:
      selector:
        app: gemma-server
      type: ClusterIP
      ports:
      - protocol: TCP
        port: 8000
        targetPort: 8000
    
  2. Terapkan manifes dengan menjalankan perintah berikut:

    kubectl apply --filename=tgi-gemma-2-9b-it-hp.yaml --namespace=llm
    

    Operasi deployment akan memerlukan waktu beberapa menit hingga selesai.

  3. Untuk memeriksa apakah GKE berhasil membuat Deployment, jalankan perintah berikut:

    kubectl --namespace=llm get deployment
    

    Output-nya akan terlihat seperti berikut:

    NAME                   READY   UP-TO-DATE   AVAILABLE   AGE
    tgi-gemma-deployment   1/1     1            1           5m13s
    

Memverifikasi pengelolaan kuota Kueue

Di bagian ini, Anda akan mengonfirmasi bahwa Kueue menerapkan kuota GPU dengan benar untuk Deployment Anda.

  1. Untuk memeriksa apakah Kueue mengetahui Deployment Anda, jalankan perintah ini untuk mengambil status objek Workload:

    kubectl --namespace=llm get workloads
    

    Output-nya akan terlihat seperti berikut:

    NAME                                              QUEUE   RESERVED IN     ADMITTED   FINISHED   AGE
    pod-tgi-gemma-deployment-6bf9ffdc9b-zcfrh-84f19   lq      cluster-queue   True                  8m23s
    
  2. Untuk menguji penggantian batas kuota, skalakan Deployment ke empat replika:

    kubectl scale --replicas=4 deployment/tgi-gemma-deployment --namespace=llm
    
  3. Jalankan perintah berikut untuk melihat jumlah replika yang di-deploy GKE:

    kubectl get workloads --namespace=llm
    

    Output-nya akan terlihat seperti berikut:

    NAME                                              QUEUE   RESERVED IN     ADMITTED   FINISHED   AGE
    pod-tgi-gemma-deployment-6cb95cc7f5-5thgr-3f7d4   lq      cluster-queue   True                  14s
    pod-tgi-gemma-deployment-6cb95cc7f5-cbxg2-d9fe7   lq      cluster-queue   True                  5m41s
    pod-tgi-gemma-deployment-6cb95cc7f5-tznkl-80f6b   lq                                            13s
    pod-tgi-gemma-deployment-6cb95cc7f5-wd4q9-e4302   lq      cluster-queue   True                  13s
    

    Output menunjukkan bahwa hanya tiga Pod yang diizinkan karena kuota resource yang diterapkan Kueue.

  4. Jalankan perintah berikut untuk menampilkan Pod di namespace llm:

    kubectl get pod --namespace=llm
    

    Output-nya akan terlihat seperti berikut:

    NAME                                    READY   STATUS            RESTARTS   AGE
    tgi-gemma-deployment-7649884d64-6j256   1/1     Running           0          4m45s
    tgi-gemma-deployment-7649884d64-drpvc   0/1     SchedulingGated   0          7s
    tgi-gemma-deployment-7649884d64-thdkq   0/1     Pending           0          7s
    tgi-gemma-deployment-7649884d64-znvpb   0/1     Pending           0          7s
    
  5. Sekarang, turunkan skala Deployment kembali ke 1. Langkah ini diperlukan sebelum men-deploy tugas penyesuaian, jika tidak, tugas tersebut tidak akan diterima karena tugas inferensi memiliki prioritas.

    kubectl scale --replicas=1 deployment/tgi-gemma-deployment --namespace=llm
    

Penjelasan perilaku

Contoh penskalaan hanya menghasilkan tiga replika (meskipun penskalaan ke empat) karena batas kuota GPU yang Anda tetapkan dalam konfigurasi ClusterQueue. Bagian spec.resourceGroups ClusterQueue menentukan nominalQuota "6" untuk nvidia.com/gpu. Deployment menentukan bahwa setiap Pod memerlukan "2" GPU. Oleh karena itu, ClusterQueue hanya dapat menampung maksimum tiga replika Deployment dalam satu waktu (karena 3 replika * 2 GPU per replika = 6 GPU, yang merupakan total kuota).

Saat Anda mencoba menskalakan ke empat replika, Kueue akan mengenali bahwa tindakan ini akan melebihi kuota GPU dan mencegah replika keempat dijadwalkan. Hal ini ditunjukkan oleh status SchedulingGated Pod keempat. Perilaku ini menunjukkan penerapan kuota resource Kueue.

Deploy Tugas pelatihan

Di bagian ini, Anda akan men-deploy Tugas penyesuaian prioritas rendah untuk model Gemma 2 yang memerlukan empat GPU di dua Pod. Pengontrol Job di Kubernetes membuat satu atau beberapa Pod dan memastikan bahwa Pod tersebut berhasil menjalankan tugas tertentu.

Tugas ini akan menggunakan kuota GPU yang tersisa di ClusterQueue. Job menggunakan image bawaan dan menyimpan titik pemeriksaan untuk memungkinkan memulai ulang dari hasil sementara.

Tugas fine-tuning menggunakan set data b-mc2/sql-create-context. Sumber untuk tugas penyesuaian dapat ditemukan di repositori.

  1. Lihat file fine-tune-l4.yaml. Manifes ini menentukan Tugas penyesuaian.

    apiVersion: v1
    kind: Service
    metadata:
      name: headless-svc-l4
    spec:
      clusterIP: None # clusterIP must be None to create a headless service
      selector:
        job-name: finetune-gemma-l4 # must match Job name
    ---
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: finetune-gemma-l4
      labels:
        kueue.x-k8s.io/queue-name: lq
    spec:
      backoffLimit: 4
      completions: 2
      parallelism: 2
      completionMode: Indexed
      suspend: true # Set to true to allow Kueue to control the Job when it starts
      template:
        metadata:
          labels:
            app: finetune-job
          annotations:
            gke-gcsfuse/volumes: "true"
            gke-gcsfuse/memory-limit: "35Gi"
        spec:
          priorityClassName: low-priority-preempting
          containers:
          - name: gpu-job
            imagePullPolicy: Always
            image: us-docker.pkg.dev/google-samples/containers/gke/gemma-fine-tuning:v1.0.0
            ports:
            - containerPort: 29500
            resources:
              requests:
                nvidia.com/gpu: "2"
              limits:
                nvidia.com/gpu: "2"
            command:
            - bash
            - -c
            - |
              accelerate launch \
              --config_file fsdp_config.yaml \
              --debug \
              --main_process_ip finetune-gemma-l4-0.headless-svc-l4 \
              --main_process_port 29500 \
              --machine_rank ${JOB_COMPLETION_INDEX} \
              --num_processes 4 \
              --num_machines 2 \
              fine_tune.py
            env:
            - name: "EXPERIMENT"
              value: "finetune-experiment"
            - name: MODEL_NAME
              value: "google/gemma-2-2b"
            - name: NEW_MODEL
              value: "gemma-ft"
            - name: MODEL_PATH
              value: "/model-data/model-gemma2/experiment"
            - name: DATASET_NAME
              value: "b-mc2/sql-create-context"
            - name: DATASET_LIMIT
              value: "5000"
            - name: EPOCHS
              value: "1"
            - name: GRADIENT_ACCUMULATION_STEPS
              value: "2"
            - name: CHECKPOINT_SAVE_STEPS
              value: "10"
            - name: HF_TOKEN
              valueFrom:
                secretKeyRef:
                  name: hf-secret
                  key: hf_api_token
            volumeMounts:
            - mountPath: /dev/shm
              name: dshm
            - name: gcs-fuse-csi-ephemeral
              mountPath: /model-data
              readOnly: false
          nodeSelector:
            cloud.google.com/gke-accelerator: nvidia-l4
          restartPolicy: OnFailure
          serviceAccountName: default
          subdomain: headless-svc-l4
          terminationGracePeriodSeconds: 60
          volumes:
          - name: dshm
            emptyDir:
              medium: Memory
          - name: gcs-fuse-csi-ephemeral
            csi:
              driver: gcsfuse.csi.storage.gke.io
              volumeAttributes:
                bucketName: <MODEL_BUCKET>
                mountOptions: "implicit-dirs"
                gcsfuseLoggingSeverity: warning
    
  2. Terapkan manifes untuk membuat Tugas penyesuaian:

    cd ${EXAMPLE_HOME}/workloads
    
    sed -e "s/<MODEL_BUCKET>/$MODEL_BUCKET/g" \
        -e "s/<PROJECT_ID>/$PROJECT_ID/g" \
        -e "s/<REGION>/$REGION/g" \
        fine-tune-l4.yaml |kubectl apply --filename=- --namespace=llm
    
  3. Pastikan Deployment Anda berjalan. Untuk memeriksa status objek Workload, jalankan perintah berikut:

    kubectl get workloads --namespace=llm
    

    Output-nya akan terlihat seperti berikut:

    NAME                                              QUEUE   RESERVED IN     ADMITTED   FINISHED   AGE
    job-finetune-gemma-l4-3316f                       lq      cluster-queue   True                  29m
    pod-tgi-gemma-deployment-6cb95cc7f5-cbxg2-d9fe7   lq      cluster-queue   True                  68m
    

    Selanjutnya, lihat Pod di namespace llm dengan menjalankan perintah ini:

    kubectl get pod --namespace=llm
    

    Output-nya akan terlihat seperti berikut:

    NAME                                    READY   STATUS    RESTARTS   AGE
    finetune-gemma-l4-0-vcxpz               2/2     Running   0          31m
    finetune-gemma-l4-1-9ppt9               2/2     Running   0          31m
    tgi-gemma-deployment-6cb95cc7f5-cbxg2   1/1     Running   0          70m
    

    Output menunjukkan bahwa Kueue mengizinkan Job fine-tune dan Pod server inferensi Anda untuk berjalan, dengan mencadangkan resource yang tepat berdasarkan batas kuota yang Anda tentukan.

  4. Lihat log output untuk memverifikasi bahwa Tugas penyesuaian Anda menyimpan titik pemeriksaan ke bucket Cloud Storage. Tugas penyesuaian memerlukan waktu sekitar 10 menit sebelum mulai menyimpan checkpoint pertama.

    kubectl logs --namespace=llm --follow --selector=app=finetune-job
    

    Output untuk titik pemeriksaan tersimpan pertama akan terlihat mirip dengan berikut ini:

    {"name": "finetune", "thread": 133763559483200, "threadName": "MainThread", "processName": "MainProcess", "process": 33, "message": "Fine tuning started", "timestamp": 1731002351.0016131, "level": "INFO", "runtime": 451579.89835739136}
    …
    {"name": "accelerate.utils.fsdp_utils", "thread": 136658669348672, "threadName": "MainThread", "processName": "MainProcess", "process": 32, "message": "Saving model to /model-data/model-gemma2/experiment/checkpoint-10/pytorch_model_fsdp_0", "timestamp": 1731002386.1763802, "level": "INFO", "runtime": 486753.8924217224}
    

Menguji preempti Kueue dan alokasi dinamis pada workload campuran Anda

Di bagian ini, Anda akan menyimulasikan skenario saat beban server inferensi meningkat, sehingga server tersebut perlu di-scale up. Skenario ini menunjukkan cara Kueue memprioritaskan server inferensi prioritas tinggi dengan menangguhkan dan mendahului Tugas penyesuaian prioritas rendah saat resource terbatas.

  1. Jalankan perintah berikut untuk menskalakan replika server inferensi menjadi dua:

    kubectl scale --replicas=2 deployment/tgi-gemma-deployment --namespace=llm
    
  2. Periksa status objek Workload:

    kubectl get workloads --namespace=llm
    

    Outputnya terlihat mirip dengan yang berikut ini:

    NAME                                              QUEUE   RESERVED IN     ADMITTED   FINISHED   AGE
    job-finetune-gemma-l4-3316f                       lq                      False                 32m
    pod-tgi-gemma-deployment-6cb95cc7f5-cbxg2-d9fe7   lq      cluster-queue   True                  70m
    pod-tgi-gemma-deployment-6cb95cc7f5-p49sh-167de   lq      cluster-queue   True                  14s
    

    Output menunjukkan bahwa Tugas penyesuaian tidak lagi diizinkan karena replika server inferensi yang ditingkatkan menggunakan kuota GPU yang tersedia.

  3. Periksa status Tugas penyesuaian:

    kubectl get job --namespace=llm
    

    Outputnya akan terlihat mirip dengan berikut ini, yang menunjukkan bahwa status Job penyesuaian kini ditangguhkan:

    NAME                STATUS      COMPLETIONS   DURATION   AGE
    finetune-gemma-l4   Suspended   0/2                      33m
    
  4. Jalankan perintah berikut untuk memeriksa Pod Anda:

    kubectl get pod --namespace=llm
    

    Outputnya akan terlihat mirip dengan berikut ini, yang menunjukkan bahwa Kueue menghentikan Pod Tugas penyesuaian untuk mengosongkan resource bagi Deployment server inferensi dengan prioritas yang lebih tinggi.

    NAME                                    READY   STATUS              RESTARTS   AGE
    tgi-gemma-deployment-6cb95cc7f5-cbxg2   1/1     Running             0          72m
    tgi-gemma-deployment-6cb95cc7f5-p49sh   0/1     ContainerCreating   0          91s
    
  5. Selanjutnya, uji skenario saat beban server inferensi berkurang dan Pod-nya diturunkan skalanya. Jalankan perintah berikut:

    kubectl scale --replicas=1 deployment/tgi-gemma-deployment --namespace=llm
    

    Jalankan perintah berikut untuk menampilkan objek Workload:

    kubectl get workloads --namespace=llm
    

    Outputnya akan terlihat mirip dengan berikut ini, yang menunjukkan bahwa salah satu Deployment server inferensi dihentikan, dan Tugas penyesuaian diizinkan kembali.

    NAME                                              QUEUE   RESERVED IN     ADMITTED   FINISHED   AGE
    job-finetune-gemma-l4-3316f                       lq      cluster-queue   True                  37m
    pod-tgi-gemma-deployment-6cb95cc7f5-cbxg2-d9fe7   lq      cluster-queue   True                  75m
    
  6. Jalankan perintah ini untuk menampilkan Job:

    kubectl get job --namespace=llm
    

    Outputnya akan terlihat mirip dengan berikut ini, yang menunjukkan bahwa tugas penyesuaian sedang berjalan lagi, melanjutkan dari checkpoint terbaru yang tersedia.

    NAME                STATUS    COMPLETIONS   DURATION   AGE
    finetune-gemma-l4   Running   0/2           2m11s      38m
    

Pembersihan

Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

Menghapus resource yang di-deploy

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang Anda buat dalam panduan ini, jalankan perintah berikut:

gcloud storage rm --recursive gs://${MODEL_BUCKET}
gcloud container clusters delete ${CLUSTER_NAME} --location ${REGION}

Langkah berikutnya