۱. مقدمه
نمای کلی
در این آزمایشگاه کد، شما یاد خواهید گرفت که چگونه یک خط لوله پردازش هوش مصنوعی ناهمزمان و مبتنی بر رویداد بسازید. شما یک مدل متنباز را با استفاده از Ollama روی یک Cloud Run Worker Pool مستقر خواهید کرد. Worker Pool پیامها را از یک Pub/Sub topic دریافت کرده و آنها را با استفاده از یک مدل gemma3:4b پردازش میکند.
آنچه یاد خواهید گرفت
- نحوه استفاده از استخرهای کارگری با اشتراک Pub/Sub Pull
- نحوه استفاده از Ollama برای انجام استنتاج به عنوان یک worker pool
۲. قبل از شروع
فعال کردن APIها
قبل از اینکه بتوانید از این codelab استفاده کنید، API های زیر را با اجرای دستور زیر فعال کنید:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
pubsub.googleapis.com \
storage.googleapis.com
۳. تنظیمات و الزامات
برای تنظیم منابع مورد نیاز، مراحل زیر را دنبال کنید:
- متغیرهای محیطی را برای این codelab تنظیم کنید:
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
- یک حساب کاربری سرویس برای مجموعه کارگران ایجاد کنید
gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
--display-name="Ollama Worker Service Account"
- به SA دسترسی Pub/Sub را اعطا کنید
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
--role="roles/pubsub.subscriber"
- یک مخزن AR برای تصویر استخر کارگران ایجاد کنید
gcloud artifacts repositories create ${AR_REPO_NAME} \
--repository-format=docker \
--location=${REGION}
- ایجاد موضوع PubSub و اشتراک
gcloud pubsub topics create $TOPIC_NAME
gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_NAME
۴. دانلود و میزبانی مدل روی GCS
به جای اینکه مدل را مستقیماً در طول فرآیند ساخت به داخل کانتینر منتقل کنیم، که میتواند کند و ناکارآمد باشد، مدل را با استفاده از رابط خط فرمان Ollama به یک دستگاه محلی منتقل میکنیم و سپس فایلهای مدل را در یک سطل GCS آپلود میکنیم. سپس مخزن کارگران (worker pool) این سطل را برای دسترسی به مدل، سوار (mount) میکند.
- Ollama را روی دستگاه محلی خود نصب کنید:
برای نصب Ollama روی لینوکس، دستور زیر را اجرا کنید. برای سایر سیستم عاملها، لطفاً به وبسایت Ollama مراجعه کنید.
curl -fsSL https://ollama.com/install.sh | sh
- سرویس Ollama را شروع کنید و مدل را دریافت کنید:
First, start the Ollama service in the background.
ollama serve &
ollama pull gemma3:4b
- یک سطل GCS ایجاد کنید:
با استفاده از متغیر محیطی BUCKET_NAME که قبلاً تنظیم کردهاید، سطل GCS را ایجاد کنید.
gsutil mb gs://${BUCKET_NAME}
- فایلهای مدل را در سطل GCS خود آپلود کنید:
اولاما فایلهای مدل را در دایرکتوری ~/.ollama/models ذخیره میکند. محتویات این دایرکتوری را در مخزن GCS خود آپلود کنید. این کار تمام مدلهایی را که دانلود کردهاید کپی میکند.
gsutil -m cp -r ~/.ollama/models/* gs://${BUCKET_NAME}/
- به SA دسترسی به فضای ذخیرهسازی ابری (Cloud Storage) را اعطا کنید.
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \
--member=serviceAccount:${SERVICE_ACCOUNT_EMAIL} \
--role=roles/storage.objectViewer
۵. کار Cloud Run را ایجاد کنید
کار Cloud Run از 2 کانتینر استفاده میکند:
- هماهنگکننده اولاما - برای میزبانی اولاما و ارائه مدل جما ۳ ۴ب
- pubsub-pull-msg - برای دریافت پیام از اشتراک pubsub و ارسال آن به کانتینر ollama-coordinator
ابتدا، کانتینر ollama-coordinator را ایجاد خواهید کرد.
- یک دایرکتوری والد برای codelab ایجاد کنید:
mkdir codelab-ollama-wp
cd codelab-ollama-wp
- Create a directory for the ollama-coordinator container
mkdir ollama-coordinator
cd ollama-coordinator
- یک
Dockerfileبا محتویات زیر ایجاد کنید
# 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"]
- ساخت کانتینر اولاما
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${OLLAMA_IMAGE_NAME} --timeout=20m
در مرحله بعد، کانتینر pubsub-pull-msg را ایجاد خواهید کرد.
- یک دایرکتوری برای کانتینر pubsub-pull-msg ایجاد کنید
cd ..
mkdir pubsub-pull-msg
cd pubsub-pull-msg
- ایجاد یک
Dockerfile
# 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"]
- یک فایل
requirements.txtبا محتوای زیر ایجاد کنید
google-cloud-pubsub
requests
- یک فایل
main.pyبا محتوای زیر ایجاد کنید.
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()
- حالا کانتینر pubsub-pull-msg را بسازید
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${PULL_MSG_IMAGE_NAME}
۶. استقرار و اجرای کار
در این مرحله، با استقرار یک فایل yaml، کار Cloud Run را ایجاد خواهید کرد.
برای ایجاد فایل yaml به پوشه ریشه بروید.
cd ..
- یک فایل
worker-pool.template.yamlبا محتوای زیر ایجاد کنید.
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
سپس، URL های کامل تصویر را تعریف کنید و sed برای جایگزینی متغیرها در فایل الگو استفاده کنید و فایل worker-pool.yaml نهایی را ایجاد کنید.
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
حالا میتوانید مستقر شوید
gcloud beta run worker-pools replace worker-pool.yaml
و تست
gcloud pubsub topics publish ${TOPIC_NAME} --message="What is 1 + 1?"
و سپس گزارشها را مشاهده کنید. ممکن است لازم باشد یک دقیقه صبر کنید یا میتوانید به صفحه استخر کارگران Cloud Console بروید و گزارشها را به صورت زنده مشاهده کنید.
gcloud alpha run worker-pools logs read "codelab-ollama-wp" --limit 10
و شما باید چیزی را ببینید که میگوید
Ollama response: {"model": "gemma3:4b", "created_at": "2025-11-06T23:48:39.572079369Z", "response": "1 + 1 = 2\n", ...
۷. تبریک میگویم!
تبریک میگویم که آزمایشگاه کد را تمام کردید!
توصیه میکنیم مستندات Cloud Run را بررسی کنید.
آنچه ما پوشش دادهایم
- نحوه استفاده از استخرهای کاری Cloud Run با اشتراک Pub/Sub Pull
- نحوه استفاده از Ollama برای انجام استنتاج به عنوان یک مخزن کارگر Cloud Run
۸. تمیز کردن
To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, either delete the project that contains the resources, or keep the project and delete the individual resources.
حذف پروژه
سادهترین راه برای حذف هزینهها، حذف پروژهای است که برای آموزش ایجاد کردهاید.
برای حذف پروژه:
- در کنسول گوگل کلود، به صفحه مدیریت منابع بروید.
- در لیست پروژهها، پروژهای را که میخواهید حذف کنید انتخاب کنید و سپس روی «حذف» کلیک کنید.
- در کادر محاورهای، شناسه پروژه را تایپ کنید و سپس برای حذف پروژه، روی خاموش کردن کلیک کنید.
حذف منابع فردی
برای حذف منابع تکی، دستورات زیر را اجرا کنید:
- حذف مجموعه کارگران Cloud Run:
gcloud beta run worker-pools delete codelab-ollama-wp --region ${REGION}
- سطل GCS را حذف کنید:
gsutil -m rm -r gs://${BUCKET_NAME}
- اشتراک Pub/Sub و موضوع را حذف کنید:
gcloud pubsub subscriptions delete ${SUBSCRIPTION_NAME}
gcloud pubsub topics delete ${TOPIC_NAME}
- مخزن رجیستری Artifact را حذف کنید:
gcloud artifacts repositories delete ${AR_REPO_NAME} --location=${REGION} --quiet
- حذف حساب کاربری سرویس:
gcloud iam service-accounts delete ${SERVICE_ACCOUNT_EMAIL} --quiet
Cleaning up local files
برای پاک کردن فایلهای محلی، موارد زیر را انجام دهید:
- سرویس محلی Ollama را متوقف کنید: اگر Ollama را با
ollama serve &راهاندازی کردهاید، میتوانید با پیدا کردن شناسه فرآیند (PID) آن و سپس استفاده از دستورkill، آن را متوقف کنید.# Find the process ID of the Ollama server pgrep ollama # Replace <PID> with the actual process ID obtained from the previous command kill <PID> - مدلهای دانلود شده را حذف کنید:
rm -rf ~/.ollama/models
- اولاما را حذف نصب کنید:
برای حذف نصب Ollama از دستگاه محلی خود، دستورالعملهای موجود در وبسایت Ollama را دنبال کنید.