1. परिचय
इस कोडलैब में, Google Cloud TPU का इस्तेमाल करके, Google Kubernetes Engine (GKE) पर ज़्यादा परफ़ॉर्मेंस वाली, मल्टी-होस्ट vLLM (वर्चुअल लार्ज लैंग्वेज मॉडल) इन्फ़्रेंसिंग सेवाओं को डिप्लॉय करने का तरीका बताया गया है. Ray का इस्तेमाल करके, डिस्ट्रिब्यूटेड इन्फ़रेंस को कॉन्फ़िगर किया जाएगा. साथ ही, LeaderWorkerSets का इस्तेमाल करके, GKE पर वर्कलोड को मैनेज किया जाएगा.
इस वॉकट्रू में, Qwen 30B जैसे बड़े मॉडल को इस्तेमाल करने के लिए, प्रोडक्शन सेटअप का सिम्युलेशन दिखाया गया है.
आपको क्या करना होगा
- ऐक्सलरेटर ट्रैफ़िक के लिए, कस्टम वीपीसी नेटवर्क बनाएं.
- Ray Operator और GCS Fuse CSI ड्राइवर के साथ GKE क्लस्टर उपलब्ध कराएं.
- मॉडल को तेज़ी से लोड करने के लिए, GCS रैपिड कैश को शुरू करें.
- आरक्षित क्षमता के साथ, एक से ज़्यादा होस्ट वाला TPU v6e नोड पूल उपलब्ध कराएं.
- मॉडल के वेट को सुरक्षित तरीके से ऐक्सेस करने के लिए, Workload Identity कॉन्फ़िगर करें.
- 30 अरब पैरामीटर वाले मॉडल को दिखाने के लिए, vLLM इंजन को डिप्लॉय और टेस्ट करें.

आपको किन चीज़ों की ज़रूरत होगी
- बिलिंग की सुविधा वाला Google Cloud प्रोजेक्ट.
- TPU v6e संसाधनों (32 चिप,
ct6e-standard-4t) के लिए Google Cloud Reservation. - सोर्स बकेट से मॉडल के वेट कॉपी करने का ऐक्सेस.
- Cloud Shell या
gcloud,kubectl, औरhelmइंस्टॉल किया गया लोकल टर्मिनल.
- अनुमानित अवधि: 60 मिनट
- अनुमानित लागत: 60 डॉलर से कम (अगर तुरंत हटा दिया जाता है).
2. शुरू करने से पहले
Google Cloud प्रोजेक्ट बनाना या चुनना
- Google Cloud Console में, Google Cloud प्रोजेक्ट चुनें या बनाएं.
- पक्का करें कि आपके Cloud प्रोजेक्ट के लिए बिलिंग की सुविधा चालू हो.
Cloud Shell शुरू करना
- Google Cloud कंसोल में सबसे ऊपर मौजूद, Cloud Shell चालू करें पर क्लिक करें.
- पुष्टि करें:
gcloud auth list
- अपने प्रोजेक्ट की पुष्टि करें:
gcloud config get project
- अगर ज़रूरी हो, तो इसे सेट करें:
export PROJECT_ID=<YOUR_PROJECT_ID>
gcloud config set project $PROJECT_ID
एनवायरमेंट वैरिएबल सेट करना
कमांड को आसानी से लागू करने के लिए, अपने शेल में इन वैरिएबल को तय करें. <YOUR_ZONE> की जगह, आपको असाइन किया गया टीपीयू ज़ोन और <YOUR_RESERVATION_NAME> की जगह, अपना बुकिंग आईडी डालें. बंद किए गए मॉडल के वेट डाउनलोड करने के लिए, आपको Hugging Face का उपयोगकर्ता ऐक्सेस टोकन बनाना होगा. इसे बनाने के बाद, <YOUR_HUGGING_FACE_TOKEN> को अपने नए टोकन से बदलें.
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
एपीआई चालू करें
ज़रूरी Google Cloud सेवाएं चालू करें:
gcloud services enable \
container.googleapis.com \
compute.googleapis.com \
iam.googleapis.com \
cloudresourcemanager.googleapis.com
3. कस्टम नेटवर्किंग बनाना
एक से ज़्यादा होस्ट वाले टीपीयू वर्कलोड के लिए, नेटवर्क के कुछ खास कॉन्फ़िगरेशन की ज़रूरत होती है. इनमें ऐक्सलरेटर के साथ बेहतर तरीके से कम्यूनिकेट करने के लिए, ज़्यादा एमटीयू साइज़ शामिल हैं. अपने क्लस्टर के लिए, कस्टम वीपीसी नेटवर्क बनाएं.
- ज़्यादा एमटीयू (8896) वाला वीपीएन नेटवर्क बनाएं:
gcloud compute --project=${PROJECT_ID} \ networks create ${GVNIC_NETWORK_PREFIX}-main \ --subnet-mode=custom \ --mtu=8896 - क्लस्टर के लिए सबनेट बनाएं:
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 - फ़ायरवॉल के ऐसे नियम बनाएं जिनसे इंटरनल ट्रैफ़िक की अनुमति मिलती हो, ताकि वर्कर आपस में कम्यूनिकेट कर सकें:
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. GKE क्लस्टर सेटअप करना
GCS फ़्यूज़ माउंट और Ray Operator वर्कलोड को सपोर्ट करने के लिए, स्टैंडर्ड GKE क्लस्टर सेटअप बनाएं.
- क्लस्टर बनाएं:
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 - क्लस्टर क्रेडेंशियल वापस पाना:
gcloud container clusters get-credentials ${CLUSTER_NAME} --region=${REGION} - Hugging Face सीक्रेट बनाएं: कंटेनर ऐक्सेस डाउनलोड के लिए, अपने टोकन को सुरक्षित तरीके से सेव करें:
kubectl create secret generic hf-secret \ --from-literal=hf_api_token=${HF_TOKEN} \ --dry-run=client -o yaml | kubectl apply -f - - Helm की मदद से, LeaderWorkerSet (LWS) इंस्टॉल करें. LWS, पॉड के उन ग्रुप को मैनेज करता है जिन्हें एक साथ शेड्यूल किया जाना चाहिए:
helm install lws oci://registry.k8s.io/lws/charts/lws \ --version=0.7.0 \ --namespace lws-system \ --create-namespace \ --wait
5. GCS रैपिड कैश की सुविधा चालू करना
सर्विस देने के दौरान, Cloud Storage से कई जीबी वज़न को तेज़ी से पढ़ने के लिए, एक GCS बकेट बनाएं और अपने ज़ोन में GCS Rapid Cache चालू करें.
- बकेट बनाएं:
gcloud storage buckets create gs://$BUCKET_NAME \ --location=$REGION \ --uniform-bucket-level-access - अपने टीपीयू ज़ोन में रैपिड कैश मेमोरी को चालू करें:
gcloud storage buckets anywhere-caches create gs://$BUCKET_NAME $ZONE \ --ttl=1d \ --admission-policy=ADMIT_ON_FIRST_MISS
6. Workload Identity और स्टोरेज की अनुमतियां सेटअप करना
लंबे समय तक इस्तेमाल की जा सकने वाली कुंजियों को एम्बेड किए बिना, अपने GKE पॉड में वेट बकेट को सुरक्षित तरीके से माउंट करने के लिए, आइडेंटिटी लिंक कॉन्फ़िगर करें.
- आईएम के लिए एक सेवा खाता बनाएं:
gcloud iam service-accounts create tpu-reader-sa - बकेट को पढ़ने की अनुमतियां देना:
gcloud storage buckets add-iam-policy-binding gs://${BUCKET_NAME} \ --member="serviceAccount:tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com" \ --role="roles/storage.objectAdmin" defaultनेमस्पेस Kubernetes सेवा खाते के लिए, Workload Identity Binding बनाएं: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]"- Kubernetes SA को एनोटेट करें:
kubectl annotate serviceaccount default iam.gke.io/gcp-service-account=tpu-reader-sa@${PROJECT_ID}.iam.gserviceaccount.com
7. मॉडल के वज़न का सेटअप
30 अरब पैरामीटर वाले मॉडल को दिखाने के लिए, आपको Hugging Face से GCS बकेट में वेट डाउनलोड करने होंगे. Cloud Shell के डिस्क कोटा की सीमा (5 जीबी) को बायपास करने के लिए, स्टैंडर्ड Kubernetes Job का इस्तेमाल करें. इससे क्लस्टर में सीधे तौर पर डाउनलोड किया जा सकता है. साथ ही, माउंट किए गए GCS Fuse वॉल्यूम में सुरक्षित तरीके से लिखा जा सकता है.
- मॉडल डाउनलोडर जॉब डिप्लॉय करना: डाउनलोड शुरू करने के लिए, यह मेनिफ़ेस्ट बनाएं और लागू करें:
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 - डाउनलोड पर नज़र रखना: डाउनलोडर पॉड के लॉग देखें, ताकि आपको पता चल सके कि डाउनलोडिंग की प्रोसेस कहां तक पहुंची है:
जॉब के पूरा होने और उसकी स्थिति 'सफल' होने तक इंतज़ार करें.kubectl logs -f job/model-downloader
8. आरक्षित टीपीयू नोड पूल बनाना
क्षमता के मौजूदा रिज़र्वेशन का इस्तेमाल करके, टीपीयू स्लाइस के लिए मल्टी-होस्ट की सुविधा चालू करें.
- बनाने का निर्देश चलाएं:
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 - नोड के जुड़ने का इंतज़ार करें: नोड एग्रीगेशन की स्केलिंग को सीधे तौर पर देखा जा सकता है.
ct6eवाले आठ नोड केkubectl get nodesमें शामिल होने तक इंतज़ार करें.
9. vLLM सेवा डिप्लॉय करना
- नेटवर्क के दावे बनाएं: आपको नेटवर्क एनवायरमेंट का अनुरोध करना होगा:
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 - लोड बैलेंसर एपीआई एंडपॉइंट डिप्लॉय करें:
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 - Deploy LeaderWorkerSet workload: यह मेनिफ़ेस्ट, आठ स्लाइस होस्ट में Ray हेड/वर्कर एग्रीगेशन को डाइनैमिक तरीके से शुरू करता है.
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. टेस्ट डिप्लॉयमेंट का जवाब
LeaderWorkerSet में मौजूद सभी पॉड को कंटेनर इमेज पुल करने, Ray को शुरू करने, और पूरी तरह से Ready होने में 5 से 10 मिनट लग सकते हैं. पॉड के शुरू होने की प्रोसेस देखकर, स्टेटस को ट्रैक किया जा सकता है:
kubectl get pods -l leaderworkerset.sigs.k8s.io/name=vllm-tpu-qwen -w
जब तक सभी आठ vllm-tpu-qwen- पॉड STATUS के तौर पर Running और READY के तौर पर 2/2 नहीं दिखते, तब तक इंतज़ार करें. साथ ही, यह पक्का करें कि लोड बैलेंसर को आगे बढ़ने से पहले कोई बाहरी आईपी मिला हो. इसमें 7 से 10 मिनट लग सकते हैं.
- Retrieve External IP:
export EXTERNAL_IP=$(kubectl get svc vllm-tpu-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $EXTERNAL_IP
चेतावनी: प्रोडक्शन सेवा में, इस एंडपॉइंट को पहचान के बारे में जानकारी रखने वाली प्रॉक्सी (आईएपी) जैसे किसी टूल से सुरक्षित किया जाना चाहिए
curlका इस्तेमाल करके, अनुमान लगाने का अनुरोध सबमिट करें: आपको JSON फ़ॉर्मैट में एक जवाब दिखेगा. इसमें जनरेट किया गया अनुमान शामिल होगा!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. व्यवस्थित करें
अपने Google Cloud खाते से लगातार शुल्क लिए जाने से बचने के लिए, इस कोडलैब के दौरान बनाई गई संसाधन मिटाएं.
- नोड पूल मिटाएं:
gcloud container node-pools delete "${NODE_POOL_NAME}" \ --cluster="${CLUSTER_NAME}" \ --region="${REGION}" \ --project="${PROJECT_ID}" --quiet - क्लस्टर मिटाएं:
gcloud container clusters delete "${CLUSTER_NAME}" \ --region="${REGION}" \ --project="${PROJECT_ID}" --quiet - नेटवर्क और फ़ायरवॉल सेटअप मिटाएं:
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 - सेवा खाते को अनलिंक करना और मिटाना:
# 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 - GCS बकेट मिटाना अपने Cloud Console पर जाएं. इसके बाद, Cloud Storage -> Buckets को चुनें. इसके बाद, inf-demo-model-storage को चुनें और फिर ‘मिटाएं' को चुनें.
12. बधाई हो
बधाई हो! आपने Google Kubernetes Engine पर, Ray का इस्तेमाल करके, एक से ज़्यादा होस्ट वाले टीपीयू पर चलने वाले vLLM स्टैक को डिप्लॉय कर लिया है. इससे अनुमान लगाने की दर ज़्यादा होती है.
आपको क्या सीखने को मिला
- तेज़ स्पीड वाले टीपीयू ट्रैफ़िक के लिए, ज़रूरत के मुताबिक कस्टम पाथवे उपलब्ध कराना.
- GCS Fuse और रीजनल रैपिड कैश का इस्तेमाल करके, डेटा को प्रोसेस किया जा रहा है.
- यह कुबेनेटिस के मल्टी-होस्ट वर्कलोड स्लाइस को मैनेज करता है. ये स्लाइस, LeaderWorkerSets के ज़रिए नेटिव तौर पर सिंक किए जाते हैं.
- ज़्यादा जानने के लिए, vLLM की उपयोगकर्ता गाइड और llm-d की डिप्लॉयमेंट गाइड देखें