פריסת שערים

פריסת משאבי Kubernetes Gateway כדי לנהל את האופן שבו תנועה חיצונית מגיעה לאפליקציות באשכול Google Kubernetes Engine (GKE) יחיד. הגדרת GKE Gateway מאפשרת שליטה גמישה ומשמעותית בתעבורת הנתונים הנכנסת (ingress), ומשפרת את יכולת ההתאמה לעומס (scalability) ואת האמינות של האפליקציות. לדוגמה, GKE Gateway מציע יכולות של ניתוב אופטימלי ושל התאמה אוטומטית לעומס. היכולות האלה חיוניות למילוי בקשות באופן מיידי עם זמן אחזור קצר, כדי להבטיח חוויית משתמש מהירה ולעזור לשלוט בעלויות.

כדי לפרוס שערים בכמה אשכולות או ב-fleet, קראו את המאמר פריסת שערים מרובי אשכולות. להגדרות ספציפיות של Gateway, כמו ניתוב בין מרחבי שמות ופיצול תנועת HTTP, אפשר לעיין במדריכים למשתמשים של Gateway API.

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

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

  • מפעילים את Google Kubernetes Engine API.
  • הפעלת Google Kubernetes Engine API
  • כדי להשתמש ב-Google Cloud CLI למשימה הזו, מתקינים ואז מאתחלים את ה-CLI של gcloud. אם כבר התקנתם את ה-CLI של gcloud, הריצו את הפקודה gcloud components update כדי לקבל את הגרסה העדכנית. יכול להיות שבגרסאות קודמות של ה-CLI של gcloud אי אפשר להריץ את הפקודות שבמסמך הזה.
  • מוודאים שיש לכם אשכול קיים במצב Autopilot או במצב Standard. כדי ליצור אשכול חדש, קראו את המאמר יצירת אשכול Autopilot.

  • כדי ליצור את מפות האישורים הנדרשות, ודאו שלחשבון המשתמש שלכם יש את התפקיד 'עריכת Certificate Manager' (roles/certificatemanager.editor).

הדרישות של GKE Gateway controller

  • אפשר להשתמש ב-Gateway API רק באשכולות מותאמים ל-VPC.
  • אם אתם משתמשים ב-GatewayClasses אזוריים או חוצי-אזורים, אתם צריכים להפעיל רשת משנה לשרת proxy בלבד.
  • התוסף HttpLoadBalancing צריך להיות מופעל באשכול.
  • אם אתם משתמשים ב-Istio, אתם צריכים לשדרג את Istio לאחת מהגרסאות הבאות:
    • ‫1.15.2 ואילך
    • ‫1.14.5 ואילך
    • ‫1.13.9 ואילך.
  • אם משתמשים ב-VPC משותף, צריך להקצות בפרויקט המארח את התפקיד Compute Network User לחשבון השירות של GKE בפרויקט השירות.

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

כשמשתמשים ב-GKE Gateway, חשוב להבין את המגבלות וההגבלות הבאות:

  • היכולות של GKE GatewayClasses משתנות בהתאם למאזן העומסים שבו משתמשים. למידע נוסף על התכונות השונות שנתמכות בכל GatewayClass, קראו את המאמר יכולות של GatewayClass.

    שיטה מומלצת:

    כדי להבטיח ביצועים אופטימליים, מומלץ להגביל את מספר השערים ל-100 לכל היותר. חריגה מהמגבלה הזו עלולה להשפיע על הביצועים או לגרום לעלייה בזמן האחזור.

  • ‫GKE Gateway תומך רק בערוץ ההפצה הרגיל של Gateway API.

  • ‫GKE Gateway תמיד מופעל באשכולות Autopilot. אי אפשר להתקין CRD של ערוץ ההפצה הניסיוני של Gateway API באשכולות Autopilot.

  • אי אפשר להשתמש ב-FrontendConfig או ב-BackendConfig כדי להגדיר שער. צריך להשתמש ב-Policy.

  • ‫GKE Gateway פועל באופן שונה מ-Ingress, כי Gateway לא מסיק פרמטרים של בדיקת תקינות. אם השירות לא מחזיר את הערך 200 לבקשות ל-GET /, או אם יש לכם בדיקות מוכנות אחרות של pod, אתם צריכים להגדיר HealthCheckPolicy לשירות.

  • אי אפשר לציין מספר יציאה ישירות בשם המארח (לדוגמה, web.example.com:80) לניתוב תנועה.

  • אתם יכולים לראות את משאבי מאזן העומסים ש-GKE יוצר לשערים במסוף Google Cloud , אבל המשאבים האלה לא מפנים לשער או לאשכול GKE שאליהם הם מחוברים.

  • אי אפשר ליצור באופן אוטומטי אישור SSL בניהול Google באמצעות שערים, אבל אפשר ליצור באופן ידני אישור SSL בניהול Google ולהפנות אליו. מידע נוסף זמין במאמר אבטחת שער.

  • ‫HTTPRoute הוא סוג הנתיב היחיד שנתמך. אין תמיכה ב-TCPRoutes, ב-UDPRoutes וב-TLSRoutes. רשימה של השדות שנתמכים ב-GKE Gateway Controller מופיעה במאמר היכולות של GatewayClass.

  • כותרות מותאמות אישית של בקשות ותגובות עם Gateway או הפניות אוטומטיות של נתיבים ושכתובים של כתובות URL עם Gateway זמינים רק ב-GKE מגרסה 1.27 ואילך.

  • בכותרות מותאמות אישית של בקשות ותגובות עם הפניות אוטומטיות של Gateway ונתיבים, ובשכתובים של כתובות URL עם Gateway, אין תמיכה ב-GatewayClass gke-l7-gxlb.

  • כשמגדירים כותרות של בקשות בהתאמה אישית ב-HTTPRoute, אי אפשר להשתמש Google Cloud במשתנה origin_request_header. כדי להגדיר CORS, אפשר להשתמש בסוג המסנן CORS.

  • המגבלות שלGoogle Cloud מאזן העומסים הקלאסי של אפליקציות (ALB) חלות על GKE Gateway. בנוסף, אי אפשר להגדיר כותרת תגובה מותאמת אישית של מארח בשירות לקצה העורפי.

  • הפניות אוטומטיות של נתיבים ושכתובים של כתובות URL הם בלעדיים זה לזה, אי אפשר להשתמש בשני המסננים בו-זמנית באותם כללים.

  • ב-Cloud Load Balancing אין תמיכה בהפניית תנועה ליציאה אחרת. כדי לראות את רשימת השדות שנתמכים ב-GKE Gateway controller, קראו את המאמר היכולות של GatewayClass.

  • ‫GKE Gateway לא תומך בתווים כלליים לחיפוש ובכתובות URL דינמיות. ביטויים רגולריים לא נתמכים ב-GatewayClasses‏ gke-l7-gxlb ו-gke-l7-gxlb-mc. מידע נוסף זמין במאמר הגדרת התאמה לביטויים רגולריים.

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

  • השער משתמש בקבוצות עצמאיות של נקודות קצה ברשת כדי להקצות קבוצות של נקודות קצה ברשת. כדי לוודא שבקר ה-Gateway מתאים בצורה נכונה את הגדרת מאזן העומסים, אי אפשר לשנות את ההערה cloud.google.com/neg של שירות שהוא חלק מה-Gateway.

  • ‫GKE Gateway לא תומך בהפניה לשירות שגם GKE Ingress מפנה אליו.

  • כששער מוגדר להקצות כתובת IP, אי אפשר לשנות את ה-Gateway.spec.gatewayClass. כדי לוודא שבקר השער מתאים בצורה נכונה את מאזן העומסים, צריך למחוק את השער הקיים ולפרוס מחדש את המניפסט עם הערך המעודכן של gatewayClass.

  • אין תמיכה בהערה networking.gke.io/app-protocols. כדי להשיג את אותה תוצאה, צריך להשתמש בשדה appProtocol.

  • אם אתם משתמשים ב-GKE Gateway עם external-dns ומצב התקינות של ה-Gateway לא תקין, כברירת מחדל כל רשומות ה-DNS שמשויכות ל-Gateway נמחקות מתחומי ה-DNS שלכם.

    שיטה מומלצת:

    כשמריצים את external-dns, מגדירים את הדגל policy=upsert-only. ההגדרה הזו עוזרת למנוע מחיקה של רשומות DNS קיימות.

  • אם מסירים יציאה משירות ש-GKE Gateway מפנה אליו דרך נתיב, צריך גם לעדכן את ההערה של ה-NEG העצמאי בשירות כדי להסיר את היציאה הזו. אם לא תעשו את זה, בסופו של דבר בקר ה-NEG יפסיק לסנכרן את נקודות הקצה של Pod בשביל השירות הזה. לפרטים, ראו בקר NEG מפסיק לנהל נקודות קצה כשמסירים יציאה מהשירות.

  • פריסות שמשתמשות בשערים מרובי אשכולות (MCG) עם אשכולות אזוריים עלולות לגרום לשיבושים בשירות במהלך שדרוגי אשכולות. הבעיה הזו מתרחשת כי מנגנון גילוי מדור קודם של קבוצת נקודות קצה ברשת (NEG) עלול לדווח באופן שגוי על אפס שירותים לקצה העורפי כשמישור הבקרה של האשכול האזורי לא זמין באופן זמני. אנחנו עובדים על פתרון לטווח ארוך. כדי למנוע את נקודת הכשל הבודדת הזו, השתמשו באשכולות GKE אזוריים עם MCG.

הפעלת Gateway API באשכול

כדי להשתמש במשאבי Gateway ב-GKE, צריך להפעיל את Gateway API באשכול.

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

כדי להפעיל את Gateway API באשכול GKE קיים (Autopilot או Standard), משתמשים בפקודה הבאה. הפעולה הזו יכולה להימשך עד 45 דקות, עד שהאשכול יתאים ויתקין את CustomResourceDefinition.

gcloud container clusters update CLUSTER_NAME \
    --location=CLUSTER_LOCATION\
    --gateway-api=standard

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

הדגל --gateway-api=standard מורה ל-GKE להתקין את ה-CRD של Gateway API Standard Channel עם האשכול.

אימות האשכול

אחרי שיוצרים או משדרגים את האשכול, GKE Gateway controller מתקין באופן אוטומטי את GatewayClasses. יכול להיות שיעברו כמה דקות עד שהבקר יזהה את ה-CRD ויתקין את ה-GatewayClasses.

  1. מוודאים ש-Gateway API מופעל במישור הבקרה של GKE:

    gcloud container clusters describe CLUSTER_NAME \
      --location=CLUSTER_LOCATION \
      --format json
    

    הפלט אמור להיראות כך: אם הפלט הזה ריק, מריצים מחדש את פקודת עדכון האשכול.

    "networkConfig": {
      ...
      "gatewayApiConfig": {
        "channel": "CHANNEL_STANDARD"
      },
      ...
    },
    
  2. מוודאים שה-GatewayClasses מותקנים באשכול:

    kubectl get gatewayclass
    

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

    NAME                             CONTROLLER                  ACCEPTED   AGE
    gke-l7-global-external-managed   networking.gke.io/gateway   True       16h
    gke-l7-regional-external-managed networking.gke.io/gateway   True       16h
    gke-l7-gxlb                      networking.gke.io/gateway   True       16h
    gke-l7-rilb                      networking.gke.io/gateway   True       16h
    

כדי להבין את היכולות של כל GatewayClass, קראו את המאמר יכולות של GatewayClass.

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

פריסת שער פנימי

שער פנימי חושף אפליקציות שאפשר לגשת אליהן רק מתוך ה-VPC או מרשתות שמחוברות ל-VPC.

פריסת שער פנימי אזורי

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

הגדרת רשת משנה לשרתי proxy בלבד

לפני שיוצרים שער שמשתמש במאזן עומסים של אפליקציות (ALB) פנימי, צריך להגדיר רשת משנה של שרת proxy בלבד. בכל אזור של VPC שבו אתם משתמשים במאזני עומסים פנימיים של אפליקציות (ALB), חייבת להיות רשת משנה של שרתי proxy בלבד. רשת המשנה הזו מספקת כתובות IP פנימיות לשרתי ה-Proxy של מאזן העומסים.

  1. יוצרים רשת משנה מסוג proxy-only:

    gcloud compute networks subnets create SUBNET_NAME \
        --purpose=REGIONAL_MANAGED_PROXY \
        --role=ACTIVE \
        --region=COMPUTE_REGION \
        --network=VPC_NETWORK_NAME \
        --range=CIDR_RANGE
    

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

    • ‫SUBNET_NAME: השם של רשת המשנה לשרתי proxy בלבד.
    • ‫COMPUTE_REGION: האזור של רשת המשנה לשרתי proxy בלבד.
    • ‫VPC_NETWORK_NAME: השם של רשת ה-VPC שבה יוצרים את רשת המשנה הזו שמשמשת רק לשרת proxy. חשוב לוודא שזו אותה רשת VPC שבה נמצא אשכול GKE ושבה אתם פורסים את השער. זה חשוב כדי שהתקשורת בין מאזן העומסים לבין שירותי הקצה העורפי תהיה חלקה.
    • ‫CIDR_RANGE: טווח כתובות ה-IP הראשי של רשת המשנה. צריך להשתמש במסכה של רשת משנה באורך של עד /26, כדי שלפחות 64 כתובות IP יהיו זמינות לשרתי proxy באזור. מסכה של רשת משנה המומלצת היא /23.
  2. מאמתים את רשת המשנה לשרת proxy בלבד:

    gcloud compute networks subnets describe SUBNET_NAME \
        --region=COMPUTE_REGION
    

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

    ...
    gatewayAddress: 10.1.1.1
    ipCidrRange: 10.1.1.0/24
    kind: compute#subnetwork
    name: proxy-subnet
    network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default
    privateIpGoogleAccess: false
    privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS
    purpose: REGIONAL_MANAGED_PROXY
    region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION
    role: ACTIVE
    selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet
    state: READY
    

יצירת שער

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

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

  1. שומרים את המניפסט הבא של Gateway בקובץ בשם gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
       name: internal-http
    spec:
      # Specify an existing GatewayClass.
      gatewayClassName: gke-l7-rilb
      listeners:
      # Listen for HTTP traffic on port 80.
      - name: http
        protocol: HTTP
        port: 80
    

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

    • ‫gatewayClassName: gke-l7-rilb: מציין את ה-GatewayClass שממנו נגזר ה-Gateway הזה. ‫gke-l7-rilb תואם למאזן העומסים הפנימי של האפליקציות.
    • ‫port: 80: מציין שהשער חושף רק את יציאה 80 להאזנה לתנועת HTTP.

    השער הזה מוגדר לטפל בתנועת HTTP רק ביציאה 80. הוא לא תומך ב-HTTPS (יציאה 443) כברירת מחדל, ואם תנסו להתחבר באמצעות HTTPS, יכול להיות שהבקשה תיכשל.

  2. פורסים את השער באשכול:

    kubectl apply -f gateway.yaml
    
  3. מוודאים שהשער נפרס בצורה תקינה. יכול להיות שיעברו כמה דקות עד שכל המשאבים ייפרסו.

    kubectl describe gateways.gateway.networking.k8s.io internal-http
    

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

    Name:         internal-http
    Namespace:    default
    Spec:
      Gateway Class Name:  gke-l7-rilb
      Listeners:
        Allowed Routes:
          Kinds:
            Group:  gateway.networking.k8s.io
            Kind:   HTTPRoute
          Namespaces:
            From:  Same
        Name:      http
        Port:      80
        Protocol:  HTTP
     Status:
       Addresses:
         Type:   IPAddress
         Value:  192.168.1.14
       Conditions:
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:               The OSS Gateway API has deprecated this condition, do not depend on it.
         Observed Generation:   1
         Reason:                Scheduled
         Status:                True
         Type:                  Scheduled
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Accepted
         Status:                True
         Type:                  Accepted
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Programmed
         Status:                True # Indicates that the Gateway is ready.
         Type:                  Programmed
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:               The OSS Gateway API has altered the "Ready" condition semantics and reserved it for future use.  GKE Gateway will stop emitting it in a future update, use "Programmed" instead.
         Observed Generation:   1
         Reason:                Ready
         Status:                True
         Type:                  Ready
         Last Transition Time:  2025-03-19T19:53:46Z
         Message:
         Observed Generation:   1
         Reason:                Healthy
         Status:                True
         Type:                  networking.gke.io/GatewayHealthy
    Events:
      Type    Reason  Age                From                       Message
      ----    ------  ----               ----                       -------
      Normal  ADD     92s                networking.gke.io/gateway  test/internal-http
      Normal  UPDATE  45s (x3 over 91s)  networking.gke.io/gateway  test/internal-http
      Normal  SYNC    45s                networking.gke.io/gateway  SYNC on test/internal-http was a success
    

    בפלט הזה, הסטטוס True של התנאי Programmed מציין שהשער מוכן.

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

פריסת אפליקציות ההדגמה

צוותי האפליקציות יכולים לפרוס את האפליקציות והנתיבים שלהם בנפרד מהפריסה של השערים. במקרים מסוימים, יכול להיות שצוות האפליקציה ירצה להיות הבעלים של השער ולפרוס אותו בעצמו כמשאב שמוקדש לאפליקציות שלו. במאמר קישור נתיבים מוסבר על מודלים שונים של בעלות על שערים ונתיבים. בדוגמה הזו, צוות החנות פורס את האפליקציה שלו ואת ה-HTTPRoute הנלווה כדי לחשוף את האפליקציה דרך שער ה-internal-http שנוצר בקטע הקודם.

למשאב HTTPRoute יש הרבה שדות שאפשר להגדיר להתאמת תנועה. הסבר על השדות של HTTPRoute מופיע במפרט ה-API.

  1. פורסים את אפליקציית החנות (פריסות store-v1,‏ store-v2 ו-store-german) באשכול:

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    כך נוצרים שלושה פריסות ושלושה שירותים שנקראים store-v1,‏ store-v2 ו-store-german.

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

    kubectl get pod
    

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

    NAME                        READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. מוודאים שהשירותים נפרסו:

    kubectl get service
    

    בפלט מוצג שירות לכל פריסה של חנות:

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

פריסת ה-HTTPRoute

משאבי Route מגדירים כללים ספציפיים לפרוטוקול למיפוי תנועה מ-Gateway לקצוות עורפיים של Kubernetes. המשאב HTTPRoute מבצע התאמה וסינון של תעבורת נתונים ב-HTTP וב-HTTPS, ונתמך על ידי כל ה-GatewayClasses של gke-l7.

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

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

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store
    spec:
      # Attach the HTTPRoute to a Gateway.
      parentRefs:
      - kind: Gateway
        name: internal-http
      # Route requests that have `store.example.com` in the Host header.
      hostnames:
      - "store.example.com"
      rules:
      # Send requests with the `env: canary` header to the `store-v2` Service.
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      # Send requests with `/de` in the path to the `store-german` Service.
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
      # Send unmatched requests to the store-v1 Service.
      - backendRefs:
        - name: store-v1
          port: 8080
    
  2. פורסים את HTTProute באשכול:

    kubectl apply -f store-route.yaml
    

    ה-HTTPRoute של store מקושר לשער internal-http באמצעות המאפיין parentRefs. כללי הניתוב האלה מוגדרים במאזן העומסים הבסיסי, כמו בתרשים הבא:

    כללי הניתוב שהוגדרו על ידי HTTPRoute של החנות

    כללי הניתוב האלה מעבדים את תנועת ה-HTTP באופן הבא:

    • התנועה אל store.example.com/de מגיעה לשירות store-german.
    • תנועה אל store.example.com עם כותרת ה-HTTP‏ "env: canary" מועברת לשירות store-v2.
    • שאר התנועה אל store.example.com מועברת לשירות store-v1.
  3. מוודאים שה-HTTPRoute נפרס:

    kubectl describe httproute store
    

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

    Name:         store
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1
    Kind:         HTTPRoute
    # Multiple lines are omitted here.
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   internal-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        Conditions:
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2022-11-01T04:18:52Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
    Events:
      Type    Reason  Age                From                   Message
      ----    ------  ----               ----                   -------
      Normal  ADD     24m                sc-gateway-controller  default/store
      Normal  SYNC    16m (x4 over 23m)  sc-gateway-controller  Bind of HTTPRoute "default/store" to ParentRef {Group:       gateway.networking.k8s.io",
      # Multiple lines are omitted here.
    
  4. מוודאים שה-HTTPRoute מקושר ל-Gateway:

    kubectl describe gateway
    

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

    Name:         internal-http
    Namespace:    default
    Labels:       <none>
    <...>
    Status:
      Addresses:
        Type:   IPAddress
        Value:  10.128.15.203
      Conditions:
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T03:47:01Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T03:47:01Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    http
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          <...>
    

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

אחרי שפרסתם את השער, המסלול והאפליקציה באשכול, אתם יכולים להעביר תנועה לאפליקציה. השער מוגדר להעביר תנועת HTTP רק ביציאה 80. בקשות שנשלחות באמצעות HTTPS עלולות להיכשל, אלא אם מגדירים את TLS בנפרד.

  1. מאחזרים את כתובת ה-IP מהשער כדי שתוכלו לשלוח תנועה לאפליקציה:

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

    הפלט הוא כתובת IP.

  2. שולחים תנועה לכתובת ה-IP הזו ממכונה וירטואלית (VM) שמחוברת לאשכול. הפעולה הזו נדרשת כי לשער יש כתובת IP פנימית, ואפשר לגשת אליו רק מתוך רשת ה-VPC. ‫internal-http הוא מאזן עומסים אזורי, ולכן ה-VM של הלקוח צריך להיות באותו אזור של אשכול GKE.

    יוצרים מכונה וירטואלית לבדיקה באותו אזור ורשת VPC:

    gcloud compute instances create test-vm \
        --zone=COMPUTE_ZONE \
        --network=VPC_NETWORK_NAME
    

    מתחברים למכונה הווירטואלית באמצעות SSH:

    gcloud compute ssh test-vm --zone=COMPUTE_ZONE
    

    במעטפת של ה-VM, שולחים בקשה אל store.example.com:

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

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

    הפלט מאפליקציית ההדגמה מציג מידע על המיקום שבו האפליקציה פועלת:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:31:17",
      "zone": "ZONE_NAME"
    }
    
  3. כדי לבדוק את ההתאמה של הנתיב, עוברים לגרסה הגרמנית של שירות החנות בכתובת store.example.com/de:

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

    הפלט מאשר שהבקשה טופלה על ידי Pod של store-german:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!", 
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl", 
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:35:37",
      "zone": "ZONE_NAME"
    }
    
  4. לבסוף, משתמשים בכותרת ה-HTTP‏ env: canary כדי לשלוח תנועה לגרסת ה-canary של שירות החנות:

    curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -v
    

    הפלט מאשר שהבקשה טופלה על ידי Pod של store-v2:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2", 
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb", 
      "pod_name_emoji": "🦰",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-10-25T13:38:26",
      "zone": "ZONE_NAME"
    }
    

פריסת שער חיצוני

שער חיצוני חושף אפליקציות שאפשר להגיע אליהן מהאינטרנט או מרשתות מחוץ לרשת ה-VPC. הפריסה דומה לפריסת שער פנימי, אבל צריך לאבטח את האפליקציות כי השער נגיש לאינטרנט הציבורי.

יש שתי אפשרויות ליצירת שער חיצוני: שער חיצוני גלובלי או שער חיצוני אזורי.

  • שער חיצוני אזורי: השער הזה משתמש בכתובת IP אזורית בתור ממשק ה-frontend של השער. ההתנהגות של השער הזה תלויה במסלול שירות הרשת שבחרתם:
    • אם בוחרים במסלול הרגיל של שירות הרשת (ברירת המחדל), כתובת ה-IP האזורית מפורסמת רק באזור המקומי של Google Cloud שבו נפרס שער ה-NAT החיצוני האזורי. לקוחות ששולחים תעבורת נתונים לכתובת ה-IP הזו מנותבים על ידי ספק האינטרנט המקומי שלהם ודרך האינטרנט הציבורי, לפני שהם מגיעים לאזור Google שבו כתובת ה-IP מפורסמת.
    • אם בוחרים במסלול הפרימיום של שירות הרשת, כתובת ה-IP האזורית מפורסמת ברשת הגלובלית של Google. כלומר, תעבורת הנתונים של הלקוח נכנסת לשדרה המרכזית הגלובלית והאיכותית של Google בנקודת קישור בין רשתות שכנות (peering) בקצה הרשת של Google, שהכי קרובה ללקוח, גם אם היעד הוא כתובת IP אזורית. המיקום הזה מקצר משמעותית את זמן האחזור ומשפר את הביצועים, כי הוא מצמצם את המרחק שהתנועה עוברת באינטרנט הציבורי.
  • ‫Global external Gateway: השער הזה משתמש בכתובת IP גלובלית (או בכתובת IP מסוג Anycast) בתור ממשק הקצה של השער. כתובת ה-IP הזו מפורסמת בכל האזורים של Google Cloud Compute. לקוחות ששולחים תנועה לכתובת ה-IP הזו מסוג Anycast מנותבים למיקום הקרוב ביותר של Google שבו כתובת ה-IP מפורסמת. השער החיצוני הגלובלי זמין רק במסלול הפרימיום של שירות הרשת.

פריסת שער אזורי חיצוני

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

יצירת רשת משנה של שרת proxy לשער האזורי

לפני שיוצרים שער שמשתמש במאזן עומסים חיצוני אזורי של אפליקציות (ALB), צריך להגדיר רשת משנה לשרת proxy בלבד. בכל אזור של VPC שבו משתמשים במאזן עומסים חיצוני אזורי של אפליקציות (ALB), צריך להיות רשת משנה של external_managed_proxy. רשת המשנה הזו מספקת כתובות IP פנימיות לשרתי ה-proxy של מאזן העומסים.

יצירת אישור לאבטחת תנועת הלקוחות

אתם יכולים להשתמש באישור שהונפק ואומת על ידי רשות האישורים (CA) שלכם, או ליצור אישור עם חתימה עצמית. למידע נוסף על יצירת אישור, ראו אחסון אישור ב-Kubernetes Secret.

כדי לאבטח את התנועה בין הלקוחות לבין השער האזורי, אפשר להשתמש בשיטות הבאות:

  • אישורים ב-Certificate Manager שמנוהלים על ידי Google או בניהול עצמי
  • אישורי SSL אזוריים בניהול עצמי
  • סודות של Kubernetes

אישורי SSL בניהול Google או CertificateMap לא נתמכים בשערים אזוריים.

מידע נוסף זמין במאמר אישורים ומאזני עומסים ב- Google Cloud .

יצירת שער HTTP(S) חיצוני אזורי

  1. יוצרים כתובת IP סטטית אזורית למאזן העומסים החיצוני.

    gcloud compute addresses create IP_ADDRESS_NAME \
      --region=COMPUTE_REGION \
      --network-tier=STANDARD
    

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

    • ‫IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה.
    • ‫COMPUTE_REGION: האזור ב-Compute Engine שבו פועל האשכול.
  2. כדי ליצור שער של מאזן עומסים חיצוני אזורי של אפליקציות (ALB) באמצעות אישור בניהול עצמי, פועלים לפי השלבים הבאים ושומרים את המניפסט בתור regional-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: external-regional-http
      spec:
        # Name of an existing GatewayClass.
        gatewayClassName: gke-l7-regional-external-managed
        # Listen for HTTPS traffic on port 443
        listeners:
        - name: https
          protocol: HTTPS
          port: 443
          tls:
            # Terminate the TLS session with the client at the Gateway.
            mode: Terminate
            # Certificates for the Gateway to use to create a new TLS session.
            certificateRefs:
            - name: store-example-com
        # The name of the static IP address of the external load balancer.
        # You can also use the `IPAddress` type to specify the actual IP address.
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
    
  3. מחילים את המניפסט regional-gateway:

      kubectl apply -f regional-gateway.yaml
    
  4. צריך לאמת את ההגדרות.

      kubectl get gateway
    

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

    NAME            CLASS                              ADDRESS         READY   AGE
    external-http   gke-l7-regional-external-managed   35.118.32.224   True    49s
    

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

    kubectl describe gateway
    

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

    Name:         external-regional-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-regional-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
      ...
    

פריסת אפליקציות ההדגמה

צוותי האפליקציות יכולים לפרוס את האפליקציות והנתיבים שלהם בנפרד מהפריסה של השערים. במקרים מסוימים, יכול להיות שצוות האפליקציה ירצה להיות הבעלים של השער ולפרוס אותו בעצמו כמשאב שמוקדש לאפליקציות שלו. במאמר קישור נתיבים מוסבר על מודלים שונים של בעלות על שערים ונתיבים. בדוגמה הזו, צוות החנות פורס את האפליקציה שלו ואת ה-HTTPRoute הנלווה כדי לחשוף את האפליקציה דרך השער external-http שנוצר בקטע הקודם.

מידע נוסף על שדות HTTPRoute זמין במפרט ה-API.

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

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/store.yaml
    

    האפליקציה לדוגמה יוצרת שלושה פריסות ושלושה שירותים שנקראים store-v1,‏ store-v2 ו-store-german.

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

    kubectl get pod
    

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

    NAME                            READY   STATUS    RESTARTS   AGE
    store-german-66dcb75977-5gr2n   1/1     Running   0          38s
    store-v1-65b47557df-jkjbm       1/1     Running   0          14m
    store-v2-6856f59f7f-sq889       1/1     Running   0          14m
    
  3. מוודאים שהשירותים נפרסו בהצלחה:

    kubectl get service
    

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

    NAME           TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)    AGE
    store-german   ClusterIP   10.48.3.183   <none>        8080/TCP   4s
    store-v1       ClusterIP   10.48.2.224   <none>        8080/TCP   5s
    store-v2       ClusterIP   10.48.4.48    <none>        8080/TCP   5s
    

יצירת HTTPRoute

משאבי Route מגדירים כללים ספציפיים לפרוטוקול למיפוי תנועה מ-Gateway לקצוות עורפיים של Kubernetes. המשאב HTTPRoute מבצע התאמה וסינון של תנועת HTTP ו-HTTPS, ונתמך על ידי כל ה-GatewayClasses של gke-l7-*.

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

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

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-external
    spec:
      parentRefs:
      # Bind the route to the 'external-http' Gateway.
      - kind: Gateway
        name: external-http
      hostnames:
      - "store.example.com"
      rules:
      # Default rule for store.example.com that sends traffic to the store-v1 service.
      - backendRefs:
        - name: store-v1
          port: 8080
      # Match requests with the "env: canary" header and send them to the store-v2 service.
      - matches:
        - headers:
          - name: env
            value: canary
        backendRefs:
        - name: store-v2
          port: 8080
      # Match requests with the path "/de" and sends them to the store-german service.
      - matches:
        - path:
            value: /de
        backendRefs:
        - name: store-german
          port: 8080
    

    המניפסט הזה מתאר HTTPRoute שמפנה אל השער external-http.

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

    kubectl apply -f store-route-external.yaml
    

    ה-HTTPRoute‏ store מקושר לשער external-http באמצעות המאפיין parentRefs. בתרשים הבא מוצגים כללי הניתוב שהוגדרו במאזן העומסים הבסיסי:

    כללי הניתוב שהוגדרו על ידי HTTPRoute של החנות

    כללי הניתוב מעבדים את תנועת ה-HTTP באופן הבא:

    • תנועה אל store.example.com/de מנותבת לשירות store-german.
    • תנועה אל store.example.com עם כותרת ה-HTTP‏ "env: canary" מנותבת לשירות store-v2.
    • שאר התנועה אל store.example.com מנותבת לשירות store-v1.
  3. מוודאים שה-HTTPRoute נפרס:

    kubectl describe httproute store-external
    

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

    Name:         store-external
    Namespace:    default
    Labels:       <none>
    Annotations:  <none>
    API Version:  gateway.networking.k8s.io/v1
    Kind:         HTTPRoute
    # Multiple lines are omitted here.
    Spec:
      Hostnames:
        store.example.com
      Parent Refs:
        Group:  gateway.networking.k8s.io
        Kind:   Gateway
        Name:   external-http
      Rules:
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v1
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-v2
          Port:    8080
          Weight:  1
        Matches:
          Headers:
            Name:   env
            Type:   Exact
            Value:  canary
          Path:
            Type:   PathPrefix
            Value:  /
        Backend Refs:
          Group:
          Kind:    Service
          Name:    store-german
          Port:    8080
          Weight:  1
        Matches:
          Path:
            Type:   PathPrefix
            Value:  /de
    Status:
      Parents:
        # This section shows the status of this route in relation to each Gateway attached.
        Conditions:
          Last Transition Time:  2022-11-01T05:42:31Z
          Message:
          Reason:                Accepted
          Status:                True # Means that the Gateway has validated and accepted this route's configuration.
          Type:                  Accepted
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   external-http
    Events:
      Type     Reason  Age    From                   Message
      ----     ------  ----   ----                   -------
      Normal   ADD     2m48s  sc-gateway-controller  default/store-external
      Normal  SYNC  61s (x3 over 2m27s)  sc-gateway-controller  Bind of HTTPRoute "default/store-external" to ParentRef Group:       "gateway.networking.k8s.io",
      ...
    
  4. מוודאים שה-HTTPRoute מקושר ל-Gateway:

    kubectl describe gateway external-http
    

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

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    # Multiple lines are omitted here.
    Status:
      Addresses:
        Type:   IPAddress
        Value:  34.149.207.45
      Conditions:
        Last Transition Time:  2022-11-01T05:37:21Z
        Message:
        Reason:                Scheduled
        Status:                True
        Type:                  Scheduled
        Last Transition Time:  2022-11-01T05:43:18Z
        Message:
        Reason:                Ready
        Status:                True
        Type:                  Ready
      Listeners:
        Attached Routes:  1
        Conditions:
          Last Transition Time:  2022-11-01T05:43:18Z
          Message:
          Reason:                Ready
          Status:                True
          Type:                  Ready
        Name:                    https
        Supported Kinds:
          Group:  gateway.networking.k8s.io
          Kind:   HTTPRoute
          # Multiple lines are omitted here.
    

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

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

  1. מאתרים את כתובת ה-IP של השער:

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

    הפלט הוא כתובת IP.

  2. יוצרים מכונה וירטואלית:

    gcloud cloud-shell ssh
    
  3. שולחים תנועה לכתובת ה-IP של השער מה-VM. צריך להגדיר את כותרת המארח באופן ידני כי שם המארח example.com לא בבעלותך.

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

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

    ‫cacert.pem: קובץ האישור שיצרתם. אתם צריכים לשמור את הקובץ הזה במחשב שבו אתם משתמשים כדי להתחבר לשער.

    הפלט מציג מידע מאפליקציית ההדגמה על המיקום שבו האפליקציה פועלת:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v1-84b47c7f58-pmgmk",
      "pod_name_emoji": "💇🏼‍♀️",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:31:17",
      "zone": "us-central1-a"
    }
    
  4. כדי לבדוק את ההתאמה של הנתיב, נכנסים לגרסה הגרמנית של שירות store בכתובת store.example.com/de:

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

    הפלט מאשר שהבקשה טופלה על ידי Pod של store-german:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "Gutentag!",
      "node_name": "gke-gke1-pool-2-bd121936-n3xn.c.gateway-demo-243723.internal",
      "pod_name": "store-german-5cb6474c55-lq5pl",
      "pod_name_emoji": "🧞‍♀",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:35:37",
      "zone": "us-central1-a"
    }
    
  5. שולחים תנועה לגרסת ה-canary של השירות store באמצעות כותרת ה-HTTP‏ env: canary:

    curl -H "env: canary" https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -v
    

    הפלט מאשר שהבקשה טופלה על ידי Pod של store-v2:

    {
      "cluster_name": "gke1",
      "host_header": "store.example.com",
      "metadata": "store-v2",
      "node_name": "gke-gke1-pool-2-bd121936-5pfc.c.gateway-demo-243723.internal",
      "pod_name": "store-v2-5788476cbd-s9thb",
      "pod_name_emoji": "👩🏿",
      "project_id": "gateway-demo-243723",
      "timestamp": "2022-09-25T13:38:26",
      "zone": "us-central1-a"
    }
    

פריסת שער חיצוני גלובלי

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

יצירת מפת אישורים

‫Google ממליצה להשתמש בCertificate Manager כדי לנהל אישורים כשצריך 15 אישורים או יותר לכל שער, או כשצריך להשתמש בתעודות wildcard.

אתם יכולים גם לאבטח את ה-Gateway החיצוני באמצעות סודות של Kubernetes או אישורי SSL בניהול Google. מידע נוסף זמין במאמר אבטחת שער.

בקטע הזה יוצרים אישורים באמצעות Certificate Manager כדי לאבטח את האפליקציות שפועלות באשכול.

  1. מפעילים את Certificate Manager API:

    gcloud services enable certificatemanager.googleapis.com
    
  2. יוצרים מפת אישורים:

    gcloud beta certificate-manager maps create store-example-com-map
    
  3. טוענים את האישור והמפתחות שמנוהלים על ידי Google לתוך אישור:

    gcloud beta certificate-manager certificates create store-example-com-cert \
        --certificate-file="CERTIFICATE_FILE" \
        --private-key-file="PRIVATE_KEY_FILE"
    

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

    • ‫CERTIFICATE_FILE: השם של קובץ האישור. הקובץ חייב להיות עם הסיומת .pem. לדוגמה: cert.pem.
    • ‫PRIVATE_KEY_FILE: השם של קובץ המפתח הפרטי.

    מידע נוסף זמין במאמר יצירת מפתח פרטי ואישור.

  4. יוצרים CertificateMapEntry שמקצה את האישור למפת האישורים:

    gcloud beta certificate-manager maps entries create store-example-com-map-entry \
        --map=store-example-com-map \
        --hostname=store.example.com \
        --certificates=store-example-com-cert
    

כדי ללמוד איך לאבטח שער באמצעות מקורות אחרים לאישורים, כמו סודות של Kubernetes או אישורי SSL, קראו את המאמר אבטחת שער.

יצירת שער

משאב Gateway מייצג מישור נתונים שמנתב תנועה ב-Kubernetes. שער יכול לייצג סוגים רבים ושונים של איזון עומסים וניתוב, בהתאם ל-GatewayClass שבו הוא משתמש.

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

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

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

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: external-http
      annotations:
        networking.gke.io/certmap: store-example-com-map
    spec:
      # This GatewayClass uses a global external Application Load Balancer.
      gatewayClassName: gke-l7-global-external-managed
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
    
    

    המניפסט הזה מתאר שער עם השדות הבאים:

    • ‫gatewayClassName: gke-l7-global-external-managed: מציין את ה-GatewayClass של השער הזה. במחלקה הזו של שערים משתמשים במאזן עומסים גלובלי חיצוני של אפליקציות (ALB).
    • ‫protocol: HTTPS ו-port: 443: מציינים שהשער חושף את יציאה 443 לתנועת HTTPS. השדות האלה מפעילים את TLS.
    • ‫networking.gke.io/certmap: store-example-com-map: מציין את השם של מפת האישורים ב-Certificate Manager.

    אין קטע TLS כי TLS מוגדר באמצעות Certificate Manager באמצעות ההערה networking.gke.io/certmap.

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

    kubectl apply -f gateway.yaml
    

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

  3. מוודאים שהשער נפרס בהצלחה:

    kubectl describe gateway
    

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

    Name:         external-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-global-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
     ...
    

    הפלט הזה מראה שלשער שנפרס באשכול יש מאזן עומסים וכתובת IP ציבורית. לשער אין מסלולים, ולכן הוא לא יכול לשלוח תנועה לקצוות עורפיים. בלי נתיבים, כל התנועה עוברת לקצה עורפי שמוגדר כברירת מחדל, שמחזיר תגובת HTTP 404. בקטע הבא תפרסו את Routes, שמנחה את השער לשלוח תנועה לקצוות עורפיים.

פריסת אפליקציית ההדגמה

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

למידע נוסף על פריסת אפליקציות ההדגמה, ראו פריסת אפליקציות ההדגמה.

יצירת HTTPRoute

כדי להתאים ולסנן תנועה ב-HTTP וב-HTTPS, צריך ליצור HTTPRoute.

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

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

למידע נוסף על שליחת תנועה לאפליקציה, ראו שליחת תנועה לאפליקציה.

פריסת שער אזורי חיצוני

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

יצירת רשת משנה של שרת proxy לשער האזורי

לפני שיוצרים שער שמשתמש במאזן עומסים אזורי חיצוני של אפליקציות (ALB), צריך להגדיר רשת משנה של שרתי proxy בלבד. בכל אזור של VPC שבו משתמשים במאזן עומסים חיצוני אזורי של אפליקציות (ALB), צריכה להיות תת-רשת external_managed_proxy. רשת המשנה הזו מספקת כתובות IP פנימיות לשרתי ה-proxy של מאזן העומסים.

יצירת אישור לאבטחת תנועת הלקוחות

אתם יכולים להשתמש באישור שהונפק ואומת על ידי רשות האישורים (CA) שלכם, או ליצור אישור עם חתימה עצמית. למידע נוסף על יצירת אישור, ראו אחסון אישור ב-Kubernetes Secret.

כדי לאבטח את התנועה בין הלקוחות לבין השער האזורי, אפשר להשתמש בשיטות הבאות:

  • אישורים ב-Certificate Manager שמנוהלים על ידי Google או בניהול עצמי
  • אישורי SSL אזוריים בניהול עצמי
  • סודות של Kubernetes

אישורי CertificateMap או אישורי SSL בניהול Google לא נתמכים בשערים אזוריים.

מידע נוסף זמין במאמר אישורים ומאזני עומסים ב- Google Cloud .

יצירת שער HTTP(S) חיצוני אזורי

  1. יוצרים כתובת IP סטטית אזורית למאזן העומסים החיצוני.

    gcloud compute addresses create IP_ADDRESS_NAME \
      --region=COMPUTE_REGION \
      --network-tier=STANDARD
    

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

    • ‫IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה.
    • ‫COMPUTE_REGION: האזור ב-Compute Engine שבו פועל האשכול.
  2. כדי ליצור שער של מאזן עומסים חיצוני אזורי של אפליקציות (ALB) באמצעות אישור בניהול עצמי, פועלים לפי השלבים הבאים ושומרים את המניפסט בתור regional-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: external-regional-http
      spec:
        # Name of an existing GatewayClass.
        gatewayClassName: gke-l7-regional-external-managed
        # Listen for HTTPS traffic on port 443
        listeners:
        - name: https
          protocol: HTTPS
          port: 443
          tls:
            # Terminate the TLS session with the client at the Gateway.
            mode: Terminate
            # Certificates for the Gateway to use to create a new TLS session.
            certificateRefs:
            - name: store-example-com
        # The name of the static IP address of the external load balancer.
        # You can also use the `IPAddress` type to specify the actual IP address.
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
    
  3. מחילים את המניפסט regional-gateway:

      kubectl apply -f regional-gateway.yaml
    
  4. צריך לאמת את ההגדרות.

      kubectl get gateway
    

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

    NAME            CLASS                              ADDRESS         READY   AGE
    external-http   gke-l7-regional-external-managed   35.118.32.224   True    49s
    

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

    kubectl describe gateway
    

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

    Name:         external-regional-http
    Namespace:    default
    Labels:       <none>
    ...
    Spec:
      Gateway Class Name:  gke-l7-regional-external-managed
      Listeners:
        Allowed Routes:
          Namespaces:
            From:  Same
        Name:      https
        Port:      443
        Protocol:  HTTPS
        Tls:
          Certificate Refs:
            Group:
            Kind:   Secret
            Name:   store-example-com
          Mode:     Terminate
      ...
    

פריסת אפליקציית ההדגמה

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

למידע נוסף על פריסת אפליקציות ההדגמה, ראו פריסת אפליקציות ההדגמה.

יצירת HTTPRoute

כדי להתאים ולסנן תנועה ב-HTTP וב-HTTPS, צריך ליצור HTTPRoute.

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

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

למידע נוסף על שליחת תנועה לאפליקציה, ראו שליחת תנועה לאפליקציה.

שימוש בשערים משותפים

ב-Gateway API נעשה שימוש במשאבים נפרדים, משאבי Gateways ומשאבי Route, כדי לפרוס מאזני עומסים וכללי מסלול. זה שונה מ-Ingress, שמשלב את הכול במשאב אחד. על ידי פיצול האחריות בין המשאבים, Gateway מאפשר לפרוס את מאזן העומסים ואת כללי המסלול שלו בנפרד, ועל ידי משתמשים או צוותים שונים. כך אפשר להפוך את השערים לשערים משותפים שמחוברים להרבה נתיבים שונים, שיכולים להיות בבעלות מלאה של צוותים עצמאיים ובניהולם, אפילו במרחבי שמות שונים.

פריסת נתיבים מול שער משותף

הדוגמה הזו מבוססת על השער של internal-http שנפרס בפריסת שער פנימי.

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

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

    kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yaml
    
  2. שומרים את המניפסט הבא בקובץ בשם site-route-internal.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: site-internal
    spec:
      # Attach the HTTPRoute to the `internal-http` Gateway.
      parentRefs:
      - kind: Gateway
        name: internal-http
      # Route requests that have `site.example.com` in the Host header.
      hostnames:
      - "site.example.com"
      # Send all requests to the `site-v1` Service.
      rules:
      - backendRefs:
        - name: site-v1
          port: 8080
    

    המניפסט הזה מתאר HTTPRoute שתואם לכל התנועה של site.example.com ומנתב אותה לשירות site-v1.

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

    kubectl apply -f site-route-internal.yaml
    
  4. מוודאים שה-HTTPRoute מצורף ל-Gateway:

    kubectl describe httproute.gateway.networking.k8s.io site-internal
    

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

    Status:
      Parents:
        Conditions:
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                Accepted
          Status:                True
          Type:                  Accepted
          Last Transition Time:  2023-01-09T15:05:43Z
          Message:
          Reason:                ReconciliationSucceeded
          Status:                True
          Type:                  Reconciled
        Controller Name:         networking.gke.io/gateway
        Parent Ref:
          Group:  gateway.networking.k8s.io
          Kind:   Gateway
          Name:   internal-http
          ...
    

    אם התנאי Accepted של השער הוא True, ה-HTTPRoute נקשר בהצלחה לשער. למידע נוסף על השדה Status, קראו את המאמר סטטוס המסלול.

  5. מוודאים שהתנועה לשער מנותבת בצורה נכונה:

    curl -H "host: site.example.com" GATEWAY_IP_ADDRESS
    curl -H "host: store.example.com" GATEWAY_IP_ADDRESS
    

    מחליפים את GATEWAY_IP_ADDRESS בכתובת ה-IP של השער הפנימי.

    צריך להשתמש במכונה וירטואלית (VM) באותו VPC כמו השער.

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

    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "site.example.com",
      "metadata": "site-v1",
      "pod_name": "site-v1-5d64fc4d7d-fz6f6",
      "pod_name_emoji": "👩🏼‍🍳",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    ...
    {
      "cluster_name": "CLUSTER_NAME",
      "host_header": "store.example.com",
      "metadata": "store-v1",
      "pod_name": "store-v1-6d8d58d78-vz8pn",
      "pod_name_emoji": "🧝🏻‍♂️",
      "project_id": "PROJECT_ID",
      "timestamp": "2022-11-02T19:07:01",
      "zone": "ZONE_NAME"
    }
    

    הפלט הזה מציין שבקשות עם כותרת המארח site.example.com מגיעות לשירות site-v1, ובקשות עם כותרת המארח store.example.com מגיעות לשירות store-v1.

הגדרת מסלול הרשת

כדי לציין את מסלול הרשת של כתובת המאזין של מאזן עומסים חיצוני אזורי של אפליקציות (ALB), משתמשים בשדה type במערך addresses[] שבהגדרת השער. אם לא מציינים מסלול רשת, כברירת מחדל מוגדרת לשער כתובת IP זמנית במסלול הרגיל.

משתמשים בערכים הבאים בשדה type:

  • ‫networking.gke.io/premium-ephemeral-ipv4-address: מקצה כתובת IP של מסלול פרימיום.
  • ‫networking.gke.io/standard-ephemeral-ipv4-address: מקצה כתובת IP במסלול הרגיל.

כדי להקצות כתובות IP משני מסלולי הרשת, צריך לציין את שני הסוגים בשדה addresses.

בדוגמה הבאה מוסבר איך מקצים כתובת IP במסלול פרימיום לשער. Google Cloud כדי להקצות כתובת IP במסלול הרגיל, משתמשים ב-networking.gke.io/standard-ephemeral-ipv4-address.

  1. שומרים את המניפסט לדוגמה הבא בתור external-regional-http.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: external-regional-http
    spec:
      # Name of an existing GatewayClass.
      gatewayClassName: gke-l7-regional-external-managed
      # Listen for HTTPS traffic on port 443.
      listeners:
      - name: https
        protocol: HTTPS
        port: 443
        tls:
          # Terminate the TLS session with the client at the Gateway.
          mode: Terminate
          # Certificates for the Gateway to use to create a new TLS session.
          certificateRefs:
          - name: store-example-com
        addresses:
        # Request a Premium Tier ephemeral IPv4 address for the Gateway.
        - type: networking.gke.io/premium-ephemeral-ipv4-address
    
  2. מחילים את המניפסט לדוגמה:

    kubectl apply -f external-regional-http.yaml
    

הגדרת הקצה העורפי שמוגדר כברירת מחדל של השער

כל ה-GatewayClasses של gke-l7-* מחזירים HTTP 404 לתנועה שלא תואמת. אפשר להגדיר את ברירת המחדל של הקצה העורפי באמצעות נתיב ברירת מחדל מפורש, ששולח תנועה לא תואמת לשירות שסופק על ידי המשתמש.

שערי הגישה מוגדרים לטפל בקודי שגיאה כמו 404 (לא נמצא) ו-500 (שגיאה בחיבור לשרת), גם בלי הגדרות מפורשות של קצה עורפי. התנהגות ברירת המחדל עשויה להשתנות בין הטמעות של Gateway. כדי לשלוט טוב יותר בטיפול בשגיאות, כדאי להגדיר קצוות עורפיים בהתאמה אישית.

ה-HTTPRoute הבא הוא דוגמה להתאמה אישית של ברירת המחדל של הקצה העורפי. אם תפעילו HTTPRoute שדומה לזה שבהמשך, הוא יקבל עדיפות על פני ברירת המחדל של הקצה העורפי המשתמע:

kind: HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: custom-default-backend
spec:
  parentRefs:
  - kind: Gateway
    name: my-internal-gateway
  # Omit the `hostnames` field to route all unmatched traffic from the
  # attached Gateway.
  rules:
  - backendRefs:
    - name: my-custom-default-backend-service
      port: 8080

ה-HTTPRoute הזה תואם לכל התנועה משער מסוים. אפשר להגדיר רק כלל אחד כזה לכל שער, אחרת הכללים מתנגשים וסדר הקדימויות חל.

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

הגדרת כתובת IP סטטית לשער

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

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

kind: Gateway
...
status:
  addresses:
    - value: 10.15.32.3

בהתאם ל-GatewayClass, כתובת ה-IP מוקצית מרשתות המשנה הבאות:

GatewayClasses מאגר ברירת המחדל של כתובות ה-IP
  • gke-l7-rilb
  • gke-l7-rilb-mc
  • כתובות IP פרטיות אזוריות מטווח כתובות ה-IPv4/IPv6 של הצומת הראשי
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
  • כתובות IP ציבוריות אזוריות מטווחי IPv4/IPv6 החיצוניים האזוריים של Google
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
  • כתובות IP ציבוריות גלובליות מטווחי IPv4/IPv6 החיצוניים הגלובליים של Google

    בשדה addresses.NamedAddress אפשר לציין כתובת IP בלי קשר לשער. אפשר ליצור משאב של כתובת IP סטטית לפני פריסת השער, והמשאב יופנה על ידי NamedAddress. אתם יכולים להשתמש שוב בכתובת ה-IP הסטטית גם אם מחקתם את השער.

    שימוש בכתובת IP עם שם

    אפשר להגדיר כתובת IPv4 או IPv6 על ידי ציון NamedAddress. צריך להקצות כתובת IP סטטית לפני שיוצרים שער.

    1. יוצרים משאב של כתובת IP סטטית:

      gcloud compute addresses create IP_ADDRESS_NAME \
          --purpose=SHARED_LOADBALANCER_VIP \
          --region=COMPUTE_REGION \
          --subnet=SUBNET \
          --project=PROJECT_ID
      

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

      • ‫IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה
      • ‫COMPUTE_REGION: לשערי גישה אזוריים, האזור ב-Compute Engine שבו פועל האשכול. הדגל הזה לא נדרש לשערי גישה גלובליים וחיצוניים.
      • ‫SUBNET: רשת המשנה של כתובת ה-IP. הדגל הזה לא נדרש לשערי API גלובליים וחיצוניים.
      • ‫PROJECT_ID: הפרויקט שבו פועל אשכול GKE.
    2. שומרים את המניפסט הבא בקובץ בשם named-ip-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: internal-http
      spec:
        gatewayClassName: gke-l7-rilb
        listeners:
        - name: http
          protocol: HTTP
          port: 80
        addresses:
        - type: NamedAddress
          value: IP_ADDRESS_NAME
      

      המניפסט הזה מתאר שער שמפנה לכתובת ה-IP שצוינה.

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

      kubectl apply -f named-ip-gateway.yaml
      
    4. אימות כתובת ה-IP של השער:

      kubectl describe gateway internal-http
      

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

      Name:         internal-http
      Namespace:    default
      Labels:       <none>
      ...
      Spec:
        Addresses:
          Type:              NamedAddress
          Value:             IP_ADDRESS_NAME
        Gateway Class Name:  gke-l7-rilb
        Listeners:
          Allowed Routes:
            Namespaces:
              From:  Same
          Name:      http
          Port:      80
          Protocol:  HTTP
      Status:
        Addresses:
          Type:   IPAddress
          Value:  10.15.32.103
      

    הגדרת הפניות אוטומטיות מ-HTTP ל-HTTPS

    ב-Cloud Load Balancing יש פונקציונליות של הפניה אוטומטית מ-HTTP ל-HTTPS. מאזן עומסים חיצוני של אפליקציות (ALB) מפנה בקשות HTTP לא מוצפנות למאזן עומסים ב-HTTPS שמשתמש באותה כתובת IP. כשיוצרים שער עם הפניות אוטומטיות מ-HTTP ל-HTTPS, שני מאזני העומסים האלה נוצרים באופן אוטומטי. בקשות לכתובת ה-IP החיצונית של השער ביציאה 80 מופנות אוטומטית לאותה כתובת IP חיצונית ביציאה 443.

    כברירת מחדל, הפניות אוטומטיות מ-HTTP ל-HTTPS לא מוגדרות בשער.

    כדי להפנות אוטומטית תנועת HTTP ל-HTTPS, מגדירים שער שיטפל גם בתנועת HTTP וגם בתנועת HTTPS. אם משביתים את HTTP או את HTTPS, השער לא מפנה את התנועה.

    בדוגמה הבאה מוסבר איך להשתמש בהפניה אוטומטית מ-HTTP ל-HTTPS כדי לוודא שהתנועה מהלקוחות לאפליקציות האינטרנט תמיד מופנית לדף מאובטח.

    הפניות אוטומטיות מ-HTTP ל-HTTPS לא נתמכות ב-GatewayClasses‏ gke-l7-gxlb ו-gke-l7-gxlb-mc. למידע נוסף על התכונות השונות שנתמכות בכל GatewayClass, קראו את המאמר יכולות של GatewayClass.

    שימו לב שהקטע hostnames ב-HTTPRoute הוא אופציונלי. כדי ליצור הפניה אוטומטית כוללת לכל שמות המארחים ביציאת HTTP ספציפית, אפשר להשמיט את הקטע hostnames. בנוסף, אפשר להשתמש בהפניה אוטומטית עם תו כללי לחיפוש, לדוגמה:

    ...
    hostnames:
    - "*.example.com" # Matches all subdomains of example.com
    ...
    

    הפניית תנועת HTTP ממרחב שמות של תשתית

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

    בדוגמה הבאה מוצגת הגבלה נוספת על השימוש במאזין ה-HTTP, כדי למנוע שימוש לא מכוון בפרוטוקול לא מאובטח מצד צוותי האפליקציה. בדוגמה הזו, השער מוגדר כך ש-HTTPRoute יוכל להשתמש במאזין ה-HTTP רק אם המסלול נמצא במרחב שמות עם התווית otherInfra: httpToHttps. עם זאת, השער מאפשר ל-HTTPRoutes בכל מרחב שמות להשתמש במאזין ה-HTTPS. אתם יכולים להגביל את מרחב השמות http-redirect באמצעות Kubernetes RBAC, כדי שצוותי האפליקציות לא יוכלו ליצור HTTPRoute במרחב השמות הזה בטעות.

    1. יוצרים את מרחב השמות של השער. שומרים את המניפסט בשם gateway-namespace.yaml:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: gateway-infra
      
    2. מחילים את המניפסט:

      kubectl apply -f gateway-namespace.yaml
      
    3. יוצרים את מרחב השמות של השער ושומרים את המניפסט בתור redirect-namespace.yaml:

      apiVersion: v1
      kind: Namespace
      metadata:
        name: http-redirect
        labels:
          otherInfra: httpToHttps
      

      למרחב השמות http-redirect יש את התווית otherInfra: httpToHttps.

    4. מחילים את המניפסט:

      kubectl apply -f redirect-namespace.yaml
      
    5. כדי להגביל את השימוש במאזין ה-HTTP, יוצרים שער באמצעות המניפסט הבא. שומרים את המניפסט בתור external-gateway.yaml:

      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: external-http
        namespace: gateway-infra
      spec:
        # Name of an existing GatewayClass.
        gatewayClassName: gke-l7-global-external-managed
        listeners:
        - name: http
          protocol: HTTP
          port: 80
          #  Allow only HTTPRoutes from namespaces that have the
          # `otherInfra: httpToHttps` label to use this listener.
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: Selector
              selector:
                matchLabels:
                  otherInfra: httpToHttps
        - name: https
          protocol: HTTPS
          port: 443
          # Allow HTTPRoutes from any namespace to use this listener.
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
            namespaces:
              from: All
          tls:
            mode: Terminate
            options:
              networking.gke.io/pre-shared-certs: store-example-com
      
      • השדה namespace מציין שהשער נוצר במרחב השמות gateway-infra.

      • השדה namespaces בקטע allowedRoutes מגביל את מאזין ה-HTTP למרחב השמות שתואם לתווית otherInfra: httpToHttps.

    6. מחילים את המניפסט:

      kubectl apply -f external-gateway.yaml
      
    7. כדי לאלץ את ההפניה האוטומטית ל-HTTPS, יוצרים HTTPRoute שמוגדר כברירת מחדל באמצעות המניפסט הבא. שומרים את המניפסט בשם http-redirect.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: redirect
        # Create the HTTPRoute in the `http-redirect` namespace.
        namespace: http-redirect
      spec:
        # Attach the HTTPRoute to the `http` listener in the `external-http`
        # Gateway.
        parentRefs:
        - namespace: gateway-infra
          name: external-http
          sectionName: http
        rules:
        # Respond to the request with an HTTPS redirection.
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
      
      • השדה sectionName מורה לשער להתאים רק למאזין ה-HTTP. המסנן RequestRedirect מאלץ את ההפניה ל-https listener.
    8. מחילים את המניפסט:

      kubectl apply -f http-redirect.yaml
      
    9. יוצרים שירות לאפליקציה באמצעות המניפסט הבא. שומרים את המניפסט בתור service-deployment.yaml:

      apiVersion: v1
      kind: Service
      metadata:
        name: store-v1
      spec:
        selector:
          app: store
          version: v1
        ports:
        - port: 8080
          targetPort: 8080
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: store-v1
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: store
            version: v1
        template:
          metadata:
            labels:
              app: store
              version: v1
          spec:
            containers:
            - name: whereami
              image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
              ports:
              - containerPort: 8080
              env:
              - name: METADATA
                value: "store-v1"
      
    10. מחילים את המניפסט:

      kubectl apply -f service-deployment.yaml
      
    11. יוצרים HTTPRoute לאפליקציה שמאפשרת רק HTTPS באמצעות המניפסט הבא. שומרים את המניפסט בשם http-route.yaml:

      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: store-external
        labels:
          gateway: external-http
      spec:
        # Attach the HTTPRoute to the HTTPS listener in the `external-http`
        # Gateway.
        parentRefs:
        - name: external-http
          namespace: gateway-infra
          sectionName: https
        # Match requests that have the `store.example.com` Host header.
        hostnames:
        - "store.example.com"
        # Route requests to the `store-v1` Service.
        rules:
        - backendRefs:
          - name: store-v1
            port: 8080
      
    12. מחילים את המניפסט:

      kubectl apply -f http-route.yaml
      

    הגדרת הפניות אוטומטיות של נתיבים ושכתובים של כתובות URL

    הפניות אוטומטיות של נתיבים כוללות הפניה אוטומטית של בקשה נכנסת מנתיב אחד של כתובת URL לנתיב אחר. הפניות לכתובות URL מאפשרות לשנות את המבנה של כתובת ה-URL כשצריך לטפל בכתובות URL מיושנות או שהוצאו משימוש.

    שכתוב כתובות URL עוזר לשנות את כתובת ה-URL הנכנסת לפני העיבוד שלה בשרת. הוא מאפשר לשנות את המבנה או הפורמט של כתובת ה-URL בלי לשנות את התוכן או את מבנה הקובץ. כתיבה מחדש של כתובות URL עוזרת ליצור כתובות URL ידידותיות למשתמש ול-SEO, שקל לזכור ולהבין. כברירת מחדל, הפניות אוטומטיות של נתיבים ושכתובים של כתובות URL לא מוגדרים, וצריך להגדיר אותם באופן מפורש באמצעות מסנן ב-HTTPRoute.

    ‫GKE Gateway תומך בהפניות אוטומטיות של נתיבים ובשכתובים של כתובות URL. מידע נוסף זמין במאמר הפניות אוטומטיות ושכתובים של נתיבי HTTP.

    הגדרת הפניות אוטומטיות של נתיבים

    אפשר להגדיר הפניות אוטומטיות של נתיבים כך שיחליפו את כל הנתיב או רק את הקידומת בכתובת ה-URL.

    החלפת כל הנתיב

    1. כדי להחליף נתיב שלם, מגדירים מסנן ב-HTTPRoute שמחליף כל כתובת URL שמכילה את הקידומת /any-path בנתיב כתובת ה-URL בערך המחמיר /new-path.

    2. יוצרים מניפסט של HTTPRoute באופן הבא ונותנים לו את השם store.yaml:

        apiVersion: gateway.networking.k8s.io/v1
        kind: HTTPRoute
        metadata:
          name: store
        spec:
          parentRefs:
          - kind: Gateway
            name: external-http
          hostnames:
          - store.example.com
          rules:
          - matches:
            - path:
                # Match requests by a prefix, like `/any-path` and `/any-path/home`.
                type: PathPrefix
                value: /any-path
            filters:
            - type: RequestRedirect
              requestRedirect:
                path:
                  # Replace the full path with `/new-path`. For example, both
                  # `/any-path/home` and `/any-path` become `/new-path`.
                  type: ReplaceFullPath
                  replaceFullPath: /new-path
                statusCode: 302
      

      לדוגמה, המניפסט הזה מגדיר כלל ניתוב ל-HTTPRoute באופן הבא: כל מסלול לכתובת ה-URL‏ https://store.example.com/any-path/... צריך להיות מופנה למיקום חדש, https://store.example.com/new-path/ (מחמיר).

    3. מחילים את המניפסט:

      kubectl apply -f store.yaml
      

    כלל מסלול זה פועל לפי כלל הפניה אוטומטית מחמיר, כלומר הדפדפן לא מנסה לשמור במטמון את ההפניה האוטומטית, אלא מפנה אוטומטית לגרסה העדכנית.

    החלפת קידומת בלבד

    1. כדי להחליף רק קידומת, מגדירים מסנן ב-HTTPRoute שמחליף כל כתובת URL שמכילה את הקידומת /any-prefix בנתיב כתובת ה-URL בערך המדויק /new-prefix.

    2. יוצרים מניפסט של HTTPRoute באופן הבא ונותנים לו את השם store.yaml:

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
        - matches:
            - path:
                # Match requests by prefix, like `/any-prefix` and
                # `/any-prefix/home`.
                type: PathPrefix
                value: /any-prefix
          filters:
          - type: RequestRedirect
            requestRedirect:
              path:
                # Replace the matched prefix with `/new-prefix`. For example,
                # `/any-prefix` becomes `/new-prefix` and `/any-prefix/home`
                # becomes `/new-prefix/home`.
                type: ReplacePrefixMatch
                replacePrefixMatch: /new-prefix
              statusCode: 302
      

      לדוגמה, המניפסט הזה מגדיר כלל ניתוב ל-HTTPRoute באופן הבא: כל מסלול לכתובת ה-URL https://store.example.com/any-path/v1/... צריך להיות מופנה למיקום חדש, https://store.example.com/new-path/v1/... (בלבד).

    3. מחילים את המניפסט:

        kubectl apply -f store.yaml
      

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

    הגדרת שכתובים של כתובות URL

    אפשר להגדיר שכתובות URL ייכתבו מחדש כדי לשנות את האופן שבו הן מוצגות למשתמשים. אתם יכולים להשתמש בשכתוב כתובות URL כדי להפוך את כתובות ה-URL לידידותיות יותר למשתמש, לשפר את ה-SEO או להפנות את המשתמשים לדף חדש.

    שכתוב של כל שם המארח

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

    1. מגדירים מסנן ב-HTTPRoute שמורה לשער להחליף את המידע של Host בכותרת הבקשה מ-www.example.com ל-store.example.com לפני העברת הבקשה לשירות לקצה העורפי.

    2. יוצרים מניפסט של HTTPRoute באופן הבא ונותנים לו את השם www.yaml:

        apiVersion: gateway.networking.k8s.io/v1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - filters:
            - type: URLRewrite
              # Replace the hostname in the URL with `store.example.com`.
              urlRewrite:
                hostname: store.example.com
            backendRefs:
            - name: store-v1
              port: 8080
      

      לדוגמה, בהגדרה שלמעלה, כל בקשה ל-https://www.example.com מועברת לשירות לקצה העורפי עם הכותרת Host: store.example.com, במקום Host: www.example.com.

    3. מחילים את המניפסט:

        kubectl apply -f www.yaml
      

    שכתוב באמצעות משני נתיבים

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

    כדי לשכתב באמצעות משתני נתיב:

    1. מגדירים מסנן ב-HTTPRoute שמורה לשער להחליף את המידע של Host בכותרת הבקשה מ-www.example.comto store.example.com, ולהחליף את הערך /store ב-/ לפני העברת הבקשה לשירות לקצה העורפי.

    2. יוצרים מניפסט של HTTPRoute באופן הבא ונותנים לו את השם www.yaml:

        apiVersion: gateway.networking.k8s.io/v1
        kind: HTTPRoute
        metadata:
          name: www
        spec:
          parentRefs:
            - kind: Gateway
              name: external-http
          hostnames:
          - www.example.com
          rules:
          - matches:
            - path:
                type: PathPrefix
                value: /store
            filters:
            - type: URLRewrite
              # For URLs that have `/store` in the path, replace the hostname with
              # store.example.com and replace the `/store` prefix with `/de`.
              urlRewrite:
                hostname: store.example.com
                path:
                  type: ReplacePrefixMatch
                  replacePrefixMatch: /de
            backendRefs:
            - name: store-german
              port: 8080
      

      לדוגמה, בהגדרה שלמעלה, כל בקשה ל-https://www.example.com/store/... מועברת לשירות לקצה העורפי עם Host: store.example.com ב-request header (במקום Host: www.example.com), וה-/store נכתב מחדש כ-/de.

    3. מחילים את המניפסט:

      kubectl apply -f www.yaml
      

    שכתוב באמצעות ביטויים רגולריים

    אתם יכולים להשתמש במשאב GCPHTTPFilter עם spec.urlRewrite.regexModifier כדי לשכתב נתיבי כתובות URL באמצעות ביטויים רגולריים, לפני העברת הבקשה לשירות לקצה העורפי.

    כדי לשכתב נתיב כתובת ה-URL באמצעות ביטוי רגולרי:

    1. שומרים את המניפסט הבא בתור store-regex-rewrite-filter.yaml:

      apiVersion: networking.gke.io/v1
      kind: GCPHTTPFilter
      metadata:
        name: store-regex-rewrite-filter
      spec:
        urlRewrite:
          regexModifier:
            pathPattern: /service1/
            pathSubstitution: /service2/
      

      המניפסט הזה מתאר GCPHTTPFilter עם המאפיינים הבאים:

      • ‫urlRewrite.regexModifier: מגדיר שכתוב של נתיב כתובת ה-URL באמצעות ביטויים רגולריים.
      • ‫pathPattern: מציין את הביטוי הרגולרי RE2 שתואם לנתיב כתובת ה-URL של הבקשה, כמו /service1/([a-zA-Z0-9]+).
      • ‫pathSubstitution: מציין את מחרוזת ההחלפה שמחליפה את נתיב כתובת ה-URL התואם, שיכולה להפנות לקבוצות לחילוץ ממוספרות מ-pathPattern, כמו /service2/\1.
    2. מחילים את המניפסט על האשכול:

      kubectl apply -f store-regex-rewrite-filter.yaml
      
    3. שומרים את המניפסט הבא בתור www-regex-rewrite.yaml:

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: www-regex-rewrite
      spec:
        parentRefs:
        - kind: Gateway
          name: external-http
        hostnames:
        - www.example.com
        rules:
        - matches:
          - path:
              type: PathPrefix
              value: /service1/
          filters:
          - type: ExtensionRef
            extensionRef:
              group: networking.gke.io
              kind: GCPHTTPFilter
              name: store-regex-rewrite-filter
          backendRefs:
          - name: store-v1
            port: 8080
      

      המניפסט הזה מתאר HTTPRoute עם המאפיינים הבאים:

      • ‫extensionRef: מפנה אל store-regex-rewrite-filter GCPHTTPFilter שנוצר בשלב הקודם.
      • ‫backendRefs: מעביר את הבקשה שנכתבה מחדש אל store-v1 Service. לדוגמה, בקשה ל-https://www.example.com/service1/item123 נכתבת מחדש ל-/service2/item123 לפני שהיא מועברת לשירות לקצה העורפי store-v1.
    4. מחילים את המניפסט על האשכול:

      kubectl apply -f www-regex-rewrite.yaml
      

    אימות ההגדרות את ההגדרות

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

    kubectl get httproute www -o yaml
    

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

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        annotations:
          kubectl.kubernetes.io/last-applied-configuration: |
            {"apiVersion":"gateway.networking.k8s.io/v1","kind":"HTTPRoute","metadata":{"annotations":{},"name":"www","namespace":"default"},"spec":{"hostnames":["www.example.com"],"parentRefs":[{"kind":"Gateway","name":"external-http"}],"rules":[{"backendRefs":[{"name":"store-german","port":8080}],"filters":[{"type":"URLRewrite","urlRewrite":{"hostname":"store.example.com","path":{"replacePrefixMatch":"/de","type":"ReplacePrefixMatch"}}}],"matches":[{"path":{"type":"PathPrefix","value":"/store"}}]}]}}
        creationTimestamp: "2023-06-22T01:00:42Z"
        generation: 3
        name: www
        namespace: default
        resourceVersion: "51268631"
        uid: e516493e-806d-44d6-ae0d-1c9ff25682cf
      spec:
        hostnames:
        - www.example.com
        parentRefs:
        - group: gateway.networking.k8s.io
          kind: Gateway
          name: external-http
        rules:
        - backendRefs:
          - group: ""
            kind: Service
            name: store-german
            port: 8080
            weight: 1
          filters:
          - type: URLRewrite
            urlRewrite:
              hostname: store.example.com
              path:
                replacePrefixMatch: /de
                type: ReplacePrefixMatch
          matches:
          - path:
              type: PathPrefix
              value: /store
      status:
        parents:
        - conditions:
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: Accepted
            status: "True"
            type: Accepted
          - lastTransitionTime: "2023-06-22T01:11:26Z"
            message: ""
            observedGeneration: 2
            reason: ReconciliationSucceeded
            status: "True"
            type: Reconciled
          controllerName: networking.gke.io/gateway
          parentRef:
            group: gateway.networking.k8s.io
            kind: Gateway
            name: external-http
    
    

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

    kubectl describe httproute
    

    הגדרת שיתוף משאבים ממקורות שונים (CORS)

    שיתוף משאבים בין מקורות (CORS) הוא מנגנון אבטחה שמאפשר לאפליקציות אינטרנט שפועלות במקור (דומיין) אחד לגשת באופן מאובטח למשאבים שמתארחים במקור אחר.

    אתם יכולים להגדיר כללי מדיניות CORS ישירות במשאבי HTTPRoute באמצעות המסנן CORS. הגישה הזו מאפשרת למאזן העומסים להוסיף את כותרות התגובה המתאימות של CORS ולטפל בבקשות קדם-הפעלה (OPTIONS) של CORS, וכך להסיר את האחריות הזו משירותי הקצה העורפי.

    הגדרת מדיניות CORS

    בדוגמה הבאה מוצג HTTPRoute שמוגדר עם מסנן CORS שמאפשר בקשות ממקורות שונים מ-https://www.example.com לשיטות ולכותרות ספציפיות:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: route-with-cors
      namespace: default
    spec:
      parentRefs:
      - name: my-gateway
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /api
        backendRefs:
        - name: my-backend
          port: 8080
        filters:
        - type: CORS
          cors:
            allowOrigins:
            - "https://www.example.com"
            allowMethods:
            - GET
            - POST
            - DELETE
            allowHeaders:
            - "x-request-header-1"
            - "x-request-header-2"
            exposeHeaders:
            - "x-response-header-a"
            - "x-response-header-b"
            allowCredentials: true
            maxAge: 3600
    

    בלוק ההגדרות האישיות cors תומך בשדות הבאים:

    • ‫allowOrigins: רשימה של מקורות מורשים. יש תמיכה בפרוטוקולים http ו-https. אפשר לציין את המקורות האלה בפורמטים הבאים:
      • מקורות מפורשים (לדוגמה, https://www.example.com).
      • תו כללי לחיפוש (*) שכולל את כל המקורות. אם משתמשים בתו הכללי הזה, אי אפשר לציין מקורות אחרים. מטעמי אבטחה, אנחנו ממליצים מאוד לא לשלב את התו הכללי לחיפוש עם ההגדרה allowCredentials (למידע נוסף, אפשר לעיין בהגדרה של השדה הבא).
      • תבניות של תווים כלליים לחיפוש (לדוגמה, https://*.domain.com). התו הכללי לחיפוש * חייב להופיע מיד אחרי הסכימה (http:// או https://) ואחריו חייבת להופיע נקודה (לדוגמה, http://*.domain.com), יציאה (לדוגמה, https://*:4433) או שהוא חייב להיות התו האחרון (לדוגמה, http://*).
    • ‫allowMethods: השיטות של HTTP שמותרות לבקשות CORS. תומך בתו הכללי לחיפוש (*) כדי לאפשר את כל השיטות. אם משתמשים בתו הכללי, אי אפשר לציין שיטות אחרות.
    • ‫allowHeaders: כותרות ה-HTTP שהלקוחות יכולים לשלוח. תומך בתו הכללי לחיפוש (*) כדי לאפשר את כל הכותרות. אם משתמשים בתו הכללי לחיפוש, אי אפשר לציין כותרות אחרות.
    • ‫exposeHeaders: כותרות ה-HTTP שאפשר לחשוף לסקריפט של הלקוח. תומך בתו הכללי לחיפוש (*) כדי לחשוף את כל הכותרות.
    • ‫allowCredentials: קובע אם הדפדפן יכול לשתף את תגובת השרת לבקשות שנשלחות במצב עם פרטי כניסה, כמו בקשות שמכילות קובצי Cookie או אימות HTTP. ערך ברירת המחדל הוא false. כשאתם קובעים את ההגדרה הזו, כדאי להביא בחשבון את היבטי האבטחה הבאים:
      • אם מציינים את התו הכללי לחיפוש * כערך של אחד מהשדות allowMethods,‏ allowHeaders או exposeHeaders, הדפדפן חוסם את התגובה לבקשה במצב עם פרטי כניסה. החסימה הזו מתרחשת גם אם הערך של השדה allowCredentials מוגדר כ-true מטעמי אבטחה.
      • כשהשדה allowOrigins מכיל את התו הכללי לחיפוש *, בקר השער של GKE לא מעתיק באופן מילולי את התו הכללי לחיפוש * מהשדה allowOrigins לכותרות התגובה. כתוצאה מכך, הדפדפן לא יחסום תגובה כזו לבקשה במצב עם פרטי כניסה, ויאפשר לכל אתר שעלול להיות זדוני לגשת לנתוני המשתמשים. לכן, אנחנו ממליצים מאוד לא להגדיר את ההגדרות הבאות: allowCredentials: true ו-allowOrigins עם התו הכללי לחיפוש *.
    • ‫maxAge: מציין כמה זמן (בשניות) הדפדפן יכול לשמור במטמון את התגובה לבדיקה המקדימה. ברירת המחדל היא 5 שניות. הערך חייב להיות 1 או יותר.

    מגבלות

    • שערים של אשכול יחיד בלבד: אין תמיכה ב-CORS לשערים של כמה אשכולות.
    • חוסר תאימות עם RequestRedirect: אי אפשר להשתמש במסנן CORS ובמסנן RequestRedirect באותו כלל מסלול.
    • מגבלות על ביטויים רגולריים: בקר השער של GKE מייצג באופן פנימי תבניות של תווים כלליים לחיפוש בערך של השדה allowOrigins כביטויים רגולריים. יש מגבלות על השימוש בביטויים רגולריים, שמשפיעות על GatewayClasses באופן הבא:
      • ב-GatewayClass של gke-l7-global-external-managed, אפשר להשתמש רק בביטוי רגולרי אחד לכל מאזין של Gateway (שמשותף עם תכונות אחרות). המגבלה הזו כפופה לכללי ספירה כפולה, כלומר אי אפשר לשלב תבנית של תו כללי לחיפוש עם התאמה של PathPrefix.
      • ב-GatewayClasses מסוג gke-l7-regional-external-managed ו-gke-l7-rilb, אפשר להשתמש בעד חמישה ביטויים רגולריים לכל שם מארח (שמשותף עם תכונות אחרות).
      • התו הכללי לחיפוש (*) לא נכלל במגבלות האלה.
      • תבנית אחת של תו כללי לחיפוש במסנן CORS יכולה להיספר כמה פעמים במגבלה של הביטויים הרגולריים. בקר השער של GKE מכפיל מסנן CORS בכלל HTTPRoute במספר ההתאמות באותו כלל. בנוסף, התאמה מסוג PathPrefix נספרת פעמיים, אלא אם הנתיב הוא /.

    למידע נוסף על ההתנהגות הרגילה של CORS ב-Gateway API, קראו את המדריך למשתמש של CORS.

    הגדרת כותרות מותאמות אישית של בקשות ותגובות

    כותרות מותאמות אישית של בקשות ותגובות מאפשרות לכם לציין כותרות נוספות לבקשות ולתגובות HTTP(S). בהתאם למידע שזוהה על ידי מאזן העומסים, הכותרות האלה יכולות לכלול את המידע הבא:

    • זמן האחזור ללקוח
    • המיקום הגיאוגרפי של כתובת ה-IP של הלקוח
    • הפרמטרים של חיבור ה-TLS

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

    כדי להגדיר כותרות בהתאמה אישית, מוסיפים קטע של מסנן לכללים של HTTPRoute, באופן הבא:

    הגדרת כותרות של בקשות בהתאמה אישית

    יוצרים מניפסט של HTTPRoute עם מסנן RequestHeaderModifier ושומרים אותו בשם http-route-request.yaml:

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        <...>
        rules:
            filters:
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  <...>
    

    מחילים את המניפסט:

      kubectl apply -f http-route-request.yaml
    

    הגדרת כותרות תגובה בהתאמה אישית

    יוצרים מניפסט של HTTPRoute עם מסנן ResponseHeaderModifier ושומרים אותו בשם http-route-response.yaml:.

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: store
    spec:
      <...>
      rules:
          filters:
            - type: ResponseHeaderModifier
              responseHeaderModifier:
                <...>
    

    מחילים את המניפסט:

      kubectl apply -f http-route-response.yaml
    

    אפשר להוסיף, להגדיר ולהסיר כותרות כמו שמתואר בהטמעה של Gateway API. אפשר להגדיר את HTTPRoute עם כותרת בהתאמה אישית באמצעות Google Cloud משתנים נתמכים.

    דוגמה 1:

    כדי להגדיר HTTPRoute שמוסיף את פרטי המיקום של הלקוח לבקשת ה-HTTP לפני שהיא נשלחת לשירות לקצה העורפי, יוצרים מניפסט של HTTPRoute ונותנים לו את השם external-http-request.yaml:

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /fr
            filters:
              # Add custom headers to requests that have `/fr` in the path.
              - type: RequestHeaderModifier
                requestHeaderModifier:
                  add:
                    - name: X-Client-Geo-Location
                      value: "{client_region},{client_city}"
            backendRefs:
              - name: store-french
                port: 8080
    

    לדוגמה, ללקוחות שנמצאים בשטרסבורג שבצרפת, השער מוסיף את הכותרת X-Client-Geo-Location:FR,Strasbourg.

    דוגמה 2:

    כדי להגדיר HTTPRoute שמוסיף כותרת תגובה בהתאמה אישית לתמיכה ב-HTTP Strict Transport Security, יוצרים מניפסט של HTTPRoute ונותנים לו את השם external-http-response.yaml:

      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: store
      spec:
        parentRefs:
          - kind: Gateway
            name: external-http
        hostnames:
        - store.example.com
        rules:
          - matches:
            - path:
                type: PathPrefix
                value: /de
            filters:
              # Add custom headers to responses to requests that have `/de` in the
              # path.
              - type: ResponseHeaderModifier
                responseHeaderModifier:
                  add:
                    - name: Strict-Transport-Security
                      value: max-age=63072000
            backendRefs:
              - name: store-german
                port: 8080
    

    אימות ההגדרות את ההגדרות

    1. כדי לאמת את ההגדרות האישיות של כותרות הבקשות והתגובות:

        kubectl get httproute
      

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

        NAME    HOSTNAMES               AGE
        store   ["store.example.com"]   4d23h
      
    2. כדי לקבל פרטים נוספים, משתמשים בפקודה describe:

        kubectl describe httproute
      

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

        Name:         store
        Namespace:    default
        Labels:       <none>
        Annotations:  <none>
        API Version:  gateway.networking.k8s.io/v1
        Kind:         HTTPRoute
        Metadata:
          Creation Timestamp:  2023-05-27T00:51:01Z
          Generation:          5
          Resource Version:    25418887
          UID:                 2e07a1b8-420b-41b4-acd1-cecbfcd39f42
        Spec:
          Hostnames:
            store.example.com
          Parent Refs:
            Group:  gateway.networking.k8s.io
            Kind:   Gateway
            Name:   external-http
          Rules:
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v1
              Port:    8080
              Weight:  1
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-v2
              Port:    8080
              Weight:  1
            Matches:
              Headers:
                Name:   env
                Type:   Exact
                Value:  canary
              Path:
                Type:   PathPrefix
                Value:  /
            Backend Refs:
              Group:
              Kind:    Service
              Name:    store-german
              Port:    8080
              Weight:  1
            Filters:
              Request Header Modifier:
                Add:
                  Name:   X-Client-Geo-Location
                  Value:  {client_region},{client_city}
              Type:       RequestHeaderModifier
            Matches:
              Path:
                Type:   PathPrefix
                Value:  /de
        Status:
          <...>
      

    הגדרת התאמה של ביטוי רגולרי

    ‫GKE Gateway תומך בהתאמה של ביטויים רגולריים לנתיבים, לפרמטרים של שאילתות ולכותרות של HTTPRoute. אפשר להשתמש בביטויים רגולריים כדי להגדיר כללי ניתוב גמישים.

    התאמה של ביטויים רגולריים נתמכת ב-GatewayClasses הבאים:

    • gke-l7-global-external-managed
    • gke-l7-global-external-managed-mc
    • gke-l7-regional-external-managed
    • gke-l7-regional-external-managed-mc
    • gke-l7-rilb
    • gke-l7-rilb-mc
    • gke-l7-cross-regional-internal-managed-mc

    מגבלות

    • תחביר RE2: יש תמיכה רק בתחביר RE2. ‫RE2 לא תומך ב-lookahead, ב-lookbehind או בהפניות לאחור.
    • מכסות ומגבלות:
      • מספר מקסימלי של התאמות לביטויים רגולריים: אתם יכולים להגדיר עד חמש התאמות לביטויים רגולריים לכל התאמת נתיב (HTTPRoute).
      • אורך מקסימלי: האורך המקסימלי של ביטוי רגולרי הוא 250 תווים.
    • השפעה על הביצועים: התאמה של ביטויים רגולריים דורשת משאבי מחשוב רבים. שימוש בהתאמות של ביטויים רגולריים יכול להגדיל את זמן האחזור של הבקשות:
      • התאמה אחת של ביטוי רגולרי: עלייה של כ-100 מיקרו-שניות בזמן האחזור לכל בקשה.
      • חמישה ביטויים רגולריים: עלייה של כ-200 מיקרו-שניות בזמן האחזור לכל בקשה.

    הגדרת התאמה של ביטוי רגולרי לנתיב

    כדי להגדיר התאמת נתיב באמצעות ביטוי רגולרי, בכלל ההתאמה path, מגדירים את הערך של השדה type ל-RegularExpression.

    בדוגמה הבאה, בקשות שבהן הנתיב תואם לביטוי הרגולרי /videos/hd.* (לדוגמה, /videos/hd-123 או /videos/hd-promo.mp4) מנותבות לשירות store-videos-hd:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: store-path-regex
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: RegularExpression
            value: /videos/hd.*
        backendRefs:
        - name: store-videos-hd
          port: 8080
    

    הגדרת התאמה של ביטוי רגולרי לפרמטר של שאילתה

    כדי להתאים פרמטרים של שאילתה באמצעות ביטוי רגולרי, בכלל ההתאמה queryParams, מגדירים את הערך של השדה type ל-RegularExpression.

    בדוגמה הבאה, בקשות שבהן הפרמטר של השאילתה param1 תואם לביטוי הרגולרי .*param_value.*-hd מנותבות לשירות android-hd:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: store-query-regex
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - queryParams:
          - name: param1
            type: RegularExpression
            value: .*param_value.*-hd
        backendRefs:
        - name: android-hd
          port: 8080
    

    הגדרת התאמה של ביטוי רגולרי לכותרת

    כדי להתאים כותרות HTTP באמצעות ביטוי רגולרי, בכלל ההתאמה headers, מגדירים את הערך של השדה type ל-RegularExpression.

    בדוגמה הבאה, בקשות שבהן הכותרת User-Agent תואמת לביטוי הרגולרי .*Android.*-hd מנותבות לשירות android-hd:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: store-header-regex
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - headers:
          - name: User-Agent
            type: RegularExpression
            value: .*Android.*-hd
        backendRefs:
        - name: android-hd
          port: 8080
    

    הגדרת mTLS ב-frontend

    כדי להפעיל אימות של אישור לקוח, מאזן העומסים של אפליקציות Google מספק mTLS של ממשק קצה. בשערי GKE, פרוטוקול mTLS של ממשק קצה מאפשר להגדיר ולהחיל אימות של אישורי לקוח על כל משאבי GatewayClass הנתמכים, בין שהם גלובליים ובין שהם אזוריים. למידע נוסף, קראו את המאמר הגדרת mTLS לקצה הקדמי של שער.

    הגדרת TLS בקצה העורפי

    אימות TLS של קצה עורפי הוא תכונת אבטחה שמאפשרת למאזן העומסים של GKE Gateway לאמת את הזהות של הקצוות העורפיים שאליהם הוא מתחבר. בשערי GKE, הפונקציונליות הזו מאפשרת להגדיר ולהחיל אימות של אישורי קצה עורפי על GatewayClasses נתמכים, כמו מאזני עומסים מנוהלים חיצוניים גלובליים או אזוריים ומאזני עומסים פנימיים אזוריים.

    מידע נוסף זמין במאמר אבטחת שער.

    כדי לדרוש מהשער לאמת גם את הזהות שלו מול הקצה העורפי (Mutual TLS), צריך להשתמש באישור לקוח במשאב של השער. הוראות מפורטות זמינות במאמר הגדרת Mutual TLS ‏ (mTLS) לקצה העורפי של שער.

    סטטוס המסלול

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

    תנאים של HTTPRoute

    התנאים של HTTPRoute מציינים את הסטטוס של המסלול ואת השערים שאליהם הוא מקושר. מכיוון שאפשר לקשר מסלול לכמה שערים, זו רשימה של שערים והתנאים הספציפיים בין המסלול לכל שער.

    • הערך Accepted=True מציין שה-HTTPRoute מקושר בהצלחה ל-Gateway.
    • ‫Accepted=False מציין שה-HTTPRoute נדחה מהקישור לשער הזה.

    אם לא מופיעים שערים בכותרת Gateway bindings, יכול להיות שהתוויות של HTTPRoute ובוררי התוויות של השער לא תואמים. זה יכול לקרות אם אף שער לא בוחר את הנתיב שלכם.

    אירועי HTTPRoute

    אירועי HTTPRoute מספקים פרטים על הסטטוס של HTTPRoute. האירועים מקובצים לפי הסיבות הבאות:

    • אירועי ADD מופעלים כשמוסיפים משאב.
    • אירועי UPDATE מופעלים כשמשאב מתעדכן.
    • אירועי SYNC מופעלים על ידי התאמה תקופתית.

    מיזוג, קדימות ואימות של נתיבים

    קדימות של מסלולים

    ב-Gateway API מוגדרים כללי קדימות מחמירים לגבי האופן שבו התנועה מותאמת על ידי נתיבים שיש להם כללי ניתוב חופפים. סדר הקדימויות בין שני נתיבי HTTP חופפים הוא:

    1. מיזוג של שם מארח: ההתאמה הארוכה או הספציפית ביותר של שם המארח.
    2. מיזוג נתיבים: התאמת הנתיב הארוך או הספציפי ביותר.
    3. מיזוג כותרות: המספר הגדול ביותר של כותרות HTTP תואמות.
    4. התנגשות: אם שלושת הכללים הקודמים לא קובעים עדיפות, העדיפות ניתנת למשאב HTTPRoute עם חותמת הזמן הישנה ביותר.

    מיזוג מסלולים

    ב-GatewayClasses של gke-l7, כל ה-HTTPRoutes של Gateway מסוים מוזגו לאותו משאב של מפת URL. האופן שבו מתבצע המיזוג של HTTPRoutes תלוי בסוג החפיפה בין HTTPRoutes. אפשר לפצל את ה-HTTPRoute מהדוגמה הקודמת לשלושה HTTPRoute נפרדים כדי להמחיש את המיזוג ואת סדר הקדימויות של המסלולים:

    1. מיזוג נתיבים: כל שלושת ה-HTTPRoutes מחוברים לאותו internal-http Gateway, ולכן הם ממוזגים יחד.
    2. מיזוג של שמות מארחים: כל שלושת המסלולים תואמים ל-store.example.com, ולכן הכללים של שמות המארחים שלהם מוזגו.
    3. מיזוג נתיבים: ל-store-german-route יש נתיב ספציפי יותר /de, ולכן הוא לא ממוזג יותר. גם store-v1-route וגם store-v2-route תואמים לאותו נתיב /*, ולכן הם ממוזגים בנתיב.
    4. מיזוג כותרות: ל-store-v2-route יש קבוצה ספציפית יותר של התאמות של כותרות HTTP מאשר ל-store-v1-route, ולכן הן לא מתמזגות יותר.
    5. התנגשות: מכיוון שאפשר למזג את הנתיבים לפי שם המארח, הנתיב והכותרות, אין התנגשויות וכל כללי הניתוב חלים על התנועה.

    ה-HTTPRoute היחיד ששימש בדוגמה הקודמת שווה ערך לשלושת הנתיבים הנפרדים הבאים:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-v1-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - backendRefs:
        - kind: Service
          name: store-v1
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-v2-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - headers:
          - type: Exact
            name: env
            value: canary
        backendRefs:
        - kind: Service
          name: store-v2
          port: 8080
    ---
    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: store-german-route
    spec:
      parentRefs:
      - kind: Gateway
        name: internal-http
      hostnames:
      - "store.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /de
        backendRefs:
        - kind: Service
          name: store-german
          port: 8080
    

    שערי Kubernetes ושערי Istio

    שימו לב שב-Kubernetes Gateway API וב-Istio API יש משאב בשם Gateway. למרות שהם מבצעים פונקציות דומות, הם לא אותו משאב. אם אתם משתמשים ב-Istio וב-Gateway API באותו אשכול Kubernetes, השמות האלה חופפים כשמשתמשים ב-kubectl בשורת הפקודה. kubectl get gateway עשוי להחזיר את המשאבים של Kubernetes Gateway ולא את המשאבים של Istio Gateway, או להיפך.

    $ kubectl api-resources
    NAME       SHORTNAMES   APIGROUP                       NAMESPACED   KIND
    gateways   gw           networking.istio.io/v1beta1    true         Gateway
    gateways   gtw          networking.k8s.io/v1beta1      true         Gateway
    

    אם אתם משתמשים ב-Istio ומשדרגים ל-GKE מגרסה 1.20 ואילך, מומלץ להתחיל להשתמש בשם הקצר של משאב השער או לציין את קבוצת ה-API. השם הקצר של שער Kubernetes הוא gtw והשם הקצר של שער Istio הוא gw. הפקודות הבאות מחזירות את המשאבים של Kubernetes Gateway ו-Istio Gateway, בהתאמה.

    # Kubernetes Gateway
    $ kubectl get gtw
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    $ kubectl get gateway.networking.x-k8s.io
    NAME                        CLASS
    multi-cluster-gateway       gke-l7-global-external-managed-mc
    
    # Istio Gateway
    $ kubectl get gw
    NAME               AGE
    bookinfo-gateway   64m
    
    $ kubectl get gateway.networking.istio.io
    NAME               AGE
    bookinfo-gateway   64m
    

    פתרון בעיות

    חסרה רשת משנה מסוג proxy-only באזור

    התסמין:

    הבעיה הבאה יכולה לקרות כשיוצרים שער אזורי (פנימי או חיצוני):

    generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/[REGION_NAME]/targetHttpProxies/gkegw-x5vt-default-internal-http-[ID]'. A reserved managed proxy subnetwork with purpose REGIONAL_MANAGED_PROXY is required.
    

    הסיבה:

    הודעת השגיאה הזו מציינת שאין רשת משנה מסוג proxy-only באזור של השער.

    פתרון עקיף:

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

    באזור כבר קיימת רשת משנה מסוג Proxy-only עם מטרה שגויה

    התסמין:

    הבעיה הבאה יכולה לקרות כשיוצרים תת-רשת של שרת proxy בלבד בשביל שער אזורי (פנימי או חיצוני):

    ERROR: (gcloud.compute.networks.subnets.create) Could not fetch resource:
     - The resource 'projects/[PROJECT_NAME]/regions/[REGION_NAME]/subnetworks/[PROXY_ONLY_SUBNET_NAME]' already exists
    

    הסיבה:

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

    פתרון עקיף:

    כדי לפתור את הבעיה:

    1. בודקים שרשת משנה מסוג proxy-only כבר קיימת באזור, ומוודאים שהיא מיועדת למטרה הנכונה:

      1. מציגים את רשימת רשתות המשנה כדי למצוא את רשת המשנה של שרת ה-proxy בלבד באזור:

        gcloud compute networks subnets list --regions=COMPUTE_REGION
        

        מחליפים את COMPUTE_REGION באזור של Compute Engine שבו רוצים ליצור את השער האזורי.

      2. כדי לברר מה המטרה של רשת המשנה שמשמשת רק כשרת proxy באזור, מתארים אותה:

        gcloud compute networks subnets describe PROXY_ONLY_SUBNET \
            --region COMPUTE_REGION | grep -E 'name|purpose'
        

        מחליפים את PROXY_ONLY_SUBNET ברשת המשנה של שרת ה-proxy בלבד.

      ‫GKE Gateway תומך רק ברשתות משנה מסוג REGIONAL_MANAGED_PROXY proxy-only לשערי Gateway אזוריים (פנימיים או אזוריים).

    2. אם רשת המשנה הקיימת לשרתי proxy בלבד באזור נוצרה עם המטרה INTERNAL_HTTPS_LOAD_BALANCER, צריך להעביר את המטרה שלה ל-REGIONAL_MANAGED_PROXY.

    אין שרת upstream תקין

    התסמין:

    הבעיה הבאה יכולה להתרחש כשיוצרים שער אבל לא מצליחים לגשת לשירותים לקצה העורפי (קוד תגובה 503):

    no healthy upstream
    

    הסיבה:

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

    פתרון עקיף:

    כדי לפתור את הבעיה, התאימו אישית את בדיקת התקינות בהתאם לדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.

    משאבי Gateway מיותמים אחרי מחיקת אשכול

    התסמין:

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

    This load balancing service is read-only. It is managed by GKE and can be modified only by GKE.
    

    הסיבה:

    הבעיה הזו מתרחשת כשבקר ה-Gateway לא מצליח לנקות את המשאבים הבסיסיים Google Cloud הישנים במהלך המחיקה והיצירה מחדש של האשכול או ה-Gateway.

    פתרון עקיף:

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

    
    gcloud compute forwarding-rules delete FORWARDING_RULE_NAME
    
    # For HTTP proxies
    gcloud compute target-http-proxies delete PROXY_NAME
    
    # For HTTPS proxies
    gcloud compute target-https-proxies delete PROXY_NAME
    
    gcloud compute url-maps delete URL_MAP_NAME
    
    # For global backend services
    gcloud compute backend-services delete BACKEND_SERVICE_NAME --global
    
    # For regional backend services
    gcloud compute backend-services delete BACKEND_SERVICE_NAME --region=REGION
    
    gcloud compute health-checks delete HEALTH_CHECK_NAME
    
    gcloud compute network-endpoint-groups delete NEG_NAME --zone=ZONE
    
    

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

    • ‫FORWARDING_RULE_NAME: השם של כלל ההעברה.
    • ‫PROXY_NAME: השם של שרת ה-proxy לחלוקת העומס.
    • ‫URL_MAP_NAME: השם של מפת URL.
    • ‫BACKEND_SERVICE_NAME: השם של שירות הקצה העורפי.
    • ‫HEALTH_CHECK_NAME: השם של בדיקת התקינות.
    • ‫NEG_NAME: השם של קבוצת נקודות הקצה ברשת.
    • ‫REGION: האזור של השירות לקצה העורפי האזורי.
    • ‫ZONE: האזור של קבוצת נקודות הקצה ברשת.

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