התאמה אישית של תעבורה ב-GKE Gateway באמצעות Service Extensions

בדף הזה מוסבר איך Google Kubernetes Engine‏ (GKE) משתמש בתוספי שירות כדי להוסיף לוגיקה מותאמת אישית ל-Cloud Load Balancing.

הדף הזה מיועד לאדמינים של זהויות וחשבונות ב-GKE ולמפתחים שצריכים להגדיר לוגיקה מותאמת אישית לניהול תנועה באמצעות תוספי שירות.

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

סקירה כללית

‫GKE משתמש ב-Service Extensions כדי להוסיף לוגיקה מותאמת אישית ל-Cloud Load Balancing. אפשר להשתמש בתוספי שירות למשימות כמו פיצול מתקדם של תנועה, אימות מותאם אישית או רישום ביומן של בקשות.

ה-GKE Gateway controller תומך בתוספי השירות הבאים:

  • GCPRoutingExtension: התוסף הזה מוסיף לוגיקה מותאמת אישית ל-Cloud Load Balancing כדי לשלוט בניתוב התנועה.
  • GCPTrafficExtension: התוסף הזה מוסיף לוגיקה מותאמת אישית ל-Cloud Load Balancing כדי לשנות את התנועה. הלוגיקה הזו חלה על התנועה אחרי שהשירות נבחר. מאזן העומסים יכול להוסיף או לשנות את הכותרות ואת המטענים הייעודיים (payloads) של בקשות ותגובות HTTP. ‫GCPTrafficExtension לא משפיע על בחירת השירות או על מדיניות אבטחת השירות.
  • GCPEdgeExtension: התוסף הזה מאפשר לכם להשפיע על בחירת שירות הקצה העורפי ומפתחות המטמון של Cloud CDN על ידי שינוי כותרות הבקשה. הוא נתמך באופן בלעדי במאזני עומסים גלובליים חיצוניים מנוהלים.

תוסף מצורף לשער. ב-Gateway של אשכול יחיד, ההרחבה מפנה למשאב Service, למשאב GCPWasmPlugin או למשאב googleAPIServiceName. ב-Gateway מרובה אשכולות, התוסף מפנה למשאב ServiceImport או למשאב googleAPIServiceName.

  • הפניה למשאב Service או למשאב ServiceImport: במודל הזה, אתם פורסים את הלוגיקה המותאמת אישית שלכם כאפליקציית קצה עורפי נפרדת, שמוצגת כשירות Kubernetes. מאזן העומסים מבצע קריאה לשירות הזה כדי לעבד את התנועה. הגישה הזו מגוונת ומאפשרת לכם להטמיע לוגיקה מותאמת אישית של ניתוב או לבצע מניפולציות בתנועה, כמו שינוי כותרות או בדיקת מטען ייעודי.

  • הפניה למשאב GCPWasmPlugin: לתרחישי שימוש עם ביצועים גבוהים, אפשר להחדיר לוגיקה מותאמת אישית שנכתבה על ידי המשתמש ישירות לנתיב הנתונים של מאזן העומסיםCloud de Confiance by S3NS באמצעות מודול WebAssembly‏ (Wasm). מגדירים GCPWasmPluginמשאב שמפנה לתמונה של מודול Wasm ב-Artifact Registry. השיטה הזו משמשת רק עם משאבי GCPTrafficExtension ו-GCPEdgeExtension ועם מאזן עומסים גלובלי חיצוני של אפליקציות

  • הפניה לשירות Google API: אפשר גם להפנות ישירות לשירות Google API באמצעות השדה googleAPIServiceName בתוך GCPTrafficExtension.

בתרשים הבא, המשאב GCPRoutingExtension מצורף ל-Gateway ומפנה לכמה שירותים. התוסף שולט בהפניית התנועה לשירותים.

המשאב `GCPRoutingExtension` מצורף לשער ומפנה לשירות. התוסף שולט בניווט התעבורה.
איור: איך התוסף GCPRoutingExtension פועל עם שערים

בתרשים הבא, המשאב GCPTrafficExtension מצורף ל-Gateway ומפנה לשירות, ל-GoogleAPIServiceName או ל-GCPWasmPlugin. התוסף משנה את הכותרות ואת נתוני הבקשות והתגובות.

המשאב `GCPTrafficExtension` מצורף לשער ומפנה לשירות, ל-`GoogleAPIServiceName` או ל-`GCPWasmPlugin`. התוסף משנה את הכותרות ואת נתוני הבקשות והתגובות.
איור: איך GCPTrafficExtension פועל עם שערים

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

לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:

  • מפעילים את ממשק Google Kubernetes Engine API.
  • הפעלת Google Kubernetes Engine API
  • כדי להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את gcloud CLI. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
  • אם צריך, מפעילים את Compute Engine API, את Network Services API ואת Model Armor API.

    עוברים אל הפעלת גישה לממשקי API ופועלים לפי ההוראות.

  • מידע מפורט על התמחור של Cloud de Confiance הרחבות שירות זמין במאמר בנושא תמחור.

  • בודקים את התפקידים וההרשאות הנדרשים במאמר בקרת גישה לתוספי שירות.

  • כדאי לעיין במכסות ובמגבלות שמופיעות במאמר מכסות של תוספי שירות.

  • אם אתם מתכוונים להשתמש ב-matchers של Common Expression Language ‏ (CEL), כדאי לעיין במאפיינים ובאופרטורים הנתמכים בהפניה לשפת ה-matcher של CEL.

  • מומלץ לעיין בהגבלות על הרחבות שירות.

דרישות של GKE Gateway Controller

  • האשכול צריך להיות בגרסה 1.33 של GKE ומעלה.
  • כדי להשתמש ב-GCPWasmPlugin, באשכול צריך להיות מותקנת גרסה 1.33.3 של GKE ומעלה.
  • כדי להשתמש במשאב ServiceImport, האשכול צריך להיות בגרסה 1.34.3 ואילך של GKE.
  • צריך להגדיר משאב Gateway בשביל שער פנימי מרובה אשכולות. המשאב יכול להיות מאזן עומסים גלובלי חיצוני של אפליקציות (ALB), מאזן עומסים פנימי של אפליקציות (ALB) בין אזורים, מאזן עומסים חיצוני אזורי של אפליקציות (ALB) או שער אזורי של מאזן עומסים פנימי של אפליקציות (ALB).
  • צריך להפעיל את Gateway API באשכול.
  • צריך שיהיה לכם משאב מסוג Gateway מוגדר. המשאב הזה יכול להיות מאזן עומסים גלובלי חיצוני של אפליקציות (ALB), מאזן עומסים חיצוני אזורי של אפליקציות (ALB) או שער מאזן עומסים פנימי אזורי של אפליקציות (ALB). אם משתמשים במשאב GCPWasmPlugin, צריך לפרוס רק שער של מאזן עומסים חיצוני גלובלי של אפליקציות.
  • צריך להגדיר משאב HTTPRoute.

הגבלות ומגבלות

בטבלה הבאה מפורטות ההגבלות שקשורות להגדרת תוספים של שירותי שער ב-GKE:

קטגוריה הגבלות ומגבלות
מאזן עומסים המאפיין GCPRoutingExtension נתמך במאזני העומסים הבאים:
  • מאזן עומסים חיצוני אזורי של אפליקציות (ALB) (gke-l7-regional-external-managed Gateway Class)
  • מאזן עומסים חיצוני אזורי של אפליקציות (ALB) (gke-l7-regional-external-managed-mc Gateway Class)
  • מאזן עומסים פנימי אזורי של אפליקציות (gke-l7-rilb Gateway Class)
  • מאזן עומסים פנימי אזורי של אפליקציות (gke-l7-rilb-mc Gateway Class)
  • מאזן עומסים פנימי של אפליקציות (ALB) בין אזורים (gke-l7-cross-regional-internal-managed-mc Gateway Class)
המאפיין GCPTrafficExtension נתמך במאזני העומסים הבאים:
  • מאזן עומסים חיצוני אזורי של אפליקציות (ALB) (gke-l7-regional-external-managed Gateway Class)
  • מאזן עומסים חיצוני אזורי של אפליקציות (ALB) (gke-l7-regional-external-managed-mc Gateway Class)
  • מאזן עומסים פנימי אזורי של אפליקציות (gke-l7-rilb Gateway Class)
  • מאזן עומסים פנימי אזורי של אפליקציות (gke-l7-rilb-mc Gateway Class)
  • מאזן עומסים גלובלי חיצוני של אפליקציות (ALB) (gke-l7-global-external-managed Gateway Class)
  • מאזן עומסים גלובלי חיצוני של אפליקציות (ALB) (gke-l7-global-external-managed-mc Gateway Class)
  • מאזן עומסים פנימי של אפליקציות (ALB) בין אזורים (gke-l7-cross-regional-internal-managed-mc Gateway Class)
GCPEdgeExtension נתמך באופן בלעדי במאזן עומסים גלובלי חיצוני מנוהל (gke-l7-global-external-managed Gateway Class).
שרשרת תוספים ומפרט
  • בGCPTrafficExtension, לכל ExtensionChain יכולים להיות עד 3 Extensions.
  • גם ל-GCPRoutingExtension וגם ל-GCPEdgeExtension, כל ExtensionChain מוגבל ל-Extension אחד.
  • לכל סוגי התוספים (תנועה, ניתוב ו-Edge) יכולים להיות עד 5 ExtensionChains לכל משאב.
פסק זמן
  • ערך הזמן הקצוב לתפוגה של כל הודעה בנפרד בסטרימינג בתוך תוסף צריך להיות בין 10 ל-10,000 אלפיות השנייה. ברירת המחדל של הזמן הקצוב לתפוגה היא שנייה אחת.
MatchCondition
  • כל MatchCondition בתוך ExtensionChain מוגבל ל-10 CELExpressions לכל היותר.
  • מחרוזת התווים MatchCondition שנוצרת ונשלחת ל-GCE מוגבלת ל-512 תווים.
  • המחרוזת CELMatcher בתוך CELExpression יכולה להיות באורך של עד 512 תווים.
  • ב-GCPEdgeExtension:
    • אין תמיכה במאפייני תגובה (לדוגמה, response.code) ב-CELMatcher.
    • מאפייני בקשה שלא נתמכים כוללים את backend_service_name ו-backend_service_project_number.
    • מספר הביטויים הרגולריים מוגבל ל-1.
  • רק שדה backendRefs מסוג Service או ServiceImport נתמך ב-CELExpression.
  • אין תמיכה בשדה backendRefs עם gke-l7-global-external-managed ו-gke-l7-global-external-managed-mc Gateway Classes
Header
  • ForwardHeaders הרשימה בExtension יכולה להכיל עד 50 שמות של כותרות HTTP.
מטא-נתונים
  • במפה Metadata ב-Extension יכולים להיות עד 16 נכסים.
  • המפתחות במפה Metadata צריכים להיות באורך של 1 עד 63 תווים.
  • הערכים במיפוי Metadata צריכים להיות באורך של 1 עד 1,023 תווים.
אירוע
  • נדרשת הרשאה ל-SupportedEvents כדי להשתמש ב-GCPTrafficExtension.
  • המאפיין SupportedEvents הוא אופציונלי עבור GCPRoutingExtension.
  • עבור GCPEdgeExtension, הרשימה SupportedEvents חייבת להכיל רק RequestHeaders.
  • אם לא מציינים, ההנחה היא שאירוע RequestHeaders נתמך.
RequestBodySendMode
  • אפשר להשתמש ב-RequestBodySendMode רק עם backendRefs מסוג Service או ServiceImport.
  • אפשר להגדיר את RequestBodySendMode רק אם SupportedEvents כולל את RequestBody.
  • אם SupportedEvents include RequestBody, אבל RequestBodySendMode לא מוגדר, המערכת תשתמש בערך ברירת המחדל Streamed.
  • אם הערך של RequestBodySendMode הוא FullDuplexStreamed, הערך של SupportedEvents חייב לכלול גם את RequestBody וגם את RequestTrailers.
  • במקרה של GCPTrafficExtension, יש תמיכה רק ב-FullDuplexStreamed.
ResponseBodySendMode
  • השדה ResponseBodySendMode נתמך רק ב-GCPTrafficExtension.
  • אפשר להשתמש ב-ResponseBodySendMode רק עם backendRefs מסוג Service או ServiceImport.
  • אפשר להגדיר את השדה רק אם בשדה SupportedEvents מופיע הערך ResponseBody.
  • אם SupportedEvents include ResponseBody, אבל ResponseBodySendMode לא מוגדר, המערכת תשתמש בערך ברירת המחדל Streamed.
  • כשהערך של השדה הזה הוא FullDuplexStreamed, השדה SupportedEvents חייב לכלול את הערכים ResponseBody ו-ResponseTrailers.
הפניות למשאבים
  • בשביל GCPEdgeExtension, סוג ה-backend הנתמך היחיד הוא GCPWasmPlugin.
  • אין תמיכה בשדה googleAPIServiceName ב-GCPEdgeExtension.
  • השער, תוסף Edge והפלאגין חייבים להיות באותו מרחב שמות.
GCPWasmPlugin
  • השדה GCPWasmPlugin נתמך רק ב-GCPTrafficExtension וב-GCPEdgeExtension.
  • תוספים עם GCPWasmPlugin לא תומכים בשדות הבאים:
    • authority
    • timeout
    • metadata
    • requestBodySendMode
    • responseBodySendMode
  • תוספים עם תמיכה ב-GCPWasmPlugin תומכים רק באירועים RequestHeaders,‏ RequestBody,‏ ResponseHeaders ו-ResponseBody.
googleAPIServiceName
  • השדה googleAPIServiceName נתמך רק ב-GCPTrafficExtension.
  • אם googleAPIServiceName מוגדר, אסור להגדיר את authority.
  • אפשר להגדיר רק אחד מהמאפיינים backendRef או googleAPIServiceName עבור Extension.
backendRef כשמפנים לשירות שמשתמש ב-backendRef בתוסף, צריך לעמוד בתנאים הבאים:
  • חובה להשתמש ב-HTTP2 כappProtocol.
  • השם חייב להיות באותו מרחב שמות כמו התוסף והשער שאליו התוסף מפנה.
  • אי אפשר להשתמש בIAP.
  • אי אפשר להשתמש במדיניות האבטחה של Google Cloud Armor.
  • אי אפשר להשתמש ב-Cloud CDN.
  • צריך להגדיר בדיוק אחד מהמאפיינים backendRef או googleAPIServiceName עבור Extension.
  • אם מגדירים את backendRef והערך של kind הוא Service, חובה להגדיר את authority.
observabilityMode אפשר להגדיר את השדה observabilityMode ב-Extension עם המגבלות הבאות:
  • התכונה נתמכת באשכולות GKE בגרסה ‎1.35.0-gke.3047000 ואילך.
  • נתמך על ידי משאבי GCPTrafficExtension ו-GCPRoutingExtension שמצורפים לשערי API עם מחלקות אזוריות של שערים.
  • האפשרות Enabled observabilityMode נתמכת רק אם השדות requestBodySendMode ו-responseBodySendMode לא מוגדרים או מוגדרים לערך Streamed.

הפניה לשירות

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

כדי להגדיר תוספי שירות של GKE, מבצעים את השלבים הבאים:

  1. פריסת שירות לקריאה חוזרת (callback) לקצה העורפי: יוצרים שירות Kubernetes שמייצג את השירות לקצה העורפי להרצת לוגיקה מותאמת אישית. מאזן העומסים מפעיל את השירות הזה.

  2. הגדרת תוספים לשירותים: צריך להשתמש בתוסף המתאים בהתאם לסוג מאזן העומסים.

    1. GCPRoutingExtension עבור שערים אזוריים: משתמשים בתוסף הזה עבור מאזן עומסים חיצוני אזורי של אפליקציות (ALB) ומאזן עומסים פנימי אזורי של אפליקציות (ALB) כדי להטמיע לוגיקה מותאמת אישית של ניתוב בתוך האזור.

    2. GCPTrafficExtension למאזני עומסים גלובליים חיצוניים, אזוריים חיצוניים ופנימיים: אפשר להשתמש בתוסף הזה למאזן עומסים גלובלי חיצוני של אפליקציות (ALB), למאזן עומסים חיצוני אזורי של אפליקציות (ALB) ולמאזן עומסים פנימי אזורי של אפליקציות (ALB) כדי לבצע מניפולציות בתעבורה, כמו שינוי כותרות או בדיקת מטען ייעודי (payload), בסוגים שונים של מאזני עומסים.

פריסת שירות לקצה העורפי של יתרונות מרכזיים

שירות Callout מטמיע לוגיקה מותאמת אישית לתוספי שירות של Gateway ב-GKE. השער מפעיל את אפליקציות ה-Backend האלה, על סמך ההגדרות של GCPTrafficExtension או GCPRoutingExtension, כדי לשנות את התנועה או לנתב אותה.

אתם פורסים שירות קריאה ל-API כדי להוסיף לוגיקה בהתאמה אישית לשער. השירות הנפרד הזה מטפל בעיבוד מותאם אישית, כמו שינוי כותרות, המרות של נתוני payload או ניתוב תנועה.

כדי לפרוס שירות שיכול לשמש כהפניה ל-Gateway, מבצעים את השלבים הבאים:

  1. (אופציונלי) יצירת סוד ל-TLS: הפקודה הזו יוצרת סוד Kubernetes מסוג TLS שמכיל את אישור ה-TLS והמפתח הפרטי שלכם.

    כדי ליצור את סוד ה-TLS לשירות שלכם לביצוע שיחות חיצוניות, מחליפים את הערכים הבאים:

    • SECRET_NAME: שם הסוד של שירות ההתקשרות
    • path-to-cert: הנתיבים לקובץ האישור
    • path-to-key: הנתיבים לקובץ המפתח
  2. כדי לוודא שהסוד נוסף, מריצים את הפקודה הבאה:

    kubectl get secrets SECRET_NAME
    

    מחליפים את SECRET_NAME בשם הסוד של שירות ההתקשרות.

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

    NAME            TYPE                DATA   AGE
    SECRET_NAME     kubernetes.io/tls   2      12s
    
  3. הגדרת משאבי פריסה ושירות.

    צריך להגדיר את הפרטים הבאים:

    • פריסה: כדי לנהל את קבוצות ה-Pod של האפליקציה שמכילות את הלוגיקה המותאמת אישית של תוספי השירות.
    • Service: כדי לחשוף את קבוצות ה-Pod של האפליקציה שמנוהלות על ידי ה-Deployment כשירות רשת.
    1. יוצרים קובץ מניפסט לדוגמה extension-service-app.yaml עם הגדרות של Deployment ו-Service:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: extension-service-app
      spec:
        selector:
          matchLabels:
            app: store
        replicas: 1
        template:
          metadata:
            labels:
              app: store
          spec:
            containers:
            - name: serviceextensions
              image: us-docker.pkg.dev/service-extensions-samples/callouts/python-example-basic:public-image-e42d951
              ports:
              - containerPort: 8080
              - containerPort: 443
              volumeMounts:
              - name: certs
                mountPath: "/etc/certs/"
                readOnly: true
              env:
              - name: POD_NAME
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.name
              - name: NAMESPACE
                valueFrom:
                  fieldRef:
                    fieldPath: metadata.namespace
              - name: TLS_SERVER_CERT_PATH
                value: "/etc/certs/path-to-cert"
              - name: TLS_SERVER_PRIVKEY
                value: "/etc/certs/path-to-key"
              resources:
                requests:
                  cpu: 10m
            volumes:
            - name: certs
              secret:
                secretName: SECRET_NAME
                optional: false
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: extension-service
      spec:
        ports:
        - port: 443
          targetPort: 443
          appProtocol: HTTP2
        selector:
          app: store
      

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

      • POD_NAME: השם של ה-Pod.
      • SECRET_NAME: השם הסודי של שירות ההתקשרות.
      • TLS_SERVER_CERT_PATH: הנתיב לאישור השרת TLS בתוך ה-Pod.
      • TLS_SERVER_PRIVKEY: הנתיב למפתח הפרטי של שרת TLS בתוך ה-Pod.
    2. החלת המניפסט extension-service-app.yaml:

      kubectl apply -f extension-service-app.yaml
      
  4. אימות ההגדרה:

    1. מוודאים שהאפליקציה נפרסה:

      kubectl get pod --selector app=store
      

      אחרי שהאפליקציה מתחילה לפעול, הפלט אמור להיראות כך:

      NAME                                     READY   STATUS    RESTARTS   AGE
      extension-service-app-85f466bc9b-b5mf4   1/1     Running   0          7s
      
    2. מוודאים שהשירות נפרס:

      kubectl get service extension-service
      

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

      NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
      extension-service   ClusterIP   34.118.225.9   <none>        443/TCP   2m40s
      

הגדרת Service Extensions

אתם יכולים להגדיר GCPRoutingExtension או GCPTrafficExtension כדי להתאים אישית את זרימת התנועה.

הגדרת GCPRoutingExtension לשערים אזוריים

אפשר לנתב מחדש את התנועה באמצעות GCPRoutingExtension. כדי להגדיר GCPRoutingExtension, מעדכנים את HTTPRoute כדי לציין את הבקשות למארח service-extensions.com.

  1. מעדכנים את HTTPRoute. משנים את HTTPRoute כך שיכלול שמות מארחים או נתיבים שיפעילו את תוסף הניתוב.

    1. שומרים את קובץ המניפסט לדוגמה הבא כקובץ store-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name:GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
        - matches:
          - headers:
            - name: env
              value: canary
          backendRefs:
          - name: store-v2
            port: 8080
        - matches:
          - path:
              value: /de
          backendRefs:
          - name: store-german
            port: 8080
      

      מחליפים את GATEWAY_NAME בשם השער.

    2. החלת המניפסט store-route.yaml:

      kubectl apply -f store-route.yaml
      
  2. מגדירים את GCPRoutingExtension.

    1. שומרים את ההגדרה של GCPRoutingExtension בקובץ gcp-routing-extension.yaml לדוגמה:

      kind: GCPRoutingExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: my-gateway-extension
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            authority: "myext.com"
            timeout: 1s
            backendRef:
              group: ""
              kind: Service
              name: extension-service
              port: 443
      

      מחליפים את GATEWAY_NAME בשם השער.

    2. מחילים את קובץ המניפסט לדוגמה על האשכול:

      kubectl apply -f gcp-routing-extension.yaml
      
  3. מאמתים את ההגדרה של GCPRoutingExtension ואת הקישור שלה ל-Gateway.

    1. בדיקת הפריסה של GCPRoutingExtension:

      kubectl describe gcproutingextension my-gateway-extension
      

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

      Name:         my-gateway-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPRoutingExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      בפלט מוצגים הפרטים של GCPRoutingExtension, שנקרא my-gateway-extension, במרחב השמות שמוגדר כברירת מחדל. בפלט מוצג השדה Spec, שמכיל את ההגדרה של אופן הפעולה של התוסף.

    2. מאמתים את הקישור של שער התשלומים:

      1. מוודאים ש-GCPRoutingExtension משויך לשער. הפעולה הזו עשויה להימשך כמה דקות:

        kubectl describe gateway GATEWAY_NAME
        

        מחליפים את GATEWAY_NAME בשם השער.

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

        Name:         GATEWAY_NAME
        Namespace:    default
        Labels:       none
        Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                      networking.gke.io/backend-services:
                        /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                      networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                      networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                      networking.gke.io/health-checks:
                        /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                      networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                      networking.gke.io/lb-route-extensions:
                        /projects/1234567890/locations/us-central1/lbRouteExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                      networking.gke.io/lb-traffic-extensions:
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                        /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                      networking.gke.io/target-https-proxies:
                      networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
        API Version:  gateway.networking.k8s.io/v1
        Kind:         Gateway
        Metadata:
          Creation Timestamp:  2025-03-02T16:37:50Z
          Finalizers:
          gateway.finalizer.networking.gke.io
          Generation:        1
          Resource Version:  31284863
          UID:               fd512611-bad2-438e-abfd-5619474fbf31
        ...
        

        בפלט מוצגות ההערות, ש-GKE משתמש בהן כדי לאחסן את הקישורים בין ה-Gateway לביןCloud de Confiance המשאבים הבסיסיים. ההערה networking.gke.io/lb-route-extensions מאשרת את הקישור של שער התשלומים ל-GCPRoutingExtension.

      2. כדי לבדוק את סטטוס התוסף, מוודאים של-GCPRoutingExtension יש סטטוס Programmed עם הסיבה ProgrammingSucceeded. הפקודה הזו עשויה להימשך כמה דקות.

        kubectl describe gcproutingextension my-gateway-extension
        

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

        Name:         my-gateway-extension
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  networking.gke.io/v1
        Kind:         GCPRoutingExtension
        Metadata:
          Creation Timestamp:  2025-03-02T17:12:30Z
          Generation:          1
          Resource Version:    31284378
          UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
        Spec:
          Extension Chains:
            Extensions:
              Authority:  myext.com
              Backend Ref:
                Group:
                Kind:   Service
                Name:   extension-service
                Port:   443
              Name:     ext1
              Timeout:  1s
            Match Condition:
              Cel Expressions:
                Cel Matcher:  request.path.contains("serviceextensions")
            Name:             chain1
          Target Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   GATEWAY_NAME
        Status:
          Ancestors:
            Ancestor Ref:
              Group:      gateway.networking.k8s.io
              Kind:       Gateway
              Name:       GATEWAY_NAME
              Namespace:  default
            Conditions:
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                Accepted
              Status:                True
              Type:                  Accepted
              Last Transition Time:  2025-03-02T17:14:15Z
              Message:
              Reason:                ProgrammingSucceeded
              Status:                True
              Type:                  Programmed
            Controller Name:         networking.gke.io/gateway
        Events:
          Type    Reason  Age                From                   Message
          ----    ------  ----               ----                   -------
          Normal  ADD     2m31s              sc-gateway-controller  default/my-gateway-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        GATEWAY_NAME,
        SectionName: nil,
        Port:        nil} was a success
          Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPRoutingExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        GATEWAY_NAME,
        SectionName: nil,
        Port:        nil} was a success
        

        בשדה Status.Conditions מוצג תנאי Programmed עם Status: True ו-Reason: ProgrammingSucceeded. המידע הזה מאשר שהתוסף הוחל בהצלחה.

  4. שליחת תנועה לאפליקציה.

    אחרי שפורסים את ה-Gateway, את המסלול ואת האפליקציה באשכול, אפשר להעביר תנועה לאפליקציה.

    1. כדי לגשת לאפליקציה, צריך למצוא את כתובת ה-IP של השער.

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

      kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
      

      מחליפים את GATEWAY_NAME בשם השער.

      הפקודה הזו מחזירה את כתובת ה-IP של השער. בפקודות הבאות, מחליפים את GATEWAY_IP_ADDRESS בכתובת ה-IP מהפלט.

    2. כדי לבדוק את עדכון הנתיב, עוברים לגרסה serviceextensions של שירות החנות בכתובת store.example.com/serviceextensions:

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

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

      {
      "cluster_name": "gke1",
      "host_header": "service-extensions.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-5d9554f847-cvxpd",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo",
      "timestamp": "2025-03-15T12:00:00",
      "zone": "us-central1-c"
      }
      

הגדרת GCPTrafficExtension

אתם יכולים להשתמש ב-GCPTrafficExtension כדי להשתמש ביכולות מתקדמות של ניהול תנועת גולשים בסביבה שלכם ב- Cloud de Confiance . אפשר להגדיר את התוסף הזה במאזני עומסים גלובליים חיצוניים של אפליקציות (ALB), במאזני עומסים אזוריים חיצוניים של אפליקציות (ALB) ובמאזני עומסים אזוריים פנימיים של אפליקציות (ALB). אפשר להשתמש ב-GCPTrafficExtension כדי להטמיע לוגיקה מותאמת אישית של בקשות ותשובות HTTP, ניתוב מתוחכם, טרנספורמציות ומדיניות אבטחה.

  1. מעדכנים את HTTPRoute. משנים את HTTPRoute כך שיכלול שמות מארחים או נתיבים שיפעילו את תוסף התנועה.

    1. שומרים את קובץ המניפסט לדוגמה הבא כקובץ store-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store
      spec:
        parentRefs:
        - kind: Gateway
          name: GATEWAY_NAME
        hostnames:
        - "store.example.com"
        - "service-extensions.example.com"
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
        - matches:
          - headers:
            - name: env
              value: canary
          backendRefs:
          - name: store-v2
            port: 8080
        - matches:
          - path:
              value: /de
          backendRefs:
          - name: store-german
            port: 8080
      

      מחליפים את GATEWAY_NAME בשם השער, כמו internal-http, external-http או global-external-http.

    2. מחילים את המניפסט store-route.yaml על האשכול:

      kubectl apply -f store-route.yaml
      
  2. מגדירים את GCPTrafficExtension.

    1. שומרים את ההגדרה של GCPTrafficExtension בקובץ לדוגמה gcp-traffic-extension.yaml:

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
      name: my-traffic-extension
      namespace: default
      spec:
      targetRefs:
      - group: "gateway.networking.k8s.io"
        kind: Gateway
        name: GATEWAY_NAME
      extensionChains:
      - name: chain1
        matchCondition:
          celExpressions:
          - celMatcher: request.path.contains("serviceextensions")
        extensions:
        - name: ext1
          authority: "myext.com"
          timeout: 1s
          backendRef:
            group: ""
            kind: Service
            name: extension-service
            port: 443
          supportedEvents:
            - RequestHeaders
            - RequestBody
            - ResponseHeaders
            - ResponseBody
      

      מחליפים את GATEWAY_NAME בשם השער, כמו internal-http, external-http או global-external-http.

    2. מחילים את קובץ המניפסט לדוגמה על האשכול:

      kubectl apply -f gcp-traffic-extension.yaml
      
  3. מאמתים את ההגדרה של GCPTrafficExtension ואת הקישור שלה ל-Gateway.

    1. בדיקת הפריסה של GCPTrafficExtension:

      kubectl describe gcptrafficextension my-traffic-extension
      

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

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:    myext.com
            Backend Ref:
              Group:
              Kind: Service
              Name: extension-service
              Port: 443
            Name:       ext1
            Timeout:    1s
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      בפלט מוצגים הפרטים של GCPTrafficExtension בשם my-traffic-extension במרחב השמות שמוגדר כברירת מחדל. הוא מציג את השדה Spec, שמכיל את ההגדרה של אופן הפעולה של התוסף.

    2. מאמתים את הקישור של שער התשלומים:

      מוודאים ש-GCPTrafficExtension משויך לשער. יכול להיות שיחלפו כמה דקות עד שהפקודה הזו תסתיים:

      kubectl describe gateway GATEWAY_NAME
      

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

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/1234567890/regions/us-central1/addresses/test-hgbk-default-internal-http-5ypwen3x2gcr
                    networking.gke.io/backend-services:
                      /projects/1234567890/regions/us-central1/backendServices/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/re...
                    networking.gke.io/firewalls: /projects/1234567890/global/firewalls/test-hgbk-l7-default-us-central1
                    networking.gke.io/forwarding-rules: /projects/1234567890/regions/us-central1/forwardingRules/test-hgbk-default-internal-http-qn7dk9i9zm73
                    networking.gke.io/health-checks:
                      /projects/1234567890/regions/us-central1/healthChecks/test-hgbk-default-extension-service-443-rduk21fwhoj0, /projects/1234567890/regio...
                    networking.gke.io/last-reconcile-time: 2025-03-02T17:15:02Z
                    networking.gke.io/lb-traffic-extensions:
                      /projects/1234567890/locations/us-central1/lbTrafficExtensions/test-hgbk-default-internal-http-lwh0op4qorb0
                    networking.gke.io/ssl-certificates:
                    networking.gke.io/target-http-proxies:
                      /projects/1234567890/regions/us-central1/targetHttpProxies/test-hgbk-default-internal-http-2jzr7e3xclhj
                    networking.gke.io/target-https-proxies:
                    networking.gke.io/url-maps: /projects/1234567890/regions/us-central1/urlMaps/test-hgbk-default-internal-http-2jzr7e3xclhj
      API Version:  gateway.networking.k8s.io/v1
      Kind:         Gateway
      Metadata:
        Creation Timestamp:  2025-03-02T16:37:50Z
        Finalizers:
          gateway.finalizer.networking.gke.io
        Generation:        1
        Resource Version:  31284863
        UID:               fd512611-bad2-438e-abfd-5619474fbf31
      ...
      

      בפלט מוצגות ההערות, ש-GKE משתמש בהן כדי לאחסן את הקישורים בין ה-Gateway לבין המשאבים הבסיסיים של Cloud de Confiance . ההערה networking.gke.io/lb-traffic-extensions מאשרת את הקישור.

    3. בודקים את הסטטוס של התוסף:

      כדי לבדוק את סטטוס התוסף של GCPTrafficExtension, מריצים את הפקודה הבאה:

      kubectl describe gcptrafficextension my-traffic-extension
      

      מוודאים שהסטטוס של GCPTrafficExtension הוא Programmed עם הסיבה ProgrammingSucceeded. יכול להיות שיחלפו כמה דקות עד שהפקודה תסתיים.

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

      Name:         my-traffic-extension
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:          1
        Resource Version:    31284378
        UID:                 ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Authority:  myext.com
            Backend Ref:
              Group:
              Kind:   Service
              Name:   extension-service
              Port:   443
            Name:     ext1
            Timeout:  1s
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   GATEWAY_NAME
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       GATEWAY_NAME
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-03-02T17:14:15Z
            Message:
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                From                   Message
        ----    ------  ----               ----                   -------
        Normal  ADD     2m31s              sc-gateway-controller  default/my-traffic-extension
        Normal  SYNC    51s (x2 over 98s)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/my-gateway-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        GATEWAY_NAME,
        SectionName: nil,
        Port:        nil} was a success
        Normal  SYNC    23s           sc-gateway-controller  Reconciliation of GCPTrafficExtension "default/my-traffic-extension" to AncestorRef {Group:       "gateway.networking.k8s.io",
        Kind:        "Gateway",
        Namespace:   "default",
        Name:        GATEWAY_NAME,
        SectionName: nil,
        Port:        nil} was a success
      

      בשדה Status.Conditions מוצג תנאי Programmed עם Status: True ו-Reason: ProgrammingSucceeded. המידע הזה מאשר שהתוסף הופעל בהצלחה.

  4. שליחת תנועה לאפליקציה.

    אחרי שפורסים את ה-Gateway, את המסלול ואת האפליקציה באשכול, אפשר להעביר תנועה לאפליקציה.

    1. כדי לגשת לאפליקציה, צריך למצוא את כתובת ה-IP של השער.

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

      kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
      

      מחליפים את GATEWAY_NAME בשם השער.

      הפקודה הזו מחזירה את כתובת ה-IP של השער. בפקודות הבאות, מחליפים את GATEWAY_IP_ADDRESS בכתובת ה-IP מהפלט.

    2. כדי לבדוק את עדכון הנתיב, עוברים לגרסה serviceextensions של שירות החנות בכתובת store.example.com/serviceextensions:

      curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
      

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

      {
      *   Request completely sent off
      < HTTP/1.1 200 OK
      < server: Werkzeug/2.3.7 Python/3.11.3
      < date: Sun, 02 Mar 2025 16:58:10 GMT
      < content-type: application/json
      < access-control-allow-origin: *
      < hello: service-extensions
      < via: 1.1 google
      < transfer-encoding: chunked
      }
      

הפניה למשאב GCPWasmPlugin

אפשר להוסיף לוגיקה בהתאמה אישית ישירות לנתיב הנתונים של מאזן העומסים באמצעות GCPWasmPlugin עם GCPTrafficExtension או GCPEdgeExtension. השיטה הזו מאפשרת לפרוס יכולות מותאמות אישית לניהול תנועה, שמאוגדות כמודול Wasm.

כדי להגדיר תוספי שירות של GKE, מבצעים את השלבים הבאים:

  1. פריסת GCPWasmPlugin: יוצרים ופורסים GCPWasmPlugin CustomResourceDefinition ‏ (CRD) שמכיל את הקוד המותאם אישית של מודול Wasm. אפשר להשתמש ב-GCPWasmPlugin עם GCPTrafficExtension או GCPEdgeExtension עבור gke-l7-global-external-managed GatewayClass.

  2. הגדרת תוספים לשירות: מגדירים אחד מהתוספים הבאים באמצעות GCPWasmPlugin:

פריסה של GCPWasmPlugin

התכונה GCPWasmPlugin מאפשרת להוסיף לוגיקה מותאמת אישית שנכתבה על ידי המשתמש ישירות לנתיב הנתונים של מאזן העומסים Cloud de Confiance . המקור GCPWasmPlugin מצביע על תמונת מודול ה-Wasm ב-Artifact Registry, שמופעלת על ידי מאזן העומסים.

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

כדי לפרוס משאב GCPWasmPlugin, מבצעים את השלבים הבאים:

  1. שומרים את קובץ המניפסט הבא בשם wasm-plugin.yaml:

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version
        description: "Test wasm plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      logConfig:
        enabled: true
        # Configures the sampling rate of activity logs.
        # The value of the field must be in range [0, 1e6].
        sampleRate: 1000000
        # Specifies the lowest level of logs that are exported to Cloud Logging.
        minLogLevel: INFO
    

    שימו לב לנקודות הבאות:

    • spec.versions.name: שם הגרסה צריך להיות ייחודי במשאב GCPWasmPlugin. אפשר לציין עד 10 גרסאות, ורק לגרסה אחת צריך להיות משקל שונה מאפס.
    • spec.versions.image: מפנה לתמונה שמכילה את קוד הפלאגין שמאוחסן ב-Artifact Registry.
    • spec.versions.weight: מציין את המשקל של גרסת הפלאגין. המשקל חייב להיות מספר בין 0 ל-1,000,000, כולל.
    • spec.logConfig: מציין אם להפעיל את Cloud Logging עבור הפלאגין הזה. אם לא מציינים את הערך, Cloud Logging מושבת כברירת מחדל.
    • spec.logConfig.sampleRate: הגדרת קצב הדגימה של יומני הפעילות. השיעור חייב להיות מספר בין 0 ל-1,000,000, כולל. אם לא מציינים ערך כשמפעילים את Cloud Logging, ערך ברירת המחדל הוא 1,000,000 (100% מהבקשות נרשמות ביומן).
    • spec.logConfig.minLogLevel: מציין את הרמה הנמוכה ביותר של יומנים שמיוצאים ל-Cloud Logging. אם לא מציינים את הערך כש-Cloud Logging מופעל, השדה מוגדר ל-INFO כברירת מחדל.
  2. החלת המניפסט wasm-plugin.yaml:

    kubectl apply -f wasm-plugin.yaml
    
  3. מוודאים שהפלאגין נפרס:

    kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
    

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

    Name:         gcp-wasm-plugin
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  networking.gke.io/v1
    Kind:         GCPWasmPlugin
    Metadata:
      Creation Timestamp:  2025-08-08T19:54:18Z
      Generation:          1
      Resource Version:    44578
      UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
    Spec:
      Log Config:
        Enabled: true
        Min Log Level: INFO
        Sample Rate: 1000000
      Versions:
        Description:  Test wasm plugin version
        Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
        Name:         wasm-plugin-version
        Weight:       1000000
      Events:     <none>
    

הגדרה של GCPTrafficExtension

כדי להוסיף לוגיקה מותאמת אישית למאזן עומסים גלובלי חיצוני של אפליקציות, אפשר להגדיר GCPTrafficExtension לשימוש ב-GCPWasmPlugin. אתם יכולים להשתמש ב-GCPTrafficExtension כדי להשתמש ביכולות מתקדמות של ניהול תנועה בסביבת Cloud de Confiance . אפשר להגדיר את התוסף הזה במאזני עומסים גלובליים חיצוניים של אפליקציות (ALB).

כדי להגדיר GCPTrafficExtension לשימוש ב-GCPWasmPlugin, מבצעים את השלבים הבאים:

  1. מגדירים את GCPTrafficExtension.

    1. שומרים את ההגדרה של GCPTrafficExtension בתור gcp-traffic-extension-with-plugin.yaml:

      kind: GCPTrafficExtension
      apiVersion: networking.gke.io/v1
      metadata:
        name: gcp-traffic-extension-with-plugin
        namespace: default
      spec:
        targetRefs:
        - group: "gateway.networking.k8s.io"
          kind: Gateway
          name: GATEWAY_NAME
        extensionChains:
        - name: chain1
          matchCondition:
            celExpressions:
            - celMatcher: request.path.contains("serviceextensions")
          extensions:
          - name: ext1
            supportedEvents:
            - RequestHeaders
            - ResponseHeaders
            backendRef:
              group: "networking.gke.io"
              kind: GCPWasmPlugin
              name: gcp-wasm-plugin
      

      מחליפים את GATEWAY_NAME בשם השער, למשל global-external-http.

    2. מחילים את קובץ המניפסט לדוגמה על האשכול:

      kubectl apply -f gcp-traffic-extension-with-plugin.yaml
      
  2. מאמתים את ההגדרה של GCPTrafficExtension ואת הקישור שלה ל-Gateway.

    1. בדיקת הפריסה של GCPTrafficExtension:

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

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

      Name:         gcp-traffic-extension-with-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-03-02T17:12:30Z
        Generation:        1
        Resource Version:  31283253
        UID:               ec8efaa0-d8e7-4e1b-9fd4-0ae0ef3c74d0
      Spec:
        Extension Chains:
          Extensions:
            Backend Ref:
              Group: networking.gke.io
              Kind: GCPWasmPlugin
              Name: gcp-wasm-plugin
            Name:       ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          Match Condition:
            Cel Expressions:
              Cel Matcher: request.path.contains("serviceextensions")
          Name:  chain1
        Target Refs:
          Group: gateway.networking.k8s.io
          Kind: Gateway
          Name: GATEWAY_NAME
      Events:  <none>
      

      מחליפים את GATEWAY_NAME בשם השער.

      בפלט מוצגים הפרטים של GCPTrafficExtension בשם gcp-traffic-extension-with-plugin במרחב השמות שמוגדר כברירת מחדל. הוא מציג את השדה Spec, שמכיל את ההגדרה של אופן הפעולה של התוסף.

    2. מאמתים את הקישור של שער התשלומים:

      מוודאים ש-GCPTrafficExtension משויך לשער. יכול להיות שיחלפו כמה דקות עד שהפקודה הזו תסתיים:

      kubectl describe gateway GATEWAY_NAME
      

      מחליפים את GATEWAY_NAME בשם השער.

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

      Name:         GATEWAY_NAME
      Namespace:    default
      Labels:       <none>
      Annotations:  networking.gke.io/addresses: /projects/922988411345/global/addresses/test-k18j-default-external-http-2jfqxrkgd0fm
                    networking.gke.io/backend-services:
                      /projects/922988411345/global/backendServices/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/backendServices...
                      networking.gke.io/certmap: store-example-com-map
                      networking.gke.io/firewalls: /projects/922988411345/global/firewalls/test-k18j-l7-default-global
                      networking.gke.io/forwarding-rules: /projects/922988411345/global/forwardingRules/test-k18j-default-external-http-wt1tl0cwi6zr
                      networking.gke.io/health-checks:
                        /projects/922988411345/global/healthChecks/test-k18j-default-gw-serve404-80-8zjp3d8cqfsu, /projects/922988411345/global/healthChecks/test-...
                      networking.gke.io/last-reconcile-time: 2025-08-08T20:27:35Z
                      networking.gke.io/lb-route-extensions:
                      networking.gke.io/lb-traffic-extensions:
                        projects/922988411345/locations/global/lbTrafficExtensions/test-k18j-default-external-http-0tdum40yts35
                      networking.gke.io/ssl-certificates:
                      networking.gke.io/target-http-proxies:
                      networking.gke.io/target-https-proxies: /projects/922988411345/global/targetHttpsProxies/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/url-maps: /projects/922988411345/global/urlMaps/test-k18j-default-external-http-jy9mc97xb5yh
                      networking.gke.io/wasm-plugin-versions:
                        projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk/versions/test-k18j-wasm-plugin-version-i...
                      networking.gke.io/wasm-plugins: projects/922988411345/locations/global/wasmPlugins/test-k18j-default-gcp-wasm-plugin-itle20jj9nyk
      API Version:  gateway.networking.k8s.io/v1
      Kind:         Gateway
      Metadata:
        Creation Timestamp:  2025-03-02T16:37:50Z
        Finalizers:
          gateway.finalizer.networking.gke.io
        Generation:        1
        Resource Version:  31284863
        UID:               fd512611-bad2-438e-abfd-5619474fbf31
      Spec:
        Gateway Class Name:  gke-l7-global-external-managed
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      https
          Port:      443
          Protocol:  HTTPS
      ...
      

      בפלט מוצגות ההערות, ש-GKE משתמש בהן כדי לאחסן את הקישורים בין ה-Gateway לבין משאבי Cloud de Confianceהבסיס. ההערות networking.gke.io/lb-traffic-extensions,‏ networking.gke.io/wasm-plugin-versions ו-networking.gke.io/wasm-plugins מאשרות את הקישור.

    3. בודקים את הסטטוס של התוסף:

      מוודאים שהסטטוס של GCPTrafficExtension הוא Programmed עם הסיבה ProgrammingSucceeded. יכול להיות שיחלפו כמה דקות עד שהפקודה תסתיים.

      kubectl describe gcptrafficextensions.networking.gke.io gcp-traffic-extension-with-plugin
      

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

      Name:         gcp-traffic-extension-with-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPTrafficExtension
      Metadata:
        Creation Timestamp:  2025-08-08T20:08:09Z
        Generation:          1
        Resource Version:    56528
        UID:                 1389f790-9663-45ca-ac4e-a2c082f43359
      Spec:
        Extension Chains:
          Extensions:
            Backend Ref:
              Group:  networking.gke.io
              Kind:   GCPWasmPlugin
              Name:   gcp-wasm-plugin
            Name:     ext1
            Supported Events:
              RequestHeaders
              ResponseHeaders
          Match Condition:
            Cel Expressions:
              Cel Matcher:  request.path.contains("serviceextensions")
          Name:             chain1
        Target Refs:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T20:16:13Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                  From                   Message
        ----    ------  ----                 ----                   -------
        Normal  ADD     19m                  sc-gateway-controller  default/gcp-traffic-extension-with-plugin
        Normal  SYNC    3m25s (x4 over 11m)  sc-gateway-controller  Attachment of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  All the object references were able to be resolved for GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  3m25s (x4 over 11m)  sc-gateway-controller  Programming of GCPTrafficExtension "default/gcp-traffic-extension-with-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
    4. בודקים את סטטוס הפלאגין.

      מוודאים שלמשאב GCPWasmPlugin יש סטטוס Programmed עם הסיבה ProgrammingSucceeded. יכול להיות שיחלפו כמה דקות עד שהפקודה תסתיים.

      kubectl describe gcpwasmplugins.networking.gke.io gcp-wasm-plugin
      

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

      Name:         gcp-wasm-plugin
      Namespace:    default
      Labels:       <none>
      Annotations:  <none>
      API Version:  networking.gke.io/v1
      Kind:         GCPWasmPlugin
      Metadata:
        Creation Timestamp:  2025-08-08T19:54:18Z
        Generation:          1
        Resource Version:    44578
        UID:                 549a12c7-91d1-43ad-a406-d6157a799b79
      Spec:
        Log Config:
          Enabled: true
          Min Log Level: INFO
          Sample Rate: 1000000
        Versions:
          Description:  Test wasm plugin version
          Image:        us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main
          Name:         wasm-plugin-version
          Weight:       1000000
      Status:
        Ancestors:
          Ancestor Ref:
            Group:      gateway.networking.k8s.io
            Kind:       Gateway
            Name:       external-http
            Namespace:  default
          Conditions:
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                Accepted
            Status:                True
            Type:                  Accepted
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ResolvedRefs
            Status:                True
            Type:                  ResolvedRefs
            Last Transition Time:  2025-08-08T19:59:06Z
            Message:
            Observed Generation:   1
            Reason:                ProgrammingSucceeded
            Status:                True
            Type:                  Programmed
          Controller Name:         networking.gke.io/gateway
      Events:
        Type    Reason  Age                 From                   Message
        ----    ------  ----                ----                   -------
        Normal  ADD     31m                 sc-gateway-controller  default/gcp-wasm-plugin
        Normal  SYNC    2m1s (x7 over 26m)  sc-gateway-controller  Attachment of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  All the object references were able to be resolved for WasmPlugin "default/gcp-wasm-plugin" bound to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil}
        Normal  SYNC  2m1s (x7 over 26m)  sc-gateway-controller  Programming of WasmPlugin "default/gcp-wasm-plugin" to AncestorRef {Group:       "gateway.networking.k8s.io",
      Kind:        "Gateway",
      Namespace:   "default",
      Name:        "external-http",
      SectionName: nil,
      Port:        nil} was a success
      
  3. שליחת תנועה לאפליקציה.

    אחרי שפורסים את ה-Gateway, את המסלול ואת האפליקציה באשכול, אפשר להעביר תנועה לאפליקציה.

    1. כדי לגשת לאפליקציה, צריך למצוא את כתובת ה-IP של השער.

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

      kubectl get gateways.gateway.networking.k8s.io GATEWAY_NAME -o=jsonpath="{.status.addresses[0].value}"
      

      מחליפים את GATEWAY_NAME בשם השער.

      הפקודה הזו מחזירה את כתובת ה-IP של השער. בפקודות הבאות, מחליפים את GATEWAY_IP_ADDRESS בכתובת ה-IP מהפלט.

    2. כדי לבדוק את עדכון הנתיב, עוברים לגרסה serviceextensions של שירות החנות בכתובת store.example.com/serviceextensions:

      curl https://store.example.com/serviceextensions --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
      

      הפלט שמתקבל הוא Hello World.

הגדרה של GCPEdgeExtension באמצעות GCPWasmPlugin

כדי להוסיף לוגיקה מותאמת אישית למאזן עומסים גלובלי חיצוני של אפליקציות באמצעות מודול WebAssembly‏ (Wasm), צריך להגדיר GCPEdgeExtension שמפנה אל GCPWasmPlugin.

  1. שומרים את קובץ המניפסט GCPEdgeExtension הבא בשם gcp-edge-extension-with-plugin.yaml:

    kind: GCPEdgeExtension
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-edge-extension-with-plugin
      namespace: default
    spec:
      targetRefs:
      - group: "gateway.networking.k8s.io"
        kind: Gateway
        name: GATEWAY_NAME
      extensionChains:
      - name: chain1
        matchCondition:
          celExpressions:
          - celMatcher: request.path.startsWith("/serviceextensions")
        extensions:
        - name: ext1
          supportedEvents:
          - RequestHeaders
          backendRef:
            group: "networking.gke.io"
            kind: GCPWasmPlugin
            name: gcp-wasm-plugin
    

    מחליפים את GATEWAY_NAME בשם השער.

  2. מחילים את המניפסט על האשכול:

    kubectl apply -f gcp-edge-extension-with-plugin.yaml
    
  3. מאמתים את ההגדרה של GCPEdgeExtension ואת הקישור שלו לשער:

    1. בודקים את הסטטוס של התוסף:

      כדי לבדוק את סטטוס התוסף של GCPEdgeExtension, מריצים את הפקודה הבאה:

      kubectl describe gcpedgeextensions.networking.gke.io gcp-edge-extension-with-plugin
      

      עליך לאשר שהסטטוס של GCPEdgeExtension הוא Programmed והסיבה היא ProgrammingSucceeded. יכול להיות שיעברו כמה דקות עד שהפקודה הזו תסתיים.

    2. מאמתים את הקישור של שער התשלומים:

      מריצים את הפקודה הבאה:

      kubectl describe gateway GATEWAY_NAME
      

      מחליפים את GATEWAY_NAME בשם השער.

      מוודאים ש-GCPEdgeExtension משויך לשער. יכול להיות שיעברו כמה דקות עד שהפקודה הזו תסתיים. הפלט כולל את ההערה networking.gke.io/lb-edge-extensions, שמאשרת את הקישור בין שער הנתונים לבין תוסף ה-Edge.

שליחת תנועה לתוסף

אחרי שפורסים את שער הגישה ואת GCPEdgeExtension, בודקים את לוגיקת הניתוב על ידי שליחת תנועה לאפליקציה.

  1. כדי לגשת לאפליקציה, צריך לקבל את כתובת ה-IP של השער:

    kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"
    

    הפלט הוא כתובת ה-IP של השער. בפקודות הבאות, מחליפים את GATEWAY_IP_ADDRESS בכתובת ה-IP מהפלט.

  2. שליחת בקשה לכתובת ה-URL הבסיסית:

    curl http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    השער מנתב את הבקשה לשירות שמוגדר כברירת מחדל, כמו store-v1.

  3. שולחים בקשה לנתיב שצוין ב-celMatcher, למשל /serviceextensions:

    curl http://store.example.com/serviceextensions --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    התוסף מפעיל את פלאגין ה-Wasm, שמנתב את הבקשה לשירות המשני, כמו store-v2.

ניהול המשאב GCPWasmPlugin

אפשר לעדכן את ה-CRD של GCPWasmPlugin ולעקוב אחרי הפלאגין.

עדכון של GCPWasmPlugin

כדי לעדכן משאב GCPWasmPlugin:

  1. מבצעים את השינוי במניפסט של GCPWasmPlugin ופועלים לפי השלבים שמתוארים במאמר פריסת GCPWasmPlugin.

    לדוגמה, כדי להשתמש בשתי גרסאות של הפלאגין, כשגרסה אחת מציגה תנועה והשנייה לא, מעדכנים את הקובץ wasm-plugin.yaml כך:

    kind: GCPWasmPlugin
    apiVersion: networking.gke.io/v1
    metadata:
      name: gcp-wasm-plugin
    spec:
      versions:
      - name: wasm-plugin-version-v1
        description: "Serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 1000000
      - name: wasm-plugin-version-v2
        description: "Non serving Wasm Plugin version"
        image: "us-docker.pkg.dev/service-extensions-samples/plugins/local-reply:main"
        weight: 0
      logConfig:
        enabled: true
        sampleRate: 1000000
        minLogLevel: INFO
    

    בדוגמה הזו, התנאים הבאים חלים:

    • ב-wasm-plugin-version-v1 יש weight של 1000000, כלומר הוא מציג מודעות לכל התנועה.
    • ל-wasm-plugin-version-v2 יש ערך weight של 0, כלומר הוא לא מציג תנועה.
  2. כדי לוודא שהשער עודכן, מריצים את הפקודה הבאה. יכול להיות שיעברו כמה דקות עד שהפקודה הזו תסתיים:

    kubectl describe gateway GATEWAY_NAME
    

    מחליפים את GATEWAY_NAME בשם השער.

מעקב אחרי GCPWasmPlugin

במאמר מעקב אחרי תוספים מוסבר איך רואים את המדדים של GCPWasmPlugin במסוף Cloud de Confiance .

כשמגיעים לשלב במדריך שבו צריך לבחור ערך מהרשימה Plugin version filter (מסנן גרסת הפלאגין), מחפשים את הפורמט prefix−WASM_PLUGIN_VERSION_NAME_FROM_FILE−suffix, כאשר WASM_PLUGIN_VERSION_NAME_FROM_FILE הוא שם הגרסה הספציפי שהגדרתם בקובץ ההגדרות GCPWasmPlugin.

פתרון בעיות בתוספי תנועה בשערי גישה

בקטע הזה אנחנו מפרטים טיפים לפתרון בעיות בהגדרת תוספי תנועה ב-Gateways.

השער לא נמצא

השגיאה הבאה מציינת שמשאב השער שצוין בשדה targetRefs של המשאב GCPTrafficExtension, GCPRoutingExtension או GCPEdgeExtension לא קיים:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.gatewayRef: gateway "my-gateway" not found in namespace "default"

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

השירות או יציאת השירות לא נמצאו

השגיאה הבאה מציינת שהשירות או יציאת השירות שצוינו בשדה backendRef של המשאב GCPTrafficExtension או GCPRoutingExtension לא קיימים:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: service "callout-service" not found in namespace "default"

כדי לפתור את הבעיה, צריך לוודא שהשירות ויציאת השירות שצוינו בשדה backendRef של המשאב GCPTrafficExtension או GCPRoutingExtension קיימים במרחב השמות שצוין.

אין נקודות קצה ברשת ב-NEG

השגיאה הבאה מציינת שאין נקודות קצה ברשת ב-NEG שמשויכות לשירות שצוין בשדה backendRef של המשאב GCPTrafficExtension או GCPRoutingExtension:

error: failed to create resource: GCPTrafficExtension.networking.gke.io "my-traffic-extension" is invalid: spec.service: no network endpoints found for service "callout-service"

כדי לפתור את הבעיה, צריך לוודא שלשירות שצוין בשדה backendRef של המשאב GCPTrafficExtension או GCPRoutingExtension יש נקודות קצה ברשת.

אין תשובה או שיש תשובה עם שגיאה כששולחים את הבקשה

אם לא מקבלים תשובה או שמקבלים תשובה עם שגיאה כששולחים בקשה, יכול להיות ששירות ההתקשרות לא פועל בצורה תקינה.

כדי לפתור את הבעיה, צריך לבדוק אם יש שגיאות ביומנים של שירות ההתקשרות.

קוד השגיאה 404 במטען הייעודי (payload) בפורמט JSON

השגיאה הבאה מציינת שלא נמצא שירות לשיחות יוצאות או שהוא לא מגיב לבקשה:

{
  "error": {
    "code": 404,
    "message": "Requested entity was not found.",
    "status": "NOT_FOUND"
  }
}

כדי לפתור את הבעיה, צריך לוודא שהשירות של ההפניה החוזרת פועל, שהוא מאזין ליציאה הנכונה ושהשירות מוגדר בצורה נכונה במשאב GCPTrafficExtension או GCPRoutingExtension.

קוד שגיאה 500 במטען הייעודי (payload) בפורמט JSON

השגיאה הבאה מציינת שיש שגיאת שרת פנימית בשירות של ההפניה:

{
  "error": {
    "code": 500,
    "message": "Internal server error.",
    "status": "INTERNAL"
  }
}

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

GCPWasmPlugin לא קיים

השגיאה הבאה מציינת שהמשאב GCPWasmPlugin לא קיים בפרויקט שלכם עבור GCPTrafficExtension או GCPEdgeExtension:

Status:
  Ancestors:
    Ancestor Ref:
      Group:      gateway.networking.k8s.io
      Kind:       Gateway
      Name:       external-http
      Namespace:  default
    Conditions:
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:
      Reason:                Accepted
      Status:                True
      Type:                  Accepted
      Last Transition Time:  2025-03-06T16:27:57Z
      Message:               error cause: invalid-wasm-plugin: GCPWasmPlugin default/my-wasm-plugin in GCPTrafficExtension default/my-gateway-plugin-extension does not exist
      Reason:                GCPWasmPluginNotFound
      Status:                False
      Type:                  ResolvedRefs
    Controller Name:         networking.gke.io/gateway

כדי לפתור את הבעיה, צריך ליצור GCPWasmPlugin תואם בפרויקט Cloud de Confiance או להפנות תוסף אל GCPWasmPlugin קיים.

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