Cara menghosting LLM di sidecar untuk fungsi Cloud Run

Cara menghosting LLM di sidecar untuk fungsi Cloud Run

Tentang codelab ini

subjectTerakhir diperbarui Mar 27, 2025
account_circleDitulis oleh Googler

1. Pengantar

Ringkasan

Dalam codelab ini, Anda akan mempelajari cara menghosting model gemma3:4b di sidecar untuk fungsi Cloud Run. Saat diupload ke bucket Cloud Storage, file akan memicu fungsi Cloud Run. Fungsi ini akan mengirim konten file ke Gemma 3 di sidecar untuk ringkasan.

Yang akan Anda pelajari

  • Cara melakukan inferensi menggunakan fungsi Cloud Run dan LLM yang dihosting di sidecar menggunakan GPU
  • Cara menggunakan konfigurasi traffic keluar VPC Langsung untuk GPU Cloud Run agar upload dan penayangan model lebih cepat
  • Cara menggunakan genkit untuk berinteraksi dengan model ollama yang dihosting

2. Sebelum memulai

Untuk menggunakan fitur GPU, Anda harus meminta penambahan kuota untuk wilayah yang didukung. Kuota yang diperlukan adalah nvidia_l4_gpu_allocation_no_zonal_redundancy, yang berada di Cloud Run Admin API. Berikut link langsung untuk meminta kuota.

3. Penyiapan dan Persyaratan

Tetapkan variabel lingkungan yang akan digunakan di seluruh codelab ini.

PROJECT_ID=<YOUR_PROJECT_ID>
REGION
=<YOUR_REGION>

AR_REPO
=codelab-crf-sidecar-gpu
FUNCTION_NAME
=crf-sidecar-gpu
BUCKET_GEMMA_NAME
=$PROJECT_ID-codelab-crf-sidecar-gpu-gemma3
BUCKET_DOCS_NAME
=$PROJECT_ID-codelab-crf-sidecar-gpu-docs
SERVICE_ACCOUNT
="crf-sidecar-gpu"
SERVICE_ACCOUNT_ADDRESS
=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
IMAGE_SIDECAR
=$REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3

Buat akun layanan dengan menjalankan perintah ini:

gcloud iam service-accounts create $SERVICE_ACCOUNT \
 
--display-name="SA for codelab crf sidecar with gpu"

Kita akan menggunakan akun layanan yang sama yang digunakan sebagai identitas fungsi Cloud Run sebagai akun layanan untuk pemicu eventarc guna memanggil fungsi Cloud Run. Anda dapat membuat SA yang berbeda untuk Eventarc jika mau.

gcloud projects add-iam-policy-binding $PROJECT_ID \
   
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
   
--role=roles/run.invoker

Berikan juga akses akun layanan untuk menerima peristiwa Eventarc.

gcloud projects add-iam-policy-binding $PROJECT_ID \
   
--member="serviceAccount:$SERVICE_ACCOUNT_ADDRESS" \
   
--role="roles/eventarc.eventReceiver"

Buat bucket yang akan menghosting model yang telah disesuaikan. Codelab ini menggunakan bucket regional. Anda juga dapat menggunakan bucket multi-regional.

gsutil mb -l $REGION gs://$BUCKET_GEMMA_NAME

Kemudian, berikan akses ke bucket kepada SA.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

Sekarang, buat bucket regional yang akan menyimpan dokumen yang ingin Anda ringkas. Anda juga dapat menggunakan bucket multi-regional, asalkan Anda memperbarui pemicu Eventarc sebagaimana mestinya (ditampilkan di akhir codelab ini).

gsutil mb -l $REGION gs://$BUCKET_DOCS_NAME

Kemudian, beri SA akses ke bucket Gemma 3.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_GEMMA_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

dan bucket Dokumen.

gcloud storage buckets add-iam-policy-binding gs://$BUCKET_DOCS_NAME \
--member=serviceAccount:$SERVICE_ACCOUNT_ADDRESS \
--role=roles/storage.objectAdmin

Membuat repositori artifact registry untuk image Ollama yang akan digunakan di sidecar

gcloud artifacts repositories create $AR_REPO \
   
--repository-format=docker \
   
--location=$REGION \
   
--description="codelab for CR function and gpu sidecar" \
   
--project=$PROJECT_ID

4. Mendownload model Gemma 3

Pertama, Anda harus mendownload model Gemma 3 4b dari ollama. Anda dapat melakukannya dengan menginstal ollama, lalu menjalankan model gemma3:4b secara lokal.

curl -fsSL https://ollama.com/install.sh | sh
ollama serve

Sekarang di jendela terminal terpisah, jalankan perintah berikut untuk mendownload model. Jika menggunakan Cloud Shell, Anda dapat membuka jendela terminal tambahan dengan mengklik ikon plus di panel menu kanan atas.

ollama run gemma3:4b

Setelah ollama berjalan, jangan ragu untuk mengajukan beberapa pertanyaan kepada model, misalnya:

"why is the sky blue?"

Setelah selesai melakukan chat dengan ulama, Anda dapat keluar dari chat dengan menjalankan

/bye

Kemudian, di jendela terminal pertama, jalankan perintah berikut untuk berhenti menayangkan ollama secara lokal

# on Linux / Cloud Shell press Ctrl^C or equivalent for your shell

Anda dapat menemukan tempat Ollama mendownload model, bergantung pada sistem operasi Anda, di sini.

https://github.com/ollama/ollama/blob/main/docs/faq.md#where-are-models-stored

Jika menggunakan Cloud Workstations, Anda dapat menemukan model ollama yang didownload di sini /home/$USER/.ollama/models

Pastikan model Anda dihosting di sini:

ls /home/$USER/.ollama/models

sekarang pindahkan model gemma3:4b ke bucket GCS Anda

gsutil cp -r /home/$USER/.ollama/models gs://$BUCKET_GEMMA_NAME

5. Membuat fungsi Cloud Run

Buat folder root untuk kode sumber Anda.

mkdir codelab-crf-sidecar-gpu &&
cd codelab
-crf-sidecar-gpu &&
mkdir cr
-function &&
mkdir ollama
-gemma3 &&
cd cr
-function

Buat subfolder bernama src. Di dalam folder, buat file bernama index.ts

mkdir src &&
touch src
/index.ts

Perbarui index.ts dengan kode berikut:

//import util from 'util';
import { cloudEvent, CloudEvent } from "@google-cloud/functions-framework";
import { StorageObjectData } from "@google/events/cloud/storage/v1/StorageObjectData";
import { Storage } from "@google-cloud/storage";

// Initialize the Cloud Storage client
const storage = new Storage();

import { genkit } from 'genkit';
import { ollama } from 'genkitx-ollama';

const ai = genkit({
   
plugins: [
       
ollama({
           
models: [
               
{
                   
name: 'gemma3:4b',
                   
type: 'generate', // type: 'chat' | 'generate' | undefined
               
},
           
],
           
serverAddress: 'http://127.0.0.1:11434', // default local address
       
}),
   
],
});


// Register a CloudEvent callback with the Functions Framework that will
// be triggered by Cloud Storage.

//functions.cloudEvent('helloGCS', await cloudEvent => {
cloudEvent("gcs-cloudevent", async (cloudevent: CloudEvent<StorageObjectData>) => {
   
console.log("---------------\nProcessing for ", cloudevent.subject, "\n---------------");

   
if (cloudevent.data) {

       
const data = cloudevent.data;

       
if (data && data.bucket && data.name) {
           
const bucketName = cloudevent.data.bucket;
           
const fileName = cloudevent.data.name;
           
const filePath = `${cloudevent.data.bucket}/${cloudevent.data.name}`;

           
console.log(`Attempting to download: ${filePath}`);

           
try {
               
// Get a reference to the bucket
               
const bucket = storage.bucket(bucketName!);

               
// Get a reference to the file
               
const file = bucket.file(fileName!);

               
// Download the file's contents
               
const [content] = await file.download();

               
// 'content' is a Buffer. Convert it to a string.
               
const fileContent = content.toString('utf8');

               
console.log(`Sending file to Gemma 3 for summarization`);
               
const { text } = await ai.generate({
                   
model: 'ollama/gemma3:4b',
                   
prompt: `Summarize the following document in just a few sentences ${fileContent}`,
               
});

               
console.log(text);

           
} catch (error: any) {

               
console.error('An error occurred:', error.message);
           
}
       
} else {
           
console.warn("CloudEvent bucket name is missing!", cloudevent);
       
}
   
} else {
       
console.warn("CloudEvent data is missing!", cloudevent);
   
}
});

Sekarang di direktori root crf-sidecar-gpu, buat file bernama package.json dengan konten berikut:

{
    "main": "lib/index.js",
    "name": "ingress-crf-genkit",
    "version": "1.0.0",
    "scripts": {
        "build": "tsc"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "dependencies": {
        "@google-cloud/functions-framework": "^3.4.0",
        "@google-cloud/storage": "^7.0.0",
        "genkit": "^1.1.0",
        "genkitx-ollama": "^1.1.0",
        "@google/events": "^5.4.0"
    },
    "devDependencies": {
        "typescript": "^5.5.2"
    }
}

Buat tsconfig.json juga di tingkat direktori root dengan konten berikut:

{
 
"compileOnSave": true,
 
"include": [
   
"src"
 
],
 
"compilerOptions": {
   
"module": "commonjs",
   
"noImplicitReturns": true,
   
"outDir": "lib",
   
"sourceMap": true,
   
"strict": true,
   
"target": "es2017",
   
"skipLibCheck": true,
   
"esModuleInterop": true
 
}
}

6. Men-deploy fungsi

Pada langkah ini, Anda akan men-deploy fungsi Cloud Run dengan menjalankan perintah berikut.

Catatan: instance maksimum harus ditetapkan ke angka yang kurang dari atau sama dengan kuota GPU Anda.

gcloud beta run deploy $FUNCTION_NAME \
  --region $REGION \
  --function gcs-cloudevent \
  --base-image nodejs22 \
  --source . \
  --no-allow-unauthenticated \
  --max-instances 2 # this should be less than or equal to your GPU quota

7. Membuat sidecar

Anda dapat mempelajari lebih lanjut cara menghosting Ollama dalam layanan Cloud Run di https://cloud.google.com/run/docs/tutorials/gpu-gemma-with-ollama

Pindah ke direktori untuk sidecar Anda:

cd ../ollama-gemma3

Buat file Dockerfile dengan konten berikut:

FROM ollama/ollama:latest

# Listen on all interfaces, port 11434
ENV OLLAMA_HOST 0.0.0.0:11434

# Store model weight files in /models
ENV OLLAMA_MODELS /models

# Reduce logging verbosity
ENV OLLAMA_DEBUG false

# Never unload model weights from the GPU
ENV OLLAMA_KEEP_ALIVE -1

# Store the model weights in the container image
ENV MODEL gemma3:4b
RUN ollama serve & sleep 5 && ollama pull $MODEL

# Start Ollama
ENTRYPOINT ["ollama", "serve"]

Membangun image

gcloud builds submit \
   --tag $REGION-docker.pkg.dev/$PROJECT_ID/$AR_REPO/ollama-gemma3 \
   --machine-type e2-highcpu-32

8. Memperbarui fungsi dengan sidecar

Untuk menambahkan file bantuan ke layanan, tugas, atau fungsi yang ada, Anda dapat memperbarui file YAML agar berisi file bantuan.

Ambil YAML untuk fungsi Cloud Run yang baru saja Anda deploy dengan menjalankan:

gcloud run services describe $FUNCTION_NAME --format=export > add-sidecar-service.yaml

Sekarang tambahkan sidecar ke CRf dengan memperbarui YAML sebagai berikut:

  1. Sisipkan fragmen YAML berikut tepat di atas baris runtimeClassName: run.googleapis.com/linux-base-image-update. -image harus selaras dengan item penampung ingress -image
    - image: YOUR_IMAGE_SIDECAR:latest
        name
: gemma-sidecar
        env
:
       
- name: OLLAMA_FLASH_ATTENTION
          value
: '1'
        resources
:
          limits
:
            cpu
: 6000m
            nvidia
.com/gpu: '1'
            memory
: 16Gi
        volumeMounts
:
       
- name: gcs-1
          mountPath
: /root/.ollama
        startupProbe
:
          failureThreshold
: 2
          httpGet
:
            path
: /
            port: 11434
          initialDelaySeconds: 60
          periodSeconds: 60
          timeoutSeconds: 60
      nodeSelector:
        run.googleapis.com/
accelerator: nvidia-l4
      volumes
:
       
- csi:
            driver
: gcsfuse.run.googleapis.com
            volumeAttributes
:
              bucketName
: YOUR_BUCKET_GEMMA_NAME
          name
: gcs-1
  1. Jalankan perintah berikut untuk memperbarui fragmen YAML dengan variabel lingkungan Anda:
sed -i "s|YOUR_IMAGE_SIDECAR|$IMAGE_SIDECAR|; s|YOUR_BUCKET_GEMMA_NAME|$BUCKET_GEMMA_NAME|" add-sidecar-service.yaml

File YAML yang sudah selesai akan terlihat seperti ini:

##############################################
# DO NOT COPY - For illustration purposes only
##############################################

apiVersion
: serving.knative.dev/v1
kind
: Service
metadata
:
  annotations
:    
    run
.googleapis.com/build-base-image: us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs22
    run
.googleapis.com/build-enable-automatic-updates: 'true'
    run
.googleapis.com/build-function-target: gcs-cloudevent
    run
.googleapis.com/build-id: f0122905-a556-4000-ace4-5c004a9f9ec6
    run
.googleapis.com/build-image-uri:<YOUR_IMAGE_CRF>
    run
.googleapis.com/build-name: <YOUR_BUILD_NAME>
    run
.googleapis.com/build-source-location: <YOUR_SOURCE_LOCATION>
    run
.googleapis.com/ingress: all
    run
.googleapis.com/ingress-status: all
    run
.googleapis.com/urls: '["<YOUR_CLOUD_RUN_FUNCTION_URLS"]'
  labels
:
    cloud
.googleapis.com/location: <YOUR_REGION>
  name
: <YOUR_FUNCTION_NAME>
 
namespace: '392295011265'
spec
:
 
template:
    metadata
:
      annotations
:
        autoscaling
.knative.dev/maxScale: '4'
        run
.googleapis.com/base-images: '{"":"us-central1-docker.pkg.dev/serverless-runtimes/google-22/runtimes/nodejs22"}'
        run
.googleapis.com/client-name: gcloud
        run
.googleapis.com/client-version: 514.0.0
        run
.googleapis.com/startup-cpu-boost: 'true'
      labels
:
        client
.knative.dev/nonce: hzhhrhheyd
        run
.googleapis.com/startupProbeType: Default
    spec
:
      containerConcurrency
: 80
      containers
:
     
- image: <YOUR_FUNCTION_IMAGE>
        ports
:
       
- containerPort: 8080
          name
: http1
        resources
:
          limits
:
            cpu
: 1000m
            memory
: 512Mi
        startupProbe
:
          failureThreshold
: 1
          periodSeconds
: 240
          tcpSocket
:
            port
: 8080
          timeoutSeconds
: 240
     
- image: <YOUR_SIDECAR_IMAGE>:latest
        name
: gemma-sidecar
        env
:
       
- name: OLLAMA_FLASH_ATTENTION
          value
: '1'
        resources
:
          limits
:
            cpu
: 6000m
            nvidia
.com/gpu: '1'
            memory
: 16Gi
        volumeMounts
:
       
- name: gcs-1
          mountPath
: /root/.ollama
        startupProbe
:
          failureThreshold
: 2
          httpGet
:
            path
: /
            port: 11434
          initialDelaySeconds: 60
          periodSeconds: 60
          timeoutSeconds: 60
      nodeSelector:
        run.googleapis.com/
accelerator: nvidia-l4
      volumes
:
       
- csi:
            driver
: gcsfuse.run.googleapis.com
            volumeAttributes
:
              bucketName
: <YOUR_BUCKET_NAME>
          name
: gcs-1
      runtimeClassName
: run.googleapis.com/linux-base-image-update
      serviceAccountName
: <YOUR_SA_ADDRESS>
      timeoutSeconds
: 300
  traffic
:
 
- latestRevision: true
    percent
: 100

##############################################
# DO NOT COPY - For illustration purposes only
##############################################

Sekarang, perbarui fungsi dengan sidecar dengan menjalankan perintah berikut.

gcloud run services replace add-sidecar-service.yaml

Terakhir, buat pemicu eventarc untuk fungsi. Perintah ini juga menambahkannya ke fungsi.

Catatan: jika membuat bucket multi-regional, Anda harus mengubah parameter --location

gcloud eventarc triggers create my-crf-summary-trigger  \
    --location=$REGION \
    --destination-run-service=$FUNCTION_NAME  \
    --destination-run-region=$REGION \
    --event-filters="type=google.cloud.storage.object.v1.finalized" \
    --event-filters="bucket=$BUCKET_DOCS_NAME" \
    --service-account=$SERVICE_ACCOUNT_ADDRESS

9. Menguji fungsi

Upload file teks biasa untuk ringkasan. Tidak tahu apa yang harus diringkas? Minta Gemini untuk memberikan deskripsi singkat 1-2 halaman tentang sejarah. Kemudian, upload file teks biasa tersebut ke bucket $BUCKET_DOCS_NAME untuk model Gemma3:4b guna menulis ringkasan ke log fungsi.

Dalam log, Anda akan melihat sesuatu yang mirip dengan berikut ini:

---------------
Processing for objects/dogs.txt
---------------
Attempting to download: <YOUR_PROJECT_ID>-codelab-crf-sidecar-gpu-docs/dogs.txt
Sending file to Gemma 3 for summarization
...
Here's a concise summary of the document "Humanity's Best Friend":
The dog's domestication, beginning roughly 20,000-40,000 years ago, represents a unique, deeply intertwined evolutionary partnership with humans, predating the domestication of any other animal
<
...>
solidifying their long-standing role as humanity's best friend.

10. Pemecahan masalah

Berikut beberapa error terkait kesalahan ketik yang mungkin Anda alami:

  1. Jika Anda mendapatkan error PORT 8080 is in use, pastikan Dockerfile untuk sidecar Ollama menggunakan port 11434. Pastikan juga Anda menggunakan image sidecar yang benar jika memiliki beberapa image Ollama di repo AR. Fungsi Cloud Run ditayangkan di port 8080, dan jika Anda menggunakan image Ollama yang berbeda sebagai sidecar yang juga ditayangkan di 8080, Anda akan mengalami error ini.
  2. Jika Anda mendapatkan error failed to build: (error ID: 7485c5b6): function.js does not exist, pastikan file package.json dan tsconfig.json berada di tingkat yang sama dengan direktori src.
  3. Jika Anda mendapatkan error ERROR: (gcloud.run.services.replace) spec.template.spec.node_selector: Max instances must be set to 4 or fewer in order to set GPU requirements., di file YAML, ubah autoscaling.knative.dev/maxScale: '100' menjadi 1 atau menjadi sesuatu yang kurang dari atau sama dengan kuota GPU Anda.