פריסת שערים

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

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

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

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

  • מפעילים את 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 כדי להגדיר שער. צריך להשתמש במדיניות.

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

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

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

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

  • יש תמיכה ב-HTTPRoute וב-TLSRoute. אין תמיכה ב-TCPRoutes וב-UDPRoutes. כאן תוכלו לראות רשימה של השדות שנתמכים ב-GKE Gateway controller.

  • כותרות מותאמות אישית של בקשות ותגובות עם הפניות אוטומטיות של 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. כדי לוודא שבקר ה-Gateway מתאים בצורה נכונה את מאזן העומסים, צריך למחוק את ה-Gateway הקיים ולפרוס מחדש את המניפסט עם הערך המעודכן של 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 בלבד:

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

    אם אתם פורסים משאב Gateway אזורי (gke-l7-rilb או gke-l7-regional-external-managed) באשכול IPv6 עם מחסנית אחת, אתם צריכים להגדיר רשת משנה מסוג proxy-only עם מחסנית כפולה באמצעות הדגל --stack-type=IPV4_IPV6. הדרישה הזו חלה גם על משאבי שער IPv4 וגם על משאבי שער IPv6, כדי ששרתי ה-proxy של מאזן העומסים יוכלו לתקשר עם Pods לקצה העורפי של IPv6. אין תמיכה ברשתות משנה מסוג IPv6 עם מחסנית אחת (single-stack) לשרתי proxy בלבד (שנוצרו באמצעות הדגל --stack-type=IPV6_ONLY), וברשת ה-VPC צריך להיות מופעל טווח ULA IPv6 פנימי (באמצעות הדגל --enable-ula-internal-ipv6):

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

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

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

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

    הפלט דומה לפלט הבא (לרשת משנה בשני פרוטוקולים מסוג proxy-only, הפלט כולל את השדות internalIpv6Prefix,‏ ipv6AccessType ו-ipv6GceEndpoint):

    ...
    gatewayAddress: 10.1.1.1
    internalIpv6Prefix: fd20:1d14:f522:2:0:0:0:0/64
    ipCidrRange: 10.1.1.0/24
    ipv6AccessType: INTERNAL
    ipv6GceEndpoint: VM_AND_FR
    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
    stackType: IPV4_IPV6
    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, ונתמך על ידי כל ה-gke-l7 GatewayClasses.

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

למידע נוסף על המשאב Gateway, קראו את התיאור של המשאב Gateway או את מפרט ה-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. בקטע הבא תפרסו את הנתיבים, שמורים לשער לשלוח תנועה לקצוות העורפיים.

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

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

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

יצירת 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, שמשלב את הכול במשאב אחד. השער מאפשר לפצל את האחריות בין המשאבים, וכך לפרוס את מאזן העומסים ואת כללי הניתוב שלו בנפרד, על ידי משתמשים או צוותים שונים. כך אפשר להפוך את השערים לשערים משותפים שמקושרים להרבה נתיבים שונים, שיכולים להיות בבעלות מלאה של צוותים עצמאיים ובניהולם, אפילו במרחבי שמות שונים.

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

הדוגמה הזו מבוססת על שער 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 מצורף לשער:

    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.

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

כדי לציין את מסלול הרשת ואת גרסת ה-IP של כתובת המאזין הזמנית של השער, משתמשים בשדה type במערך addresses[] שבהגדרת השער. אם משמיטים את השדה spec.addresses, בקר ה-Gateway מקצה כתובת IP זמנית שמוגדרת כברירת מחדל, בהתאם לסוג המקבץ של האשכול (כתובת IPv4 באשכולות IPv4 עם מקבץ יחיד ובאשכולות עם מקבץ כפול, או כתובת IPv6 באשכולות IPv6 עם מקבץ יחיד כשיש רשת משנה תואמת). במשאבי שער של gke-l7-regional-external-managed, אם משמיטים את השדה spec.addresses, ברירת המחדל היא כתובת IPv4 זמנית במסלול הרגיל באשכולות IPv4 עם סטאק יחיד ובאשכולות עם סטאק כפול, או כתובת IPv6 זמנית במסלול פרימיום באשכולות IPv6 עם סטאק יחיד (המסלול הרגיל לא נתמך בכתובות IPv6).

באשכולות IPv6 עם מחסנית אחת, כשמקצים כתובת IP זמנית למשאב Gateway אזורי (gke-l7-rilb או gke-l7-regional-external-managed), בקר ה-Gateway בוחר את רשת המשנה בסדר הבא:

  1. אם במשאב GCPGatewayPolicy שמצורף למשאב Gateway מצוין השדה spec.default.subnetwork, כתובת ה-IP הזמנית מוקצית מרשת המשנה הזו.
  2. אם לא צוינה רשת משנה במשאב GCPGatewayPolicy, ולרשת המשנה של הצומת הראשי של האשכול יש את סוג הגישה הנדרש ל-IPv6 (INTERNAL ל-gke-l7-rilb או EXTERNAL ל-gke-l7-regional-external-managed), כתובת ה-IP הזמנית מוקצית מרשת המשנה של הצומת הראשי.
  3. אם אין רשת משנה תואמת, בקר השער מדווח על שגיאה. הוראות להגדרת רשת משנה בהתאמה אישית מופיעות בקטע דרישות של רשת משנה של IPv6 חיצונית אזורית באשכולות IPv6 פנימיים.

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

  • ‫networking.gke.io/premium-ephemeral-ipv4-address: מקצה כתובת IPv4 זמנית במסלול פרימיום (gke-l7-regional-external-managed).
  • ‫networking.gke.io/standard-ephemeral-ipv4-address: מקצה כתובת IPv4 זמנית במסלול הרגיל (gke-l7-regional-external-managed).
  • ‫networking.gke.io/premium-ephemeral-ipv6-address: מקצה כתובת IPv6 זמנית במסלול פרימיום (gke-l7-regional-external-managed).
  • ‫networking.gke.io/ephemeral-ipv4-address/REGION: מקצה כתובת IPv4 ארעית אזורית ב-REGION (gke-l7-rilb ו-gke-l7-cross-regional-internal-managed-mc).
  • ‫networking.gke.io/ephemeral-ipv6-address/REGION: מקצה כתובת IPv6 אזורית זמנית ב-REGION (gke-l7-rilb).

כדי להקצות כתובות IP משני מסלולי הרשת או משתי הגרסאות של כתובות ה-IP (לדוגמה, גם כתובת IPv4 וגם כתובת IPv6 באשכול עם מחסנית כפולה), צריך לציין כמה סוגים בשדה addresses.

בדוגמה הבאה אפשר לראות איך מקצים כתובת IP במסלול פרימיום לשער. Google Cloud כדי להקצות כתובת IPv4 במסלול הרגיל, משתמשים ב-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.
      # For a Premium Tier ephemeral IPv6 address, use:
      # networking.gke.io/premium-ephemeral-ipv6-address
      - 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 מפורש תמיד יש עדיפות על פני HTTPRoutes חדשים עם כללי ניתוב סותרים.

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

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

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

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

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

GatewayClasses מאגר ברירת המחדל של כתובות IPv4 מאגר ברירת המחדל של כתובות IPv6 (זמניות וסטטיות)
  • gke-l7-rilb
  • gke-l7-rilb-mc
כתובות IPv4 פרטיות אזוריות מטווח כתובות ה-IPv4 של הצומת הראשי כתובות IPv6 פנימיות אזוריות מטווח כתובות ה-IPv6 הפנימיות של רשת המשנה של הצומת הראשי (/64 ULA) כשרשת המשנה של הצומת הראשי משתמשת ב-ipv6AccessType: INTERNAL, או מרשת משנה באותו אזור שמוגדרת עם ipv6AccessType: INTERNAL (gke-l7-rilb בלבד)
  • gke-l7-regional-external-managed
  • gke-l7-regional-external-managed-mc
כתובות IPv4 ציבוריות אזוריות ממאגר כתובות ה-IPv4 החיצוניות האזוריות של Google כתובות IPv6 חיצוניות אזוריות מטווח כתובות ה-IPv6 החיצוניות של רשת המשנה של הצומת הראשי (/64 GUA ציבורית) כשברשת המשנה של הצומת הראשי משתמשים ב-ipv6AccessType: EXTERNAL, או מרשת משנה נפרדת של VPC באותו אזור שמוגדרת עם ipv6AccessType: EXTERNAL (gke-l7-regional-external-managed בלבד; ראו הדרישה לרשת משנה של IPv6 חיצונית אזורית באשכולות IPv6 פנימיים)
  • gke-l7-global-external-managed
  • gke-l7-global-external-managed-mc
  • gke-l7-gxlb
  • gke-l7-gxlb-mc
כתובות IPv4 ציבוריות גלובליות מטווחי כתובות ה-IPv4 החיצוניות הגלובליות של Google כתובות IPv6 ציבוריות גלובליות מטווחי כתובות ה-IPv6 החיצוניות הגלובליות של Google

דרישה לרשת משנה אזורית חיצונית של IPv6 באשכולות פנימיים של IPv6

בניגוד לכתובות IPv4 חיצוניות אזוריות (שמוקצות ממאגר שמנוהל על ידי Google, ללא תלות ברשתות משנה של VPC), כתובות IPv6 חיצוניות אזוריות של Compute Engine (‏NETLB) חייבות להיות מוקצות מרשת משנה של VPC שמוגדרת עם ipv6AccessType: EXTERNAL.

אם רשת המשנה של הצומת הראשי באשכול כבר מוגדרת עם --ipv6-access-type=EXTERNAL, בקר ה-Gateway משתמש ברשת המשנה של הצומת הראשי כברירת מחדל לכתובות IPv6 של gke-l7-regional-external-managed.

אם באשכול שלכם יש רשת משנה פנימית של צומת IPv6 (--ipv6-access-type=INTERNAL), ברשת המשנה הראשית של הצומת באשכול יש רק כתובות מקומיות ייחודיות (ULA) פרטיות. לפני שפורסים משאב של שער IPv6 ב-gke-l7-regional-external-managed (באמצעות כתובת IPv6 זמנית או סטטית), צריך ליצור רשת משנה באותו אזור ורשת VPC עם --ipv6-access-type=EXTERNAL:

  1. יוצרים תת-רשת מסוג IPv6 בלבד (או עם שני סוגי כתובות) עם גישה חיצונית ל-IPv6 באותה רשת VPC ובאותו אזור של האשכול:

    gcloud compute networks subnets create EXTERNAL_IPV6_SUBNET_NAME \
        --network=VPC_NETWORK_NAME \
        --region=COMPUTE_REGION \
        --stack-type=IPV6_ONLY \
        --ipv6-access-type=EXTERNAL
    

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

    • ‫EXTERNAL_IPV6_SUBNET_NAME: השם של רשת המשנה עם גישה חיצונית ל-IPv6.
    • ‫VPC_NETWORK_NAME: השם של רשת ה-VPC שבה פועל אשכול GKE.
    • ‫COMPUTE_REGION: האזור ב-Compute Engine שבו פועל האשכול.

    כדי ליצור רשת משנה עם שני סוגי כתובות במקום רשת משנה עם כתובות IPv6 בלבד, מחליפים את --stack-type=IPV6_ONLY ב---stack-type=IPV4_IPV6 --range=IPV4_CIDR_RANGE, כאשר IPV4_CIDR_RANGE הוא טווח CIDR ראשי של IPv4 שלא נמצא בשימוש ברשת ה-VPC.

  2. מגדירים את משאב השער כך שישתמש ברשת המשנה החיצונית של IPv6:

    • לכתובת IPv6 זמנית: מצרפים משאב GCPGatewayPolicy למשאב Gateway ומציינים את שם רשת המשנה בשדה spec.default.subnetwork. שומרים את המניפסט הבא בתור gateway-policy.yaml:

      apiVersion: networking.gke.io/v1
      kind: GCPGatewayPolicy
      metadata:
        name: GATEWAY_POLICY_NAME
        namespace: GATEWAY_NAMESPACE
      spec:
        default:
          subnetwork: EXTERNAL_IPV6_SUBNET_NAME
        targetRef:
          group: gateway.networking.k8s.io
          kind: Gateway
          name: GATEWAY_NAME
      

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

      • ‫GATEWAY_POLICY_NAME: השם של המשאב GCPGatewayPolicy.
      • ‫GATEWAY_NAMESPACE: מרחב השמות של משאב ה-Gateway המטורגט.
      • ‫EXTERNAL_IPV6_SUBNET_NAME: השם של רשת המשנה שיצרתם בשלב הקודם.
      • ‫GATEWAY_NAME: השם של משאב שער היעד.

      מחילים את המניפסט gateway-policy.yaml:

      kubectl apply -f gateway-policy.yaml
      
    • לכתובת IPv6 סטטית (NamedAddress): מציינים את הדגל --subnet=EXTERNAL_IPV6_SUBNET_NAME כשיוצרים את המשאב של כתובת ה-IPv6 הסטטית, כמו שמוסבר בקטע שימוש בכתובת IP עם שם.

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

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

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

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

    • כתובת IPv4 פנימית אזורית (gke-l7-rilb):

      gcloud compute addresses create IP_ADDRESS_NAME \
          --purpose=SHARED_LOADBALANCER_VIP \
          --region=COMPUTE_REGION \
          --subnet=SUBNET \
          --project=PROJECT_ID
      
    • כתובת IPv6 פנימית אזורית (gke-l7-rilb):

      gcloud compute addresses create IP_ADDRESS_NAME \
          --region=COMPUTE_REGION \
          --subnet=CLUSTER_NODE_SUBNET \
          --ip-version=IPV6 \
          --project=PROJECT_ID
      
    • כתובת IPv6 חיצונית אזורית (gke-l7-regional-external-managed):

      gcloud compute addresses create IP_ADDRESS_NAME \
          --region=COMPUTE_REGION \
          --subnet=EXTERNAL_IPV6_SUBNET_NAME \
          --ip-version=IPV6 \
          --endpoint-type=NETLB \
          --project=PROJECT_ID
      

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

    • ‫IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה.
    • ‫COMPUTE_REGION: לשערי כניסה אזוריים, האזור ב-Compute Engine שבו פועל האשכול. הדגל הזה לא נדרש לשערים גלובליים וחיצוניים.
    • ‫SUBNET או CLUSTER_NODE_SUBNET: רשת המשנה של כתובת ה-IP הפנימית. הדגל הזה לא נדרש לשערים גלובליים וחיצוניים.
    • ‫EXTERNAL_IPV6_SUBNET_NAME: רשת המשנה האזורית שמוגדרת עם ipv6AccessType: EXTERNAL, שממנה מקצים את כתובת ה-IPv6 החיצונית האזורית.
    • ‫PROJECT_ID: הפרויקט שבו פועל אשכול GKE.

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

  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
    

הגדרת כללים של חומת אש ל-IPv6 ב-VPC משותף או ניהול ידני של חומת האש

כשמשביתים או מגבילים את היצירה האוטומטית של כללי חומת אש (למשל בפרויקטים של שירות VPC משותף), צריך ליצור באופן ידני כלל חומת אש לתעבורת נתונים נכנסת ב-IPv6 כדי לאפשר תעבורת נתונים מ Google Cloud בודקי בדיקת התקינות ב-IPv6 (2600:2d00:1:b029::/64), שרתי proxy של Google Front End (GFE) למאזני עומסים חיצוניים גלובליים של אפליקציות (2600:2d00:1:1::/64) ו-internalIpv6Prefix של רשת המשנה האזורית של שרתי proxy בלבד למאזני עומסים אזוריים של אפליקציות:

gcloud compute firewall-rules create FIREWALL_RULE_NAME \
    --network=VPC_NETWORK_NAME \
    --action=ALLOW \
    --direction=INGRESS \
    --rules=tcp:80,tcp:443 \
    --source-ranges="2600:2d00:1:b029::/64,2600:2d00:1:1::/64,PROXY_SUBNET_INTERNAL_IPV6_PREFIX" \
    --target-tags=GKE_NODE_TAG

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

  • ‫FIREWALL_RULE_NAME: השם של כלל חומת האש.
  • ‫VPC_NETWORK_NAME: השם של רשת ה-VPC
  • ‫PROXY_SUBNET_INTERNAL_IPV6_PREFIX: הקידומת הפנימית של /64 IPv6 של רשת המשנה האזורית שמשמשת רק לשרתי proxy‏ (internalIpv6Prefix).
  • ‫GKE_NODE_TAG: תג הרשת שמוגדר לצמתים באשכול.

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

ב-Cloud Load Balancing יש פונקציונליות של הפניה אוטומטית מ-HTTP ל-HTTPS. מאזן עומסים חיצוני של אפליקציות מפנה בקשות 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 עוזרת ליצור כתובות 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 בכותרת הבקשה (במקום 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. לדוגמה, בקשה ל-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 Gateway מכפיל מסנן 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)‎ לקצה העורפי של Gateway.

סטטוס המסלול

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

תנאים של HTTPRoute

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

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

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

אירועי HTTPRoute

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

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

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

קדימות של נתיבים

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

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

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

ב-GatewayClasses מסוג gke-l7, כל ה-HTTPRoutes של שער נתון מוזגו לאותו משאב של מפת 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 לשערים אזוריים (פנימיים או אזוריים).

  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: האזור של קבוצת נקודות הקצה ברשת.

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