1. Giới thiệu
Trong lớp học lập trình này, bạn sẽ tìm hiểu cách triển khai các dịch vụ suy luận vLLM (Mô hình ngôn ngữ lớn ảo) nhiều máy chủ có hiệu suất cao trên Google Kubernetes Engine (GKE) bằng cách sử dụng TPU của Google Cloud. Bạn sẽ định cấu hình suy luận phân tán bằng Ray và quản lý khối lượng công việc một cách tự nhiên trên GKE bằng LeaderWorkerSets.
Hướng dẫn này mô phỏng một chế độ thiết lập sản xuất để phân phát các mô hình lớn như Qwen 30B.
Bạn sẽ thực hiện
- Tạo một mạng VPC tuỳ chỉnh cho lưu lượng truy cập của trình tăng tốc.
- Cung cấp một cụm GKE bằng Trình điều khiển Ray và trình điều khiển CSI GCS Fuse.
- Khởi tạo một Bộ nhớ đệm nhanh GCS để tăng tốc độ tải mô hình.
- Cung cấp một bộ nút TPU v6e có nhiều máy chủ với dung lượng được đặt trước.
- Định cấu hình Workload Identity để truy cập an toàn vào trọng số mô hình.
- Triển khai và kiểm thử công cụ vLLM phục vụ mô hình tham số 30B.

Bạn cần có
- Một dự án trên Google Cloud đã bật tính năng thanh toán.
- Google Cloud Reservation cho tài nguyên TPU phiên bản 6e (32 chip,
ct6e-standard-4t). - Quyền truy cập để sao chép trọng số mô hình từ một nhóm nguồn.
- Cloud Shell hoặc một cửa sổ dòng lệnh cục bộ đã cài đặt
gcloud,kubectlvàhelm.
- Thời lượng ước tính: 60 phút
- Chi phí ước tính: Dưới 60 USD (giả sử việc tháo dỡ diễn ra ngay sau đó).
2. Trước khi bắt đầu
Tạo hoặc chọn một dự án trên Google Cloud
- Trong Google Cloud Console, hãy chọn hoặc tạo một dự án trên Google Cloud.
- Đảm bảo bạn đã bật tính năng thanh toán cho dự án trên đám mây.
Khởi động Cloud Shell
- Nhấp vào Kích hoạt Cloud Shell ở đầu bảng điều khiển Cloud.
- Xác minh hoạt động xác thực:
gcloud auth list
- Xác nhận dự án của bạn:
gcloud config get project
- Đặt nếu cần:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
Đặt các biến môi trường
Để dễ dàng thực thi các lệnh, hãy xác định các biến sau trong shell. Thay thế <YOUR_ZONE> bằng vùng TPU được phân bổ và <YOUR_RESERVATION_NAME> bằng mã đặt trước. Bạn sẽ cần tạo Mã truy cập người dùng Hugging Face để tải các trọng số mô hình có kiểm soát quyền truy cập xuống. Sau khi tạo, hãy thay thế <YOUR_HUGGING_FACE_TOKEN> bằng mã thông báo bạn vừa tạo.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)")
export ZONE="<YOUR_ZONE>" # e.g., us-east5-a
export REGION=${ZONE%-*}
export CLUSTER_NAME="qwen-serving-cluster"
export GVNIC_NETWORK_PREFIX="qwen-serving"
export BUCKET_NAME="inf-demo-model-storage-${PROJECT_NUMBER}"
export RESERVATION_NAME="<YOUR_RESERVATION_NAME>"
export NODE_POOL_NAME="tpu-v6e-32-resvd-pool"
export MULTIHOST_COLLECTION_NAME="tpu-6-collection"
export HF_TOKEN="<YOUR_HUGGING_FACE_TOKEN>" # Token with access to Qwen model if restricted
Bật API
Bật các dịch vụ bắt buộc của Google Cloud:
gcloud services enable \
container.googleapis.com \
compute.googleapis.com \
iam.googleapis.com \
cloudresourcemanager.googleapis.com
3. Tạo mạng tuỳ chỉnh
Các tải công việc TPU có nhiều máy chủ yêu cầu cấu hình mạng cụ thể, bao gồm cả kích thước MTU lớn hơn để giao tiếp hiệu quả với bộ tăng tốc. Tạo một mạng VPC tuỳ chỉnh cho cụm của bạn.
- Tạo mạng VPC có MTU lớn (8896):
gcloud compute --project=${PROJECT_ID} \ networks create ${GVNIC_NETWORK_PREFIX}-main \ --subnet-mode=custom \ --mtu=8896 - Tạo mạng con cho cụm:
gcloud compute --project=${PROJECT_ID} \ networks subnets create ${GVNIC_NETWORK_PREFIX}-tpu \ --network=${GVNIC_NETWORK_PREFIX}-main \ --region=${REGION} \ --range=192.168.100.0/24 - Tạo quy tắc tường lửa cho phép lưu lượng truy cập nội bộ để nhân viên có thể giao tiếp:
gcloud compute --project=${PROJECT_ID} firewall-rules create ${GVNIC_NETWORK_PREFIX}-allow-internal \ --network=${GVNIC_NETWORK_PREFIX}-main \ --allow=all \ --source-ranges=172.16.0.0/12,192.168.0.0/16,10.0.0.0/8 \ --description="Allow all internal traffic within the network."
4. Cung cấp cụm GKE
Tạo một chế độ thiết lập cụm GKE tiêu chuẩn được định cấu hình để hỗ trợ các lượt gắn GCS Fuse và khối lượng công việc của Ray Operator.
- Tạo cụm:
gcloud container clusters create ${CLUSTER_NAME} \ --project=${PROJECT_ID} \ --location=${REGION} \ --release-channel=rapid \ --machine-type=e2-standard-4 \ --network=${GVNIC_NETWORK_PREFIX}-main \ --subnetwork=${GVNIC_NETWORK_PREFIX}-tpu \ --num-nodes=1 \ --gateway-api=standard \ --enable-managed-prometheus \ --enable-dataplane-v2 \ --enable-dataplane-v2-metrics \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --addons=GcsFuseCsiDriver,RayOperator \ --enable-ip-alias - Truy xuất thông tin xác thực của cụm:
gcloud container clusters get-credentials ${CLUSTER_NAME} --region=${REGION} - Tạo khoá bí mật Hugging Face: Lưu mã thông báo của bạn một cách an toàn để tải nội dung xuống từ vùng chứa:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f - - Cài đặt LeaderWorkerSet (LWS) thông qua Helm. LWS quản lý các nhóm gồm những nhóm nhỏ phải được lên lịch cùng nhau:
helm install lws oci://registry.k8s.io/lws/charts/lws \ --version=0.7.0 \ --namespace lws-system \ --create-namespace \ --wait
5. Bật tính năng Bộ nhớ đệm nhanh của GCS
Để tăng tốc độ đọc hàng chục GB trọng số từ Cloud Storage trong quá trình phân phát, hãy tạo một bộ chứa GCS và bật GCS Rapid Cache trong vùng của bạn.
- Tạo vùng lưu trữ:
gcloud storage buckets create gs://$BUCKET_NAME \ --location=$REGION \ --uniform-bucket-level-access - Khởi chạy Rapid Cache trong vùng TPU:
gcloud storage buckets anywhere-caches create gs://$BUCKET_NAME $ZONE \ --ttl=1d \ --admission-policy=ADMIT_ON_FIRST_MISS
6. Thiết lập Workload Identity và quyền truy cập vào bộ nhớ
Định cấu hình mối liên kết danh tính để gắn an toàn nhóm trọng lượng vào các nhóm GKE mà không cần nhúng các khoá có thời gian tồn tại lâu dài.
- Tạo một Tài khoản dịch vụ IAM chuyên dụng:
gcloud iam service-accounts create tpu-reader-sa - Cấp quyền đọc cho bộ chứa:
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \ --member="serviceAccount:tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin" - Tạo Workload Identity Binding cho Tài khoản dịch vụ Kubernetes của không gian tên
default:gcloud iam service-accounts add-iam-policy-binding tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com \ --role="roles/iam.workloadIdentityUser" \ --member="serviceAccount:${PROJECT_ID}.svc.id.goog[default/default]" - Chú thích SA Kubernetes:
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com
7. Thiết lập trọng số mô hình
Để phân phát mô hình có 30 tỷ tham số, bạn cần tải các trọng số xuống từ Hugging Face vào vùng lưu trữ GCS. Để bỏ qua hạn mức đĩa của Cloud Shell (5 GB), hãy sử dụng Job Kubernetes tiêu chuẩn để tải xuống trực tiếp trong cụm và ghi vào ổ đĩa GCS Fuse được gắn một cách an toàn.
- Triển khai Công việc tải mô hình xuống: Tạo và áp dụng tệp kê khai sau đây để bắt đầu tải xuống:
cat <<EOF | kubectl apply -f - apiVersion: batch/v1 kind: Job metadata: name: model-downloader spec: ttlSecondsAfterFinished: 60 template: metadata: annotations: gke-gcsfuse/volumes: "true" gke-gcsfuse/memory-limit: "0" spec: serviceAccountName: default restartPolicy: OnFailure containers: - name: downloader image: python:3.10-slim command: ["/bin/sh", "-c"] args: - | pip install -U "huggingface_hub[hf_transfer]" filelock export HF_HUB_ENABLE_HF_TRANSFER=1 python -c ' import filelock class DummyLock: def __init__(self, *args, **kwargs): pass def __enter__(self): return self def __exit__(self, *args): pass def acquire(self, *args, **kwargs): pass def release(self, *args, **kwargs): pass filelock.FileLock = DummyLock from huggingface_hub import snapshot_download snapshot_download( repo_id="Qwen/Qwen3-30B-A3B", local_dir="/models/qwen3-30b-weights", local_dir_use_symlinks=False ) ' env: - name: HF_TOKEN valueFrom: secretKeyRef: name: hf-secret key: hf_api_token volumeMounts: - name: model-weights mountPath: /models volumes: - name: model-weights csi: driver: gcsfuse.csi.storage.gke.io volumeAttributes: bucketName: ${BUCKET_NAME} mountOptions: "implicit-dirs" EOF - Theo dõi quá trình tải xuống: Kiểm tra nhật ký của nhóm tải xuống để theo dõi tiến trình:
Chờ cho đến khi tác vụ hoàn tất với trạng thái thành công.kubectl logs -f job/model-downloader
8. Tạo Nhóm nút TPU được đặt trước
Cung cấp lát TPU thực tế có nhiều máy chủ bằng cách sử dụng chế độ đặt trước dung lượng hiện có.
- Chạy lệnh tạo:
gcloud beta container node-pools create ${NODE_POOL_NAME} \ --project=${PROJECT_ID} \ --cluster=${CLUSTER_NAME} \ --region=${REGION} \ --node-locations=${ZONE} \ --machine-type=ct6e-standard-4t \ --tpu-topology=4x8 \ --num-nodes=8 \ --scopes=https://www.googleapis.com/auth/cloud-platform \ --reservation-affinity=specific \ --reservation=${RESERVATION_NAME} \ --accelerator-network-profile=auto \ --node-labels=cloud.google.com/gke-nodepool-group-name=${MULTIHOST_COLLECTION_NAME} \ --node-labels=cloud.google.com/gke-workload-type=HIGH_AVAILABILITY \ --node-labels=cloud.google.com/gke-networking-dra-driver=true - Chờ các nút tham gia: Bạn có thể quan sát quá trình mở rộng quy mô tổng hợp nút một cách trực tiếp. Chờ cho đến khi 8 nút chứa
ct6etham giakubectl get nodes.
9. Triển khai dịch vụ vLLM
- Tạo Network Claims: Bạn cần yêu cầu môi trường mạng:
cat <<EOF | kubectl apply -f - apiVersion: resource.k8s.io/v1 kind: ResourceClaimTemplate metadata: name: all-netdev spec: spec: devices: requests: - name: req-netdev exactly: deviceClassName: netdev.google.com allocationMode: All EOF - Triển khai điểm cuối API của Bộ cân bằng tải:
cat <<EOF | kubectl apply -f - apiVersion: v1 kind: Service metadata: name: vllm-tpu-service spec: type: LoadBalancer selector: leaderworkerset.sigs.k8s.io/name: vllm-tpu-qwen leaderworkerset.sigs.k8s.io/worker-index: "0" ports: - protocol: TCP port: 8000 targetPort: 8000 EOF - Triển khai khối lượng công việc LeaderWorkerSet: Tệp kê khai này bắt đầu tổng hợp đầu/worker Ray một cách linh động trên 8 máy chủ lát.
cat <<EOF | kubectl apply -f - apiVersion: leaderworkerset.x-k8s.io/v1 kind: LeaderWorkerSet metadata: name: vllm-tpu-qwen spec: replicas: 1 leaderWorkerTemplate: size: 8 restartPolicy: RecreateGroupOnPodRestart workerTemplate: metadata: annotations: gke-gcsfuse/volumes: "true" gke-gcsfuse/memory-limit: "0" labels: leaderworkerset.sigs.k8s.io/name: vllm-tpu-qwen gke-gcsfuse/volumes: "true" spec: hostname: vllm-tpu-qwen serviceAccountName: default containers: - name: vllm-tpu image: vllm/vllm-tpu:nightly command: ["sh", "-c"] args: - | MY_TPU_IP=\$(hostname -I | awk '{print \$1}') echo "My TPU Network IP is: \$MY_TPU_IP" LEADER_DNS="vllm-tpu-qwen-0.vllm-tpu-qwen" until getent hosts \$LEADER_DNS; do echo "DNS not ready. Sleeping 5s..." sleep 5 done LEADER_IP=\$(getent hosts \$LEADER_DNS | awk '{print \$1}') export JAX_PLATFORMS='' export SCAN_TPU_CHIPS=True export TPU_MULTIHOST_BACKEND=ray export JAX_DISTRIBUTED_INITIALIZATION_TIMEOUT=300 export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:/usr/local/lib export VLLM_HOST_IP=\$MY_TPU_IP if [ "\$LWS_WORKER_INDEX" = "0" ]; then echo "Starting Ray Head..." ray start --head --port=6379 --node-ip-address=\$MY_TPU_IP --resources='{"TPU": 4}' --block & sleep 20 until ray status; do sleep 5; done echo "Starting vLLM API Server..." python3 -m vllm.entrypoints.openai.api_server \ --model=/models/qwen3-30b-weights \ --tensor-parallel-size=32 \ --pipeline-parallel-size=1 \ --distributed-executor-backend=ray \ --host=0.0.0.0 --port=8000 \ --enforce-eager \ --gpu-memory-utilization=0.90 else ray start --address=\${LEADER_IP}:6379 --node-ip-address=\$MY_TPU_IP --resources='{"TPU": 4}' --block fi ports: - containerPort: 8000 - containerPort: 6379 volumeMounts: - name: model-weights mountPath: /models readOnly: true - name: dshm mountPath: /dev/shm resources: claims: - name: net-resources limits: google.com/tpu: 4 memory: "100Gi" requests: google.com/tpu: 4 memory: "100Gi" nodeSelector: cloud.google.com/gke-tpu-accelerator: tpu-v6e-slice cloud.google.com/gke-tpu-topology: 4x8 gke.networks.io/accelerator-network-profile: auto resourceClaims: - name: net-resources resourceClaimTemplateName: all-netdev volumes: - name: model-weights csi: driver: gcsfuse.csi.storage.gke.io volumeAttributes: bucketName: ${BUCKET_NAME} mountOptions: "implicit-dirs" - name: dshm emptyDir: medium: Memory EOF
10. Phản hồi về việc triển khai thử nghiệm
Có thể mất từ 5 đến 10 phút để tất cả các nhóm trong LeaderWorkerSet kéo hình ảnh vùng chứa, khởi động Ray và trở thành Ready hoàn toàn. Bạn có thể theo dõi trạng thái bằng cách xem quá trình khởi động nhóm:
kubectl get pods -l leaderworkerset.sigs.k8s.io/name=vllm-tpu-qwen -w
Đợi cho đến khi tất cả 8 nhóm vllm-tpu-qwen- đều hiển thị STATUS dưới dạng Running và READY dưới dạng 2/2, đồng thời đảm bảo trình cân bằng tải đã nhận được một IP ngoài trước khi tiếp tục. Quá trình này có thể mất từ 7 đến 10 phút.
- Truy xuất IP ngoài:
export EXTERNAL_IP=$(kubectl get svc vllm-tpu-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $EXTERNAL_IP
Thận trọng: Trong một dịch vụ sản xuất, điểm cuối này phải được bảo mật bằng một thứ gì đó như Identity Aware Proxy (IAP)
- Gửi yêu cầu suy luận bằng
curl: Bạn sẽ thấy đầu ra tương tự như một phản hồi JSON chứa văn bản thể hiện suy luận đã tạo của bạn!curl -N -s http://$EXTERNAL_IP:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "/models/qwen3-30b-weights", "messages": [{"role": "user", "content": "Write a haiku about high-performance computing on TPUs."}], "temperature": 0.7, "max_tokens": 100, "stream": true }' | sed 's/^data: //' | grep -v '\[DONE\]' | grep -v '^$' | jq -rj '.choices[0].delta.content // empty' ; echo ""
11. Dọn dẹp
Để tránh các khoản phí phát sinh cho tài khoản Google Cloud của bạn, hãy xoá các tài nguyên đã tạo trong lớp học lập trình này.
- Xoá nhóm nút:
gcloud container node-pools delete "${NODE_POOL_NAME}" \ --cluster="${CLUSTER_NAME}" \ --region="${REGION}" \ --project="${PROJECT_ID}" --quiet - Xoá nhóm:
gcloud container clusters delete "${CLUSTER_NAME}" \ --region="${REGION}" \ --project="${PROJECT_ID}" --quiet - Xoá chế độ thiết lập Mạng và tường lửa:
gcloud compute firewall-rules delete \ "${GVNIC_NETWORK_PREFIX}-allow-internal" \ --project="${PROJECT_ID}" --quiet gcloud compute networks subnets delete "${GVNIC_NETWORK_PREFIX}-tpu" \ --region="${REGION}" --quiet gcloud compute networks delete "${GVNIC_NETWORK_PREFIX}-main" --quiet - Huỷ liên kết và xoá tài khoản dịch vụ:
# 1. Create the cleanup script cat << 'EOF' > clean_up_sa.sh #!/bin/bash # Validate that PROJECT_ID is available if [ -z "$PROJECT_ID" ]; then echo "Error: PROJECT_ID environment variable is not set." exit 1 fi SA_EMAIL="tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com" SA_MEMBER="serviceAccount:${SA_EMAIL}" echo "Gathering IAM policy for ${SA_EMAIL}..." # Fetch roles assigned to this specific SA ROLES=$(gcloud projects get-iam-policy ${PROJECT_ID} \ --flatten="bindings[].members" \ --filter="bindings.members:${SA_MEMBER}" \ --format="value(bindings.role)") if [ -z "$ROLES" ]; then echo "No IAM bindings found for this service account." else for ROLE in $ROLES; do echo "Removing binding for: ${ROLE}..." gcloud projects remove-iam-policy-binding ${PROJECT_ID} \ --member="${SA_MEMBER}" \ --role="${ROLE}" --quiet > /dev/null done echo "Successfully unbound all roles." fi # 2. Delete the service account itself echo "Deleting service account..." gcloud iam service-accounts delete ${SA_EMAIL} --project=${PROJECT_ID} --quiet echo "Cleanup complete." EOF # 2. Make the script executable and run it chmod +x clean_up_sa.sh ./clean_up_sa.sh - Xoá bộ chứa GCS Chuyển đến bảng điều khiển đám mây, chọn Cloud Storage -> Buckets (Bộ chứa), chọn inf-demo-model-storage rồi chọn "Xoá".
12. Xin chúc mừng
Xin chúc mừng! Bạn đã triển khai thành công một ngăn xếp vLLM có tốc độ suy luận cao gồm nhiều máy chủ, sử dụng Ray một cách tự nhiên trên Google Kubernetes Engine.
Kiến thức bạn học được
- Cung cấp các đường dẫn tuỳ chỉnh phù hợp với lưu lượng truy cập TPU tốc độ cao.
- Tăng trọng số bằng cách sử dụng GCS Fuse và bộ nhớ đệm nhanh theo khu vực.
- Điều phối các lát khối lượng công việc có nhiều máy chủ được đồng bộ hoá một cách tự nhiên thông qua LeaderWorkerSets.
- Để tìm hiểu thêm, hãy xem Hướng dẫn sử dụng vLLM và Hướng dẫn triển khai llm-d