1. Giới thiệu
Tổng quan
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách tạo một quy trình xử lý bằng AI không đồng bộ, dựa trên sự kiện. Bạn sẽ triển khai một mô hình nguồn mở bằng Ollama trên Nhóm Worker Cloud Run. Nhóm worker kéo các thông báo từ một chủ đề Pub/Sub và xử lý các thông báo đó bằng mô hình gemma3:4b.
Kiến thức bạn sẽ học được
- Cách sử dụng nhóm worker với gói thuê bao Pub/Sub Pull
- Cách sử dụng Ollama để suy luận dưới dạng một nhóm worker
2. Trước khi bắt đầu
Bật API
Trước khi có thể bắt đầu sử dụng lớp học lập trình này, hãy bật các API sau bằng cách chạy:
gcloud services enable run.googleapis.com \
cloudbuild.googleapis.com \
artifactregistry.googleapis.com \
pubsub.googleapis.com \
storage.googleapis.com
3. Thiết lập và yêu cầu
Để thiết lập các tài nguyên cần thiết, hãy làm theo các bước sau:
- Thiết lập các biến môi trường cho lớp học lập trình này:
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
- Tạo tài khoản dịch vụ cho nhóm worker
gcloud iam service-accounts create ${SERVICE_ACCOUNT_NAME} \
--display-name="Ollama Worker Service Account"
- Cấp quyền truy cập Pub/Sub cho SA
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${SERVICE_ACCOUNT_EMAIL}" \
--role="roles/pubsub.subscriber"
- Tạo một kho lưu trữ AR cho hình ảnh nhóm nhân viên
gcloud artifacts repositories create ${AR_REPO_NAME} \
--repository-format=docker \
--location=${REGION}
- Tạo chủ đề và gói thuê bao PubSub
gcloud pubsub topics create $TOPIC_NAME
gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_NAME
4. Tải xuống và lưu trữ mô hình trên GCS
Thay vì kéo mô hình trực tiếp vào trong vùng chứa trong quá trình xây dựng (việc này có thể diễn ra chậm và không hiệu quả), chúng ta sẽ kéo mô hình vào một máy cục bộ bằng cách sử dụng Ollama CLI rồi tải các tệp mô hình lên một bộ chứa GCS. Sau đó, nhóm nhân viên sẽ gắn nhóm này để truy cập vào mô hình.
- Cài đặt Ollama trên máy cục bộ:
Chạy lệnh sau để cài đặt Ollama trên Linux. Đối với các hệ điều hành khác, vui lòng tham khảo trang web của Ollama.
curl -fsSL https://ollama.com/install.sh | sh
- Khởi động dịch vụ Ollama và kéo mô hình:
Trước tiên, hãy bắt đầu dịch vụ Ollama ở chế độ nền.
ollama serve &
ollama pull gemma3:4b
- Tạo bộ chứa GCS:
Tạo bộ chứa GCS bằng biến môi trường BUCKET_NAME mà bạn đã thiết lập trước đó.
gsutil mb gs://${BUCKET_NAME}
- Tải các tệp mô hình lên bộ chứa GCS:
Ollama lưu trữ các tệp mô hình trong thư mục ~/.ollama/models. Tải nội dung của thư mục này lên bộ chứa GCS. Thao tác này sẽ sao chép tất cả các mô hình bạn đã tải xuống.
gsutil -m cp -r ~/.ollama/models/* gs://${BUCKET_NAME}/
- Cấp cho SA quyền truy cập vào bộ chứa Cloud Storage
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \
--member=serviceAccount:${SERVICE_ACCOUNT_EMAIL} \
--role=roles/storage.objectViewer
5. Tạo công việc trên Cloud Run
Tác vụ Cloud Run sử dụng 2 vùng chứa:
- ollama-coordinator – để lưu trữ ollama và phân phát mô hình gemma 3 4B
- pubsub-pull-msg – để kéo từ gói thuê bao pubsub và chuyển thông báo đến vùng chứa ollama-coordinator
Trước tiên, bạn sẽ tạo vùng chứa ollama-coordinator.
- Tạo một thư mục mẹ cho lớp học lập trình:
mkdir codelab-ollama-wp
cd codelab-ollama-wp
- Tạo một thư mục cho vùng chứa ollama-coordinator
mkdir ollama-coordinator
cd ollama-coordinator
- Tạo một
Dockerfilecó nội dung sau
# 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"]
- Tạo vùng chứa ollama
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${OLLAMA_IMAGE_NAME} --timeout=20m
Tiếp theo, bạn sẽ tạo vùng chứa pubsub-pull-msg.
- Tạo một thư mục cho vùng chứa pubsub-pull-msg
cd ..
mkdir pubsub-pull-msg
cd pubsub-pull-msg
- Tạo một
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"]
- Tạo tệp
requirements.txtcó nội dung sau
google-cloud-pubsub
requests
- Tạo tệp
main.pycó nội dung sau
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()
- Bây giờ, hãy tạo vùng chứa pubsub-pull-msg
gcloud builds submit --tag ${REGION}-docker.pkg.dev/${PROJECT_ID}/${AR_REPO_NAME}/${PULL_MSG_IMAGE_NAME}
6. Triển khai và thực thi lệnh
Trong bước này, bạn sẽ tạo một tác vụ Cloud Run bằng cách triển khai một tệp yaml.
Di chuyển đến thư mục gốc để tạo tệp yaml.
cd ..
- Tạo tệp
worker-pool.template.yamlcó nội dung sau
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
Sau đó, hãy xác định URL đầy đủ của hình ảnh và sử dụng sed để thay thế các biến trong tệp mẫu, tạo ra worker-pool.yaml cuối cùng.
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
Giờ đây, bạn có thể triển khai
gcloud beta run worker-pools replace worker-pool.yaml
Và kiểm tra
gcloud pubsub topics publish ${TOPIC_NAME} --message="What is 1 + 1?"
Sau đó, hãy xem nhật ký. Bạn có thể phải đợi một phút hoặc truy cập vào trang nhóm worker của Cloud Console và xem nhật ký theo thời gian thực.
gcloud alpha run worker-pools logs read "codelab-ollama-wp" --limit 10
và bạn sẽ thấy một dòng chữ
Ollama response: {"model": "gemma3:4b", "created_at": "2025-11-06T23:48:39.572079369Z", "response": "1 + 1 = 2\n", ...
7. Xin chúc mừng!
Chúc mừng bạn đã hoàn thành lớp học lập trình này!
Bạn nên xem tài liệu về Cloud Run.
Nội dung đã đề cập
- Cách sử dụng nhóm worker Cloud Run với gói thuê bao Pub/Sub Pull
- Cách sử dụng Ollama để suy luận dưới dạng một nhóm worker Cloud Run
8. Dọn dẹp
Để tránh bị tính phí vào tài khoản Google Cloud của bạn cho các tài nguyên được dùng trong hướng dẫn này, hãy xoá dự án chứa các tài nguyên đó hoặc giữ lại dự án rồi xoá từng tài nguyên.
Xoá dự án
Cách dễ nhất để không bị tính phí là xoá dự án mà bạn đã tạo cho hướng dẫn này.
Cách xoá dự án:
- Trong bảng điều khiển Google Cloud, hãy chuyển đến trang Quản lý tài nguyên.
- Trong danh sách dự án, hãy chọn dự án mà bạn muốn xoá, rồi nhấp vào Xoá.
- Trong hộp thoại, hãy nhập mã dự án rồi nhấp vào Tắt để xoá dự án.
Xoá từng tài nguyên
Để xoá từng tài nguyên, hãy chạy các lệnh sau:
- Xoá nhóm nhân viên Cloud Run:
gcloud beta run worker-pools delete codelab-ollama-wp --region ${REGION}
- Xoá bộ chứa GCS:
gsutil -m rm -r gs://${BUCKET_NAME}
- Xoá gói thuê bao và chủ đề Pub/Sub:
gcloud pubsub subscriptions delete ${SUBSCRIPTION_NAME}
gcloud pubsub topics delete ${TOPIC_NAME}
- Xoá kho lưu trữ Artifact Registry:
gcloud artifacts repositories delete ${AR_REPO_NAME} --location=${REGION} --quiet
- Xoá tài khoản dịch vụ:
gcloud iam service-accounts delete ${SERVICE_ACCOUNT_EMAIL} --quiet
Dọn dẹp các tệp trên thiết bị
Để dọn dẹp các tệp cục bộ, hãy làm như sau:
- Dừng dịch vụ Ollama cục bộ:Nếu đã khởi động Ollama bằng
ollama serve &, bạn có thể dừng dịch vụ này bằng cách tìm mã nhận dạng quy trình (PID) của dịch vụ rồi dùng lệnhkill.# Find the process ID of the Ollama server pgrep ollama # Replace <PID> with the actual process ID obtained from the previous command kill <PID> - Xoá các mô hình đã tải xuống:
rm -rf ~/.ollama/models
- Gỡ cài đặt Ollama:
Làm theo hướng dẫn trên trang web Ollama để gỡ cài đặt Ollama khỏi máy cục bộ.