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


Tutorial ini menunjukkan cara berbagi resource akselerator secara efisien antara workload pelatihan dan inferensi dalam satu cluster Google Kubernetes Engine (GKE). Dengan mendistribusikan beban kerja campuran di satu cluster, Anda akan meningkatkan penggunaan resource, menyederhanakan pengelolaan cluster, mengurangi masalah dari batasan jumlah akselerator, dan meningkatkan efisiensi biaya secara keseluruhan.

Dalam tutorial ini, Anda akan membuat Deployment penayangan dengan prioritas tinggi menggunakan model bahasa besar (LLM) Gemma 2 untuk inferensi dan framework penayangan Hugging Face TGI (Text Generation Interface), bersama dengan Tugas penyesuaian LLM prioritas rendah. Kedua workload tersebut berjalan di satu cluster yang menggunakan GPU NVIDIA L4. Anda menggunakan Kueue, sistem antrean Tugas native Kubernetes open source, untuk mengelola dan menjadwalkan beban kerja. Kueue memungkinkan Anda memprioritaskan tugas penayangan dan menggantikan Tugas pelatihan prioritas rendah untuk mengoptimalkan penggunaan 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 menangani akselerator dalam jumlah terbatas. Untuk mempelajari lebih lanjut peran umum dan contoh tugas yang kami referensikan dalam konten Google Cloud , lihat Peran dan tugas pengguna GKE Enterprise umum.

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

Tujuan

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

  • Konfigurasikan Deployment penayangan prioritas tinggi.
  • Menyiapkan Tugas pelatihan dengan prioritas lebih rendah.
  • Terapkan strategi preemptif untuk mengatasi berbagai permintaan.
  • Mengelola alokasi resource antara tugas pelatihan dan penayangan 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 New principals, masukkan ID pengguna Anda. Ini biasanya adalah 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 memadai 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 di-deploy ke GKE, Anda harus menandatangani perjanjian izin lisensi terlebih dahulu, lalu membuat token akses Hugging Face.

  1. Tanda tangani 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 Buat 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 diGoogle 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 Aktifkan Cloud Shell di konsol Google 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 pengalaman Kubernetes yang dikelola 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—variabel ini mewakili 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 berikut:

    • 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 terbaru GPU yang tersedia, 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 terbaru GPU yang tersedia, lihat GPU untuk Workload Komputasi.
    • MODEL_BUCKET: bucket Cloud Storage tempat Anda menyimpan bobot model terlatih.
  2. Membuat 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 inferensi dan workload penyesuaian:

    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
    

Membuat 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 secara efisien antara workload pelatihan dan penayangan Anda. Kueue mencapai hal ini dengan menentukan persyaratan resource ("ragam"), memprioritaskan beban kerja melalui antrean (dengan tugas penayangan diprioritaskan daripada pelatihan), dan mengalokasikan resource secara dinamis berdasarkan permintaan dan prioritas. Tutorial ini menggunakan jenis resource Workload untuk mengelompokkan beban kerja inferensi dan penyesuaian.

Fitur preemptif Kueue memastikan bahwa beban kerja 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, Anda mengaktifkan integrasi v1/pod dengan menerapkan konfigurasi kustom menggunakan Kustomize, untuk memastikan Pod server diberi label dengan "kueue-job: true".

  1. Di direktori /kueue, lihat kode di kustomization.yaml. Manifes 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.10.0/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 mengelola Pod dengan label "kueue-job: true".

    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
        #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/mxjob"
          - "kubeflow.org/paddlejob"
          - "kubeflow.org/pytorchjob"
          - "kubeflow.org/tfjob"
          - "kubeflow.org/xgboostjob"
          - "pod"
        #  externalFrameworks:
        #  - "Foo.v1.example.com"
          podOptions:
            # You can change namespaceSelector to define in which 
            # namespaces kueue will manage the pods.
            namespaceSelector:
              matchExpressions:
              - key: kubernetes.io/metadata.name
                operator: NotIn
                values: [ kube-system, kueue-system ]
            # Kueue uses podSelector to manage pods with particular 
            # labels. The default podSelector will match all the pods. 
            podSelector:
              matchExpressions:
              - key: kueue-job
                operator: In
                values: [ "true", "True", "yes" ]
    
  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    2/2     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. Kode contoh 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 Kueue LocalQueue 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 penampung TGI untuk menayangkan 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 dan model gemma-2-9B-it penayangan TGI. 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
            kueue-job: "true"
        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 diskalakan menjadi 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 mengakomodasi maksimal 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.

Men-deploy Tugas pelatihan

Di bagian ini, Anda akan men-deploy Tugas penyesuaian prioritas lebih rendah untuk model Gemma 2 yang memerlukan empat GPU di dua Pod. Pengontrol Tugas 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. Tugas menggunakan image bawaan dan menyimpan titik pemeriksaan untuk memungkinkan mulai ulang dari hasil perantara.

Tugas penyesuaian 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 Pod server inferensi dan Tugas penyesuaian Anda untuk berjalan, dengan mencadangkan resource yang benar 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 titik pemeriksaan pertama.

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

    Output untuk checkpoint pertama yang disimpan 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 preemption Kueue dan alokasi dinamis pada workload campuran Anda

Di bagian ini, Anda akan menyimulasikan skenario saat beban server inferensi meningkat, sehingga mengharuskannya untuk diskalakan. Skenario ini menunjukkan cara Kueue memprioritaskan server inferensi prioritas tinggi dengan menangguhkan dan menggantikan Tugas penyesuaian prioritas yang lebih rendah saat resource dibatasi.

  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 meningkat menggunakan kuota GPU yang tersedia.

  3. Periksa status Tugas penyesuaian:

    kubectl get job --namespace=llm
    

    Output-nya terlihat mirip dengan berikut ini, yang menunjukkan bahwa status Tugas 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 terlihat mirip dengan berikut ini, yang menunjukkan bahwa Kueue menghentikan Pod Tugas penyesuaian untuk mengosongkan resource untuk Deployment server inferensi 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 diskalakan ke bawah. 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 terlihat mirip dengan berikut ini, yang menunjukkan bahwa salah satu Deployment server inferensi dihentikan, dan Tugas penyesuaian diterima 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 Tugas:

    kubectl get job --namespace=llm
    

    Outputnya terlihat mirip dengan berikut ini, yang menunjukkan bahwa Tugas penyesuaian sedang berjalan lagi, melanjutkan dari titik pemeriksaan 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 dibuat dalam panduan ini, jalankan perintah berikut:

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

Langkah berikutnya