הצגת מודל עם GPU יחיד ב-GKE

במדריך הזה נסביר איך לפרוס מודל שפה גדול (LLM) ולהכניס לשימוש בסביבת הייצור באמצעות GPUs ב-Google Kubernetes Engine ‏ (GKE) עם NVIDIA Triton Inference Server ו-TensorFlow Serving. המדריך הזה מספק בסיס להבנה ולבדיקה של פריסת LLM מעשית להיקש בסביבת Kubernetes מנוהלת. אתם פורסים קונטיינר מוכן מראש באשכול GKE עם GPU אחד מסוג L4 Tensor Core ומכינים את תשתית GKE לביצוע היקש אונליין.

המדריך הזה מיועד למהנדסי למידת מכונה (ML), לאדמינים ולמפעילים של פלטפורמות, ולמומחים בתחום הנתונים וה-AI שרוצים לארח מודל מאומן מראש של למידת מכונה (ML) באשכול GKE. מידע נוסף על תפקידים נפוצים ומשימות לדוגמה שמוזכרים ב Google Cloud תוכן זמין במאמר תפקידים נפוצים של משתמשים ומשימות ב-GKE.

לפני שקוראים את הדף הזה, חשוב לוודא שמכירים את הנושאים הבאים:

מטרות

  1. יוצרים אשכול GKE Autopilot או אשכול רגיל.
  2. מגדירים קטגוריה של Cloud Storage שבה נמצא המודל שאומן מראש.
  3. פורסים את מסגרת ההסקה אונליין שבחרתם.
  4. שולחים בקשת בדיקה לשירות שנפרס.

עלויות

במדריך הזה השתמשנו ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

  • GKE
  • Cloud Storage
  • מאיצי GPU L4
  • תנועת נתונים יוצאת (egress)

השתמשו במחשבון עלויות כדי להעריך את העלויות בהתאם לשימוש הצפוי.

כדי להימנע מחיובים נוספים אחרי שסיימתם את המדריך, תוכלו למחוק את המשאבים שיצרתם. מידע נוסף זמין במאמר בנושא הסרת המשאבים.

לפני שמתחילים

הגדרת הפרויקט

  1. נכנסים לחשבון Google Cloud . אנחנו ממליצים למשתמשים חדשים ב- Google Cloud ליצור חשבון כדי שיוכלו להעריך את הביצועים של המוצרים שלנו בתרחישים מהעולם האמיתי. לקוחות חדשים מקבלים בחינם גם קרדיט בשווי 300$ להרצה, לבדיקה ולפריסה של עומסי העבודה.
  2. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the GKE API, if it is not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Roles required to create a project

    To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the GKE API, if it is not already enabled.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the API

הגדרת ברירות מחדל ל-Google Cloud CLI

  1. במסוף Google Cloud , מפעילים מכונה של Cloud Shell:
    פותחים את Cloud Shell

  2. מורידים את קוד המקור של האפליקציה לדוגמה:

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
    cd kubernetes-engine-samples/ai-ml/gke-online-serving-single-gpu
    
  3. מגדירים את משתני הסביבה שמוגדרים כברירת מחדל:

    gcloud config set project PROJECT_ID
    gcloud config set compute/region COMPUTE_REGION
    

    מחליפים את הערכים הבאים:

  4. ב-Cloud Shell, יוצרים את משתני הסביבה הבאים:

    export PROJECT_ID=$(gcloud config get project)
    export REGION=$(gcloud config get compute/region)
    export K8S_SA_NAME=gpu-k8s-sa
    export GSBUCKET=$PROJECT_ID-gke-bucket
    export MODEL_NAME=mnist
    export CLUSTER_NAME=online-serving-cluster
    

יצירת אשכול GKE

אפשר להפעיל מודלים ב-GPU יחיד באשכול GKE Autopilot או באשכול רגיל. מומלץ להשתמש באשכול Autopilot כדי ליהנות מחוויית Kubernetes מנוהלת באופן מלא. ב-GKE Autopilot, המשאבים מותאמים אוטומטית לפי בקשות המודל.

כדי לבחור את מצב הפעולה של GKE שהכי מתאים לעומסי העבודה שלכם, אפשר לעיין במאמר בחירת מצב פעולה של GKE.

טייס אוטומטי

מריצים את הפקודה הבאה כדי ליצור אשכול GKE Autopilot:

‫
  gcloud container clusters create-auto ${CLUSTER_NAME} \
      --location=${REGION} \
      --project=${PROJECT_ID} \
      --release-channel=rapid

‫GKE יוצר אשכול Autopilot עם צמתים של מעבד ו-GPU לפי בקשת עומסי העבודה שנפרסו.

רגילה

  1. מריצים את הפקודה הבאה כדי ליצור אשכול GKE Standard:

      gcloud container clusters create ${CLUSTER_NAME} \
        --project=${PROJECT_ID}  \
        --location=${REGION}  \
        --workload-pool=${PROJECT_ID}.svc.id.goog \
        --addons GcsFuseCsiDriver \
        --release-channel=rapid \
        --num-nodes=1
    

    יצירת האשכול עשויה להימשך כמה דקות.

  2. מריצים את הפקודה הבאה כדי ליצור את מאגר הצמתים:

      gcloud container node-pools create gpupool \
        --accelerator type=nvidia-l4,count=1,gpu-driver-version=latest \
        --project=${PROJECT_ID} \
        --location=${REGION} \
        --node-locations=${REGION}-a \
        --cluster=${CLUSTER_NAME} \
        --machine-type=g2-standard-8 \
        --num-nodes=1
    

    ‫GKE יוצר מאגר צמתים יחיד שמכיל GPU אחד מסוג L4 לכל צומת.

יצירת קטגוריה של Cloud Storage

יוצרים קטגוריה של Cloud Storage לאחסון המודל שעבר אימון מראש ויוצג.

ב-Cloud Shell, מריצים את הפקודה הבאה:

gcloud storage buckets create gs://$GSBUCKET --uniform-bucket-level-access

הגדרת גישה לדלי באשכול באמצעות איחוד זהויות של עומסי עבודה ל-GKE

כדי לאפשר ל-cluster גישה לקטגוריה של Cloud Storage, מבצעים את הפעולות הבאות:

  1. יוצרים Kubernetes ServiceAccount באשכול.
  2. מקצים תפקידים ב-IAM לחשבון השירות של Kubernetes.

יצירת חשבון שירות של Kubernetes באשכול

ב-Cloud Shell, מבצעים את הפעולות הבאות:

  1. יוצרים מרחב שמות של Kubernetes:

    kubectl create namespace gke-ai-namespace
    
  2. יוצרים חשבון שירות של Kubernetes במרחב השמות:

    kubectl create serviceaccount gpu-k8s-sa --namespace=gke-ai-namespace
    

הקצאת תפקידי IAM לחשבון שירות של Kubernetes

ב-Cloud Shell, מעניקים את התפקידים Storage Object Admin‏ (roles/storage.objectAdmin) ו-Storage Insights Collector Service‏ (roles/storage.insightsCollectorService) לחשבון השירות של Kubernetes:

gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/gke-ai-namespace/sa/gpu-k8s-sa" \
    --role=roles/storage.objectAdmin \
    --condition=None
gcloud projects add-iam-policy-binding PROJECT_ID \
    --member="principal://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/gke-ai-namespace/sa/gpu-k8s-sa" \
    --role=roles/storage.insightsCollectorService \
    --condition=None

מחליפים את מה שכתוב בשדות הבאים:

  • ‫PROJECT_ID: מזהה הפרויקט ב- Google Cloud .
  • ‫PROJECT_NUMBER: מספר הפרויקט ב- Google Cloud .

פריסת שרת ההיקשים אונליין

כל מסגרת הסקה אונליין מצפה למצוא את מודל ה-ML שעבר אימון מראש בפורמט ספציפי. בקטע הבא מוסבר איך פורסים את שרת ההסקה בהתאם למסגרת שבה רוצים להשתמש:

Triton

  1. ב-Cloud Shell, מעתיקים את המודל של למידת מכונה שעבר אימון מראש לקטגוריה של Cloud Storage:

    gcloud storage cp src/triton-model-repository gs://$GSBUCKET --recursive
    
  2. פורסים את המסגרת באמצעות פריסה. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה עותקים של Pods שמפוזרים בין הצמתים באשכול.

    envsubst < src/gke-config/deployment-triton.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    
  3. מוודאים ש-GKE פרס את המסגרת:

    kubectl get deployments --namespace=gke-ai-namespace
    

    כשהמסגרת מוכנה, הפלט אמור להיראות כך:

    NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
    triton-deployment    1/1     1            1           5m29s
    
  4. פורסים את השירותים כדי לגשת לפריסה:

    kubectl apply --namespace=gke-ai-namespace -f src/gke-config/service-triton.yaml
    
  5. בודקים שכתובת ה-IP החיצונית הוקצתה:

    kubectl get services --namespace=gke-ai-namespace
    

    הפלט אמור להיראות כך:

    NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                        AGE
    kubernetes      ClusterIP      34.118.224.1     <none>          443/TCP                                        60m
    triton-server   LoadBalancer   34.118.227.176   35.239.54.228   8000:30866/TCP,8001:31035/TCP,8002:30516/TCP   5m14s
    

    שימו לב לכתובת ה-IP של triton-server בעמודה EXTERNAL-IP.

  6. בודקים שהשירות והפריסה פועלים בצורה תקינה:

    curl -v EXTERNAL_IP:8000/v2/health/ready
    

    הפלט אמור להיראות כך:

    ...
    < HTTP/1.1 200 OK
    < Content-Length: 0
    < Content-Type: text/plain
    ...
    

TF Serving

  1. ב-Cloud Shell, מעתיקים את המודל של למידת מכונה שעבר אימון מראש לקטגוריה של Cloud Storage:

    gcloud storage cp src/tfserve-model-repository gs://$GSBUCKET --recursive
    
  2. פורסים את המסגרת באמצעות פריסה. פריסה היא אובייקט Kubernetes API שמאפשר להפעיל כמה עותקים של Pods שמפוזרים בין הצמתים באשכול.

    envsubst < src/gke-config/deployment-tfserve.yaml | kubectl --namespace=gke-ai-namespace apply -f -
    
  3. מוודאים ש-GKE פרס את המסגרת:

    kubectl get deployments --namespace=gke-ai-namespace
    

    כשהמסגרת מוכנה, הפלט אמור להיראות כך:

    NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
    tfserve-deployment   1/1     1            1           5m29s
    
  4. פורסים את השירותים כדי לגשת לפריסה:

    kubectl apply --namespace=gke-ai-namespace -f src/gke-config/service-tfserve.yaml
    
  5. בודקים שכתובת ה-IP החיצונית הוקצתה:

    kubectl get services --namespace=gke-ai-namespace
    

    הפלט אמור להיראות כך:

    NAME            TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                        AGE
    kubernetes      ClusterIP      34.118.224.1     <none>          443/TCP                                        60m
    tfserve-server  LoadBalancer   34.118.227.176   35.239.54.228   8500:30003/TCP,8000:32194/TCP                  5m14s
    

    שימו לב לכתובת ה-IP של tfserve-server בעמודה EXTERNAL-IP.

  6. בודקים שהשירות והפריסה פועלים בצורה תקינה:

    curl -v EXTERNAL_IP:8000/v1/models/mnist
    

    מחליפים את EXTERNAL_IP בכתובת ה-IP החיצונית.

    הפלט אמור להיראות כך:

    ...
    < HTTP/1.1 200 OK
    < Content-Type: application/json
    < Date: Thu, 12 Oct 2023 19:01:19 GMT
    < Content-Length: 154
    <
    {
      "model_version_status": [
            {
            "version": "1",
            "state": "AVAILABLE",
            "status": {
              "error_code": "OK",
              "error_message": ""
            }
          }
        ]
    }
    

פרסום המודל

Triton

  1. יוצרים סביבה וירטואלית של Python ב-Cloud Shell.

    python -m venv ./mnist_client
    source ./mnist_client/bin/activate
    
  2. מתקינים את חבילות Python הנדרשות.

    pip install -r src/client/triton-requirements.txt
    
  3. כדי לבדוק את שרת ההסקה של Triton, טוענים תמונה:

    cd src/client
    python triton_mnist_client.py -i EXTERNAL_IP -m mnist -p ./images/TEST_IMAGE.png
    

    מחליפים את מה שכתוב בשדות הבאים:

    • EXTERNAL_IP: כתובת ה-IP החיצונית שלכם.
    • ‫TEST_IMAGE: השם של הקובץ שתואם לתמונה שרוצים לבדוק. אפשר להשתמש בתמונות שמאוחסנות ב-src/client/images.

    בהתאם לתמונה שבה משתמשים, הפלט אמור להיראות כך:

    Calling Triton HTTP Service      ->      Prediction result: 7
    

TF Serving

  1. יוצרים סביבה וירטואלית של Python ב-Cloud Shell.

    python -m venv ./mnist_client
    source ./mnist_client/bin/activate
    
  2. מתקינים את חבילות Python הנדרשות.

    pip install -r src/client/tfserve-requirements.txt
    
  3. בודקים את TensorFlow Serving עם כמה תמונות.

    cd src/client
    python tfserve_mnist_client.py -i EXTERNAL_IP -m mnist -p ./images/TEST_IMAGE.png
    

מחליפים את מה שכתוב בשדות הבאים:

  • EXTERNAL_IP: כתובת ה-IP החיצונית שלכם.
  • ‫TEST_IMAGE: ערך מ-0 עד 9. אפשר להשתמש בתמונות שמאוחסנות ב-src/client/images.

בהתאם לתמונה שבה משתמשים, הפלט שמתקבל יהיה דומה לזה:

  Calling TensorFlow Serve HTTP Service    ->      Prediction result: 5

התבוננות בביצועי המודל

Triton

כדי לעקוב אחרי ביצועי המודל, אפשר להשתמש בשילוב של לוח הבקרה של Triton ב-Cloud Monitoring. לוח הבקרה הזה מאפשר לכם לראות מדדי ביצועים קריטיים כמו קצב העברת נתונים של טוקנים, זמן האחזור של הבקשות ושיעורי השגיאות.

כדי להשתמש בלוח הבקרה של Triton, צריך להפעיל את השירות המנוהל של Google Cloud ל-Prometheus, שאוסף את המדדים מ-Triton, באשכול GKE. כברירת מחדל, Triton חושף מדדים בפורמט Prometheus, כך שלא צריך להתקין כלי נוסף לייצוא נתונים.

לאחר מכן תוכלו לראות את המדדים באמצעות לוח הבקרה של Triton. מידע על שימוש בשירות מנוהל של Google Cloud ל-Prometheus כדי לאסוף מדדים מהמודל זמין בהנחיות בנושא יכולת צפייה ב-Triton במסמכי Cloud Monitoring.

TF Serving

כדי לבדוק את ביצועי המודל, אפשר להשתמש בשילוב של לוח הבקרה של TF Serving ב-Cloud Monitoring. לוח הבקרה הזה מאפשר לכם לראות מדדי ביצועים קריטיים כמו קצב העברת נתונים של טוקנים, זמן האחזור של הבקשות ושיעורי השגיאות.

כדי להשתמש בלוח הבקרה של TF Serving, צריך להפעיל את השירות המנוהל של Google Cloud ל-Prometheus באשכול GKE. השירות הזה אוסף את מדדי TF Serving.

אחר כך תוכלו לראות את המדדים באמצעות לוח הבקרה של TF Serving. מידע על שימוש בשירות מנוהל של Google Cloud ל-Prometheus כדי לאסוף מדדים מהמודל זמין בהנחיות בנושא יכולת צפייה (observability) ב-TF Serving במסמכי Cloud Monitoring.

הסרת המשאבים

כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שיצרתם במדריך הזה, אפשר לבצע אחת מהפעולות הבאות:

  • משאירים את אשכול GKE: מוחקים את משאבי Kubernetes באשכול ואת משאבי Google Cloud
  • שמירת הפרויקט Google Cloud : מחיקת אשכול GKE והמשאבים Google Cloud
  • מחיקת הפרויקט

מחיקת משאבי Kubernetes באשכול ו Google Cloud המשאבים

  1. מוחקים את מרחב השמות של Kubernetes ואת עומסי העבודה שפרסתם:

Triton

kubectl -n gke-ai-namespace delete -f src/gke-config/service-triton.yaml
kubectl -n gke-ai-namespace delete -f src/gke-config/deployment-triton.yaml
kubectl delete namespace gke-ai-namespace

TF Serving

kubectl -n gke-ai-namespace delete -f src/gke-config/service-tfserve.yaml
kubectl -n gke-ai-namespace delete -f src/gke-config/deployment-tfserve.yaml
kubectl delete namespace gke-ai-namespace
  1. מוחקים את הקטגוריה של Cloud Storage:

    1. נכנסים לדף Buckets:

      כניסה לדף Buckets

    2. מסמנים את התיבה PROJECT_ID-gke-bucket.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים DELETE ולוחצים על מחיקה.

מחיקת אשכול GKE ו Google Cloud המשאבים

  1. מוחקים את אשכול GKE:

    1. עוברים לדף Clusters:

      מעבר אל Clusters

    2. מסמנים את התיבה של online-serving-cluster.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים online-serving-cluster ולוחצים על מחיקה.

  2. מוחקים את הקטגוריה של Cloud Storage:

    1. נכנסים לדף Buckets:

      כניסה לדף Buckets

    2. מסמנים את התיבה PROJECT_ID-gke-bucket.

    3. לוחצים על מחיקה.

    4. כדי לאשר את המחיקה, מקלידים DELETE ולוחצים על מחיקה.

מחיקת הפרויקט

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

המאמרים הבאים