Ollama'yı çıkarım için çalışan havuzu olarak barındırma

1. Giriş

Genel Bakış

Bu codelab'de, olay odaklı ve eşzamansız bir yapay zeka işleme ardışık düzeni oluşturmayı öğreneceksiniz. Cloud Run Worker Pool'da Ollama'yı kullanarak açık kaynaklı bir model dağıtacaksınız. Çalışan havuzu, Pub/Sub konusundan mesajları çeker ve bunları gemma3:4b modeli kullanarak işler.

Neler öğreneceksiniz?

  • Çalışan havuzlarını Pub/Sub Pull aboneliğiyle kullanma
  • Çalışan havuzu olarak çıkarım yapmak için Ollama'yı kullanma

2. Başlamadan önce

API'leri etkinleştir

Bu codelab'i kullanmaya başlamadan önce aşağıdaki API'leri etkinleştirin:

gcloud services enable run.googleapis.com \
    cloudbuild.googleapis.com \
    artifactregistry.googleapis.com \
    pubsub.googleapis.com \
    storage.googleapis.com

3. Kurulum ve Gereksinimler

Gerekli kaynakları ayarlamak için aşağıdaki adımları uygulayın:

  1. Bu codelab için ortam değişkenlerini ayarlayın:
export PROJECT_ID=<YOUR_PROJECT_ID>
export REGION=<YOUR_REGION>

export BUCKET_NAME=$PROJECT_ID-gemma3-4b
export SERVICE_ACCOUNT_NAME=ollama-worker-sa
export SERVICE_ACCOUNT_EMAIL=${SERVICE_ACCOUNT_NAME}@${PROJECT_ID}.iam.gserviceaccount.com
export TOPIC_NAME=ollama-prompts
export SUBSCRIPTION_NAME=ollama-prompts-sub
export AR_REPO_NAME=ollama-worker-repo
export PULL_MSG_IMAGE_NAME=pubsub-pull-msg
export OLLAMA_IMAGE_NAME=ollama-coordinator
  1. Çalışan havuzu için hizmet hesabı oluşturma
gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
  --display-name="Ollama Worker Service Account"
  1. Hizmet hesabına Pub/Sub erişimi verme
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
  --member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
  --role="roles/pubsub.subscriber"
  1. Çalışan havuzu görüntüsü için bir AR deposu oluşturun
gcloud artifacts repositories create ${AR_REPO_NAME} \
  --repository-format=docker \
  --location=${REGION}
  1. PubSub konusunu ve aboneliğini oluşturma
gcloud pubsub topics create $TOPIC_NAME
gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_NAME

4. Modeli indirip GCS'de barındırma

Yavaş ve verimsiz olabilecek şekilde, derleme işlemi sırasında modeli doğrudan kapsayıcının içine çekmek yerine, Ollama CLI'yı kullanarak modeli yerel bir makineye çekecek ve ardından model dosyalarını bir GCS paketine yükleyeceğiz. Çalışan havuzu daha sonra modele erişmek için bu paketi bağlar.

  1. Ollama'yı yerel makinenize yükleyin:

Ollama'yı Linux'a yüklemek için aşağıdaki komutu çalıştırın. Diğer işletim sistemleri için lütfen �Ollama web sitesine bakın.

curl -fsSL https://ollama.com/install.sh | sh
  1. Ollama hizmetini başlatın ve modeli çekin:

Öncelikle Ollama hizmetini arka planda başlatın.

ollama serve &
ollama pull gemma3:4b
  1. GCS paketi oluşturma:

Daha önce ayarladığınız BUCKET_NAME ortam değişkenini kullanarak GCS paketini oluşturun.

gsutil mb gs://${BUCKET_NAME}
  1. Model dosyalarını GCS paketinize yükleyin:

Ollama, model dosyalarını ~/.ollama/models dizininde saklar. Bu dizinin içeriğini GCS paketinize yükleyin. Bu işlem, indirdiğiniz tüm modelleri kopyalar.

gsutil -m cp -r ~/.ollama/models/* gs://${BUCKET_NAME}/
  1. Hizmet hesabına Cloud Storage paketine erişim izni verin.
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \
     --member=serviceAccount:${SERVICE_ACCOUNT_EMAIL} \
     --role=roles/storage.objectViewer

5. Cloud Run işini oluşturma

Cloud Run işinde 2 kapsayıcı kullanılır:

  • ollama-coordinator: ollama'yı barındırmak ve gemma 3 4B modeline hizmet vermek için
  • pubsub-pull-msg: Pub/Sub aboneliğinden çekme ve mesajı ollama-coordinator kapsayıcısına iletme için

Öncelikle ollama-coordinator kapsayıcısını oluşturursunuz.

  1. Codelab için bir üst dizin oluşturun:
mkdir codelab-ollama-wp
cd codelab-ollama-wp
  1. Ollama-coordinator kapsayıcısı için bir dizin oluşturun.
mkdir ollama-coordinator
cd ollama-coordinator
  1. Aşağıdaki içeriklerle bir Dockerfile oluşturun
# Use the official Ollama image as a base image
FROM ollama/ollama

# Expose the port that Ollama listens on
EXPOSE 11434

# Set the entrypoint to start the Ollama server
ENTRYPOINT ["ollama", "serve"]
  1. Ollama kapsayıcısını oluşturma
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${OLLAMA_IMAGE_NAME} --timeout=20m

Ardından, pubsub-pull-msg kapsayıcısını oluşturursunuz.

  1. pubsub-pull-msg kapsayıcısı için bir dizin oluşturun
cd ..
mkdir pubsub-pull-msg
cd pubsub-pull-msg
  1. Dockerfile oluşturun
# Use the official Python image as a base image
FROM python:3.9-slim

# Set the working directory in the container
WORKDIR /app

# Copy the requirements file into the container
COPY requirements.txt .

# Install the required Python packages
RUN pip install --no-cache-dir -r requirements.txt

# Copy the Python script into the container
COPY main.py .

# Set the entrypoint to run the Python script
CMD ["python", "main.py"]
  1. Aşağıdaki içeriklerle bir requirements.txt dosyası oluşturun
google-cloud-pubsub
requests
  1. Aşağıdaki içeriklerle bir main.py dosyası oluşturun
import os
import sys
import requests
import json
from google.cloud import pubsub_v1

# --- Main Application Logic ---
print("--- Sidecar container script started ---")

# --- Environment and Configuration ---
project_id = os.environ.get("PROJECT_ID")
subscription_name = os.environ.get("SUBSCRIPTION_NAME")
ollama_api_url = "http://localhost:11434/api/generate"

if not project_id or not subscription_name:
    print("FATAL: PROJECT_ID and SUBSCRIPTION_NAME must be set.")
    sys.exit(1)

print(f"PROJECT_ID: {project_id}")
print(f"SUBSCRIPTION_NAME: {subscription_name}")

def callback(message):
    """Processes a single Pub/Sub message."""
    print(f"Received message ID: {message.message_id}")
    try:
        prompt = message.data.decode("utf-8")
        print(f"Decoded prompt: '{prompt}'")
        
        data = {"model": "gemma3:4b", "prompt": prompt, "stream": False}
        
        print("Sending request to Ollama...")
        response = requests.post(ollama_api_url, json=data, timeout=300)
        response.raise_for_status()
        
        print("Successfully received response from Ollama.")
        ollama_response = response.json()
        print(f"Ollama response: {json.dumps(ollama_response)[:200]}...")

        message.ack()
        print(f"Message {message.message_id} acknowledged.")

    except requests.exceptions.RequestException as e:
        print(f"Error calling Ollama API: {e}")
        message.nack()
        print(f"Message {message.message_id} not acknowledged.")
    except Exception as e:
        print(f"An unexpected error occurred in callback: {e}")
        message.nack()
        print(f"Message {message.message_id} not acknowledged.")

def main():
    """Starts the Pub/Sub subscriber."""
    subscriber = pubsub_v1.SubscriberClient()
    subscription_path = subscriber.subscription_path(project_id, subscription_name)
    
    streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback)
    print(f"Subscribed to {subscription_path}. Listening for messages...")

    try:
        # .result() will block indefinitely.
        streaming_pull_future.result()
    except Exception as e:
        print(f"A fatal error occurred in the subscriber: {e}")
        streaming_pull_future.cancel()
        streaming_pull_future.result()

if __name__ == "__main__":
    main()
  1. Şimdi pubsub-pull-msg container'ını oluşturun.
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${PULL_MSG_IMAGE_NAME}

6. İşi dağıtma ve yürütme

Bu adımda, bir YAML dosyası dağıtarak Cloud Run işini oluşturacaksınız.

YAML dosyasını oluşturmak için kök klasöre gidin.

cd ..
  1. Aşağıdaki içeriğe sahip bir worker-pool.template.yaml dosyası oluşturun.
apiVersion: run.googleapis.com/v1
kind: WorkerPool
metadata:
  name: codelab-ollama-wp
  labels:
    cloud.googleapis.com/location: europe-west1
  annotations:
    run.googleapis.com/launch-stage: BETA
    run.googleapis.com/scalingMode: manual
    run.googleapis.com/manualInstanceCount: '1'
    run.googleapis.com/gcs-fuse-mounter-enabled: "true"
spec:
  template:
    metadata:
      annotations:
        run.googleapis.com/gpu: "1"
        run.googleapis.com/gpu-zonal-redundancy-disabled: 'true'        
    spec:
      serviceAccountName: ${SERVICE_ACCOUNT_EMAIL}
      nodeSelector:
        run.googleapis.com/accelerator: nvidia-l4
      volumes:
      - name: gcs-bucket
        csi:
          driver: gcsfuse.run.googleapis.com
          readOnly: true
          volumeAttributes: 
            bucketName: ${BUCKET_NAME}
      containers:
      - image: ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${PULL_MSG_IMAGE_NAME}
        name: pubsub-pull-msg
        env:
        - name: PROJECT_ID
          value: ${PROJECT_ID}
        - name: SUBSCRIPTION_NAME
          value: "ollama-prompts-sub"
        - name: PYTHONUNBUFFERED
          value: "1"
        resources:
          limits:
            cpu: '1'
            memory: 1Gi
      - image: ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${OLLAMA_IMAGE_NAME}
        name: ollama-coordinator
        env:
        - name: OLLAMA_MODELS
          value: /mnt/models
        volumeMounts:
        - name: gcs-bucket
          mountPath: /mnt/models
        resources:
          limits:
            cpu: '6'
            nvidia.com/gpu: '1'
            memory: 16Gi

Ardından, tam resim URL'lerini tanımlayın ve şablon dosyasındaki değişkenlerin yerine sed kullanarak nihai worker-pool.yaml oluşturun.

sed -e "s|\${SERVICE_ACCOUNT_EMAIL}|${SERVICE_ACCOUNT_EMAIL}|g" \
     -e "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" \
     -e "s|\${PULL_MSG_IMAGE_NAME}|${PULL_MSG_IMAGE_NAME}|g" \
     -e "s|\${OLLAMA_IMAGE_NAME}|${OLLAMA_IMAGE_NAME}|g" \
     -e "s|\${PROJECT_ID}|${PROJECT_ID}|g" \
     -e "s|\${REGION}|${REGION}|g" \
     -e "s|\${AR_REPO_NAME}|${AR_REPO_NAME}|g" \
     worker-pool.template.yaml > worker-pool.yaml

Artık dağıtabilirsiniz

gcloud beta run worker-pools replace worker-pool.yaml

Ve Test Etme

gcloud pubsub topics publish ${TOPIC_NAME} --message="What is 1 + 1?"

Ardından günlükleri görüntüleyin. Bir dakika beklemeniz gerekebilir veya Cloud Console çalışan havuzu sayfasına gidip günlükleri gerçek zamanlı olarak izleyebilirsiniz.

gcloud alpha run worker-pools logs read "codelab-ollama-wp" --limit 10

ve

Ollama response: {"model": "gemma3:4b", "created_at": "2025-11-06T23:48:39.572079369Z", "response": "1 + 1 = 2\n", ...

7. Tebrikler!

Tebrikler, codelab'i tamamladınız.

Cloud Run belgelerini incelemenizi öneririz.

İşlediğimiz konular

  • Cloud Run Worker Pool'ları Pub/Sub Pull aboneliğiyle kullanma
  • Cloud Run çalışan havuzu olarak çıkarım yapmak için Ollama'yı kullanma

8. Temizleme

Bu eğitimde kullanılan kaynaklar için Google Cloud hesabınızın ücretlendirilmesini önlemek amacıyla kaynakları içeren projeyi silin veya projeyi koruyup tek tek kaynakları silin.

Projeyi silme

Faturalandırılmanın önüne geçmenin en kolay yolu, eğitim için oluşturduğunuz projeyi silmektir.

Projeyi silmek için:

  1. Google Cloud Console'da Kaynakları yönetin sayfasına gidin.
  2. Proje listesinde silmek istediğiniz projeyi seçin ve Sil'i tıklayın.
  3. İletişim kutusunda proje kimliğini yazın ve projeyi silmek için Kapat'ı tıklayın.

Tek tek kaynakları silme

Kaynakları tek tek silmek için aşağıdaki komutları çalıştırın:

  1. Cloud Run çalışan havuzunu silin:
gcloud beta run worker-pools delete codelab-ollama-wp --region ${REGION}
  1. GCS paketini silin:
gsutil -m rm -r gs://${BUCKET_NAME}
  1. Pub/Sub aboneliğini ve konusunu silin:
gcloud pubsub subscriptions delete ${SUBSCRIPTION_NAME}
gcloud pubsub topics delete ${TOPIC_NAME}
  1. Artifact Registry deposunu silin:
gcloud artifacts repositories delete ${AR_REPO_NAME} --location=${REGION} --quiet
  1. Hizmet hesabını silin:
gcloud iam service-accounts delete ${SERVICE_ACCOUNT_EMAIL} --quiet

Yerel dosyaları temizleme

Yerel dosyaları temizlemek için aşağıdakileri yapın:

  1. Yerel Ollama hizmetini durdurma:Ollama'yı ollama serve & ile başlattıysanız işlem kimliğini (PID) bulup kill komutunu kullanarak durdurabilirsiniz.
    # Find the process ID of the Ollama server
    pgrep ollama
    
    # Replace <PID> with the actual process ID obtained from the previous command
    kill <PID>
    
  2. İndirilen modelleri silin:
rm -rf ~/.ollama/models
  1. Ollama'yı kaldırma:

Ollama'yı yerel makinenizden kaldırmak için Ollama web sitesindeki talimatları uygulayın.