בדף הזה מוסבר איך לפרוס משאבי Gateway של Kubernetes כדי לאזן עומסים של תעבורת נתונים נכנסת לאשכול יחיד של Google Kubernetes Engine (GKE).
כדי לפרוס שערים לאיזון עומסים של תעבורת נתונים נכנסת (ingress) בכמה אשכולות (או צי), אפשר לעיין במאמר בנושא פריסת שערים מרובי אשכולות.
למידע על הגדרות ספציפיות יותר של שערים, כמו ניתוב בין מרחבי שמות ופיצול תנועת HTTP, אפשר לעיין במדריכים למשתמשים ב-Gateway API.
לפני שמתחילים
לפני שמתחילים, חשוב לוודא שביצעתם את הפעולות הבאות:
- מפעילים את ממשק Google Kubernetes Engine API. הפעלת Google Kubernetes Engine API
- אם רוצים להשתמש ב-CLI של Google Cloud למשימה הזו, צריך להתקין ואז להפעיל את ה-CLI של gcloud. אם התקנתם בעבר את ה-CLI של gcloud, מריצים את הפקודה
gcloud components updateכדי לקבל את הגרסה העדכנית. יכול להיות שגרסאות קודמות של ה-CLI של gcloud לא יתמכו בהרצת הפקודות שמופיעות במסמך הזה.
- מוודאים שיש לכם אשכול קיים של Autopilot או Standard. כדי ליצור אשכול חדש, אפשר לעיין במאמר בנושא יצירת אשכול Autopilot.
דרישות של GKE Gateway controller
- Gateway API נתמך רק באשכולות VPC-native.
- אם אתם משתמשים ב-GatewayClasses אזוריים או חוצי-אזורים, אתם צריכים להפעיל רשת משנה ל-proxy בלבד.
- צריך להפעיל את התוסף
HttpLoadBalancingבאשכול. - אם אתם משתמשים ב-Istio, אתם צריכים לשדרג את Istio לאחת מהגרסאות הבאות:
- גרסה 1.15.2 ואילך
- 1.14.5 ואילך
- גרסה 1.13.9 ואילך.
- אם משתמשים ב-VPC משותף, צריך להקצות את התפקיד
Compute Network Userלחשבון השירות של GKE בפרויקט המארח של פרויקט השירות.
הגבלות ומגבלות
כשמשתמשים ב-GKE Gateway, חשוב להבין את המגבלות וההגבלות הבאות:
מחלקות GKE Gateway תומכות ביכולות שונות בהתאם למאזן העומסים שבו הן משתמשות. מידע נוסף על התכונות השונות שנתמכות בכל GatewayClass זמין במאמר יכולות של GatewayClass.
שיטה מומלצת: כדי לקבל ביצועים אופטימליים, מומלץ להגביל את מספר השערים ל-100 לכל היותר. חריגה מהמגבלה הזו עלולה להשפיע על הביצועים או לגרום להגדלת זמן האחזור.
אי אפשר להשתמש ב-FrontendConfig או ב-BackendConfig כדי להגדיר שער. חובה להשתמש במדיניות.
ההתנהגות של GKE Gateway שונה מזו של Ingress, כי Gateway לא מסיק פרמטרים של בדיקת תקינות. אם השירות לא מחזיר 200 לבקשות אל
GET /, או אם יש לכם בדיקות מוכנות של פודים מותאמים אחרים, אתם צריכים להגדיר HealthCheckPolicy לשירות.אי אפשר לציין מספר יציאה ישירות בשם המארח (לדוגמה, web.example.com:80) לניתוב תנועה.
אפשר לראות את משאבי מאזן העומסים ש-GKE יוצר עבור Gateways במסוף Google Cloud , אבל המשאבים האלה לא מפנים אל ה-Gateway או אל אשכול GKE שאליהם הם מצורפים.
אי אפשר ליצור באופן אוטומטי אישור SSL בניהול Google באמצעות Gateways, אבל אפשר ליצור אישור SSL בניהול Google באופן ידני ולהפנות אליו. מידע נוסף זמין במאמר בנושא אבטחת שער.
HTTPRoute הוא סוג המסלול היחיד שנתמך. אין תמיכה ב-TCPRoutes, ב-UDPRoutes וב-TLSRoutes. רשימת השדות שנתמכים על ידי בקר GKE Gateway מופיעה במאמר בנושא יכולות של GatewayClass.
האפשרות להשתמש בכותרות מותאמות אישית של בקשות ותגובות עם הפניות אוטומטיות של שער או נתיב, ושינוי כתובות URL עם שער, זמינה רק ב-GKE בגרסה 1.27 ואילך.
ה-GatewayClass
gke-l7-gxlbלא נתמך בכותרות מותאמות אישית של בקשות ותגובות עם הפניות אוטומטיות של שערים ונתיבים, ועם שכתוב של כתובות URL עם שערים.כשמגדירים כותרות מותאמות אישית של בקשות ותגובות ב-HTTPRoute, אין תמיכה בGoogle Cloud משתנים הבאים:
cdn_cache_id(אין תמיכה ב-Cloud CDN עם GKE Gateway)cdn_cache_status(אין תמיכה ב-Cloud CDN עם GKE Gateway)-
origin_request_header(מדיניות CORS לא נתמכת ב-GKE Gateway)
GKE Gateway לא תומך בתכונה של איזון עומסים ב-Cloud CDN.
אין תמיכה בכותרות מותאמות אישית של Mutual TLS (mTLS עם GKE Gateway לא נתמך)
Google Cloud המגבלות של מאזן עומסים קלאסי של אפליקציות (ALB) חלות על GKE Gateway. בנוסף, אי אפשר להגדיר כותרת תגובה של מארח בהתאמה אישית בשירות הקצה העורפי.
הפניות אוטומטיות של נתיבים ושינוי של כתובות URL הן פעולות שאי אפשר לבצע בו-זמנית, ולכן אי אפשר להשתמש בשני המסננים האלה באותם כללים.
אי אפשר להפנות תנועה ליציאה אחרת באמצעות Cloud Load Balancing. רשימת השדות שנתמכים על ידי בקר GKE Gateway מופיעה במאמר בנושא יכולות GatewayClass.
GKE Gateway לא תומך בתווים כלליים לחיפוש, בביטויים רגולריים ובכתובות URL דינמיות.
אם מציינים שער עם סיווג שער חיצוני אזורי, הבקר מקצה כתובת IP פנימית במקום כתובת חיצונית. כדי ללמוד איך להשתמש בכתובת עם שם במאזן עומסים חיצוני אזורי של אפליקציות (ALB), אפשר לעיין במאמר פריסת שער חיצוני אזורי.
שער משתמש בקבוצות נקודות קצה ברשת עצמאיות כדי להקצות קבוצות של נקודות קצה ברשת. כדי לוודא שבקר Gateway מבצע התאמה נכונה של ההגדרה של מאזן העומסים, אסור לשנות את ההערה
cloud.google.com/negשל שירות שמהווה חלק מ-Gateway.GKE Gateway לא תומך בהפניה לשירות שמופנה גם על ידי GKE Ingress.
כשמגדירים
Gatewayלהקצאת כתובת IP, אי אפשר לשנות אתGateway.spec.gatewayClass. כדי לוודא שבקר Gateway מבצע התאמה נכונה של איזון העומסים, צריך למחוק את Gateway הקיים ולפרוס מחדש את המניפסט עם הערך המעודכן שלgatewayClass.אין תמיכה בהערה
networking.gke.io/app-protocols. במקום זאת, צריך להשתמש בשדהappProtocolכדי להשיג את אותה התוצאה.אם אתם משתמשים ב-GKE Gateway עם
external-dnsומצב התקינות של ה-Gateway הוא unhealthy, כברירת מחדל, כל רשומות ה-DNS שמשויכות ל-Gateway נמחקות מאזורי ה-DNS שלכם.שיטה מומלצת: כשמריצים את
external-dns, מגדירים את הדגלpolicy=upsert-only. ההגדרה הזו עוזרת למנוע מחיקה של רשומות DNS קיימות.אם יציאה מוסרת מ-
Serviceש-GKE Gateway מפנה אליו דרך מסלול, צריך לעדכן גם את הערת ה-Standalone NEG בשירות כדי להסיר את היציאה הזו מהבקר של ה-Standalone NEG בשירות. אם לא תעשו זאת, בקר ה-NEG יפסיק בסופו של דבר לסנכרן את נקודות הקצה של ה-Pod בשירות הזה. פרטים נוספים זמינים במאמר NEG Controller מפסיק לנהל נקודות קצה כשמסירים יציאה מ-Service.פריסות שמשתמשות בשערים מרובי אשכולות (MCG) שמשתמשים באשכולות אזוריים חשופות להפרעות בשירות במהלך שדרוגים של אשכולות. הבעיה הזו מתרחשת כי מנגנון גילוי של קבוצת נקודות קצה ברשת (NEG) מדור קודם עשוי לדווח באופן שגוי על אפס בק-אנדים כשמישור הבקרה של האשכול האזורי לא זמין באופן זמני. אנחנו עובדים על פתרון לטווח ארוך. כדי להימנע מנקודת כשל יחידה, מומלץ להשתמש באשכולות GKE אזוריים עם MCG.
הפעלת Gateway API באשכול
כדי להשתמש במשאבי Gateway ב-GKE, צריך להפעיל את Gateway API באשכול.
לפני שמעדכנים אשכול GKE קיים כדי להפעיל את Gateway API, צריך לוודא שמתקיימות הדרישות המינימליות לפני שממשיכים בעדכון.
כדי להפעיל את Gateway API באשכול GKE קיים (במצב Autopilot או Standard), משתמשים בפקודה הבאה. יכול להיות שיחלפו עד 45 דקות עד שהאשכול יתעדכן ויתקין את ה-CRD.
gcloud container clusters update CLUSTER_NAME \
--location=CLUSTER_LOCATION\
--gateway-api=standard
מחליפים את מה שכתוב בשדות הבאים:
CLUSTER_NAME: השם של האשכול הקיים.
CLUSTER_LOCATION: האזור או התחום של Compute Engine שבו נמצא האשכול.
הדגל --gateway-api=standard מורה ל-GKE להתקין את ה-CRD v1beta1 עם האשכול.
אימות האשכול
אחרי שיוצרים או משדרגים את האשכול, הבקר של GKE Gateway מתקין באופן אוטומטי את GatewayClasses. יכול להיות שיעברו כמה דקות עד שהבקר יזהה את ה-CRD ויתקין את GatewayClasses.
מוודאים ש-Gateway API מופעל במישור הבקרה של GKE:
gcloud container clusters describe CLUSTER_NAME \ --location=CLUSTER_LOCATION \ --format jsonהפלט אמור להיראות כך: אם הפלט הזה ריק, מריצים מחדש את הפקודה לעדכון האשכול.
"networkConfig": { ... "gatewayApiConfig": { "channel": "CHANNEL_STANDARD" }, ... },מוודאים ש-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), צריך להגדיר רשת משנה של פרוקסי בלבד. לכל אזור ב-VPC שבו אתם משתמשים במאזני עומסים פנימיים של אפליקציות (ALB) צריך להיות תת-רשת לשרת proxy בלבד. רשת המשנה הזו מספקת כתובות IP פנימיות לשרתי ה-proxy של מאזן העומסים.
יוצרים תת-רשת לשרתי proxy בלבד:
gcloud compute networks subnets create SUBNET_NAME \ --purpose=REGIONAL_MANAGED_PROXY \ --role=ACTIVE \ --region=COMPUTE_REGION \ --network=VPC_NETWORK_NAME \ --range=CIDR_RANGEמחליפים את מה שכתוב בשדות הבאים:
-
SUBNET_NAME: השם של תת-הרשת של ה-proxy בלבד. -
COMPUTE_REGION: האזור של תת-הרשת של ה-proxy בלבד. -
VPC_NETWORK_NAME: השם של רשת ה-VPC שבה יוצרים את רשת המשנה הזו מסוג proxy בלבד. חשוב לוודא שזו אותה רשת VPC שבה נמצא אשכול GKE ושבה פורס השער. הפעולה הזו חשובה כדי לאפשר תקשורת חלקה בין מאזן העומסים לבין שירותי הקצה העורפי. -
CIDR_RANGE: טווח כתובות ה-IP הראשי של רשת המשנה. צריך להשתמש במסכה של רשת משנה באורך של/26לכל היותר, כדי שיהיו לפחות 64 כתובות IP זמינות לשרתי proxy באזור. מסכה של רשת משנה מומלצת היא/23.
-
מאמתים את רשת המשנה של ה-proxy בלבד:
gcloud compute networks subnets describe SUBNET_NAME \ --region=COMPUTE_REGIONהפלט אמור להיראות כך:
... gatewayAddress: 10.1.1.1 ipCidrRange: 10.1.1.0/24 kind: compute#subnetwork name: proxy-subnet network: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/global/networks/default privateIpGoogleAccess: false privateIpv6GoogleAccess: DISABLE_GOOGLE_ACCESS purpose: REGIONAL_MANAGED_PROXY region: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION role: ACTIVE selfLink: https://www.googleapis.com/compute/v1/projects/PROJECT_NAME/regions/REGION/subnetworks/proxy-subnet state: READY
יצירת שער
משאב Gateway מייצג מישור נתונים שמנתב תעבורה ב-Kubernetes. שער יכול לייצג סוגים שונים של איזון עומסים וניתוב, בהתאם ל-GatewayClass שממנו הוא נגזר. מידע נוסף על משאב Gateway מופיע בתיאור משאב Gateway או במפרט ה-API.
במקרה הזה, האדמין של אשכול GKE רוצה ליצור שער שאפשר להשתמש בו בצוותים שונים כדי לחשוף את האפליקציות שלהם באופן פנימי. האדמין פורס את שער הכניסה, וצוותי האפליקציות פורסים את המסלולים שלהם באופן עצמאי ומצרפים אותם לשער הכניסה הזה.
שומרים את מניפסט השער הבא בקובץ בשם
gateway.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: מציין שה-Gateway חושף רק את יציאה 80 להאזנה לתנועת HTTP.
השער הזה מוגדר לטיפול בתנועת HTTP רק ביציאה 80. הוא לא תומך ב-HTTPS (יציאה 443) כברירת מחדל, ואם תנסו להתחבר דרך HTTPS, יכול להיות שהבקשה תיכשל.
-
פורסים את שער הכניסה באשכול:
kubectl apply -f gateway.yamlמוודאים שהשער נפרס בצורה נכונה. יכול להיות שיעברו כמה דקות עד שכל המשאבים יופעלו.
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מציין שהשער מוכן.בשלב הזה, יש שער (Gateway) שמוצב באשכול שלכם, שסופק לו איזון עומסים וכתובת IP. לשער אין מסלולים, ולכן הוא לא יודע איך לשלוח תנועה לשרתי קצה עורפיים. בלי מסלולים, כל התנועה מועברת לבק-אנד שמוגדר כברירת מחדל, שמחזיר HTTP 404. בשלב הבא פורסים אפליקציה ומסלולים, שמציינים ל-Gateway איך להגיע לשרתי הקצה העורפיים של האפליקציה.
פריסת אפליקציות ההדגמה
צוותי אפליקציות יכולים לפרוס את האפליקציות והנתיבים שלהם בנפרד מהפריסה של שערים. במקרים מסוימים, צוות האפליקציה עשוי לרצות להיות הבעלים של שער הגישה ולפרוס אותו בעצמו כמשאב שמוקדש לאפליקציות שלו. במאמר שיוך מסלולים מוסבר על מודלים שונים של בעלות על שערים ומסלולים. בדוגמה הזו, צוות החנות פורס את האפליקציה שלו ואת ה-HTTPRoute הנלווה כדי לחשוף את האפליקציה שלו דרך שער internal-http שנוצר בקטע הקודם.
למשאב HTTPRoute יש הרבה שדות שאפשר להגדיר להתאמת תנועה. הסבר על השדות של HTTPRoute מופיע במפרט ה-API.
פורסים את אפליקציית החנות (פריסות 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.
מוודאים שהפריסה של האפליקציה בוצעה בהצלחה:
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בודקים שהשירותים נפרסו:
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
משאבי ניתוב מגדירים כללים ספציפיים לפרוטוקול למיפוי תנועה משערים (Gateway) לשרתי קצה עורפיים של Kubernetes. המשאב HTTPRoute מבצע התאמה וסינון של תנועת HTTP ו-HTTPS, והוא נתמך על ידי כל GatewayClasses של gke-l7.
בקטע הזה פורסים HTTPRoute, שמגדיר את ה-Gateway עם כללי הניתוב שנדרשים כדי להגיע לאפליקציית החנות.
שומרים את מניפסט ה-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פורסים את ה-HTTProute באשכול:
kubectl apply -f store-route.yamlHTTPRoute
storeקשור ל-Gatewayinternal-httpבאמצעות המאפייןparentRefs. כללי הניתוב האלה מוגדרים במאזן העומסים הבסיסי, כמו בתרשים הזה:כללי הניתוב האלה מעבדים תנועת HTTP באופן הבא:
- תנועת הגולשים באתר
store.example.com/deמגיעה לשירותstore-german. - תנועה אל
store.example.comעם כותרת HTTP"env: canary"עוברת אל השירותstore-v2. - שאר התנועה אל
store.example.comמופנית אל השירותstore-v1.
- תנועת הגולשים באתר
מוודאים שרכיב ה-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.מוודאים ש-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 הוגדר בנפרד.
מאחזרים את כתובת ה-IP מהשער כדי שתוכלו לשלוח תנועה לאפליקציה:
kubectl get gateways.gateway.networking.k8s.io internal-http -o=jsonpath="{.status.addresses[0].value}"הפלט הוא כתובת IP.
שולחים תעבורה לכתובת ה-IP הזו מהמעטפת במכונה וירטואלית (VM) עם קישוריות לאשכול. אפשר ליצור מכונה וירטואלית למטרה הזו. הפעולה הזו נדרשת כי לשער יש כתובת IP פנימית, ואפשר לגשת אליו רק מתוך רשת ה-VPC. מכיוון ש-
internal-httpהוא מאזן עומסים אזורי, מעטפת הלקוח צריכה להיות באותו אזור כמו אשכול GKE.שליחת בקשה אל 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" }כדי לבדוק את ההתאמה של הנתיב, עוברים לגרסה הגרמנית של שירות החנות בכתובת
store.example.com/de:curl http://store.example.com/de --resolve store.example.com:80:GATEWAY_IP_ADDRESS -vהפלט מאשר שהבקשה הוגשה על ידי
store-germanPod:{ "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" }לבסוף, משתמשים בכותרת
env: canaryHTTP כדי לשלוח תנועה לגרסת הקנרי של שירות החנות:curl -H "env: canary" http://store.example.com --resolve store.example.com:80:GATEWAY_IP_ADDRESS -vהפלט מאשר שהבקשה הוגשה על ידי
store-v2Pod:{ "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 גלובלית (או בכתובת IP מסוג Anycast) כחלק הקדמי של השער. כתובת ה-IP הזו מפורסמת בכל האזורים של Google Cloud Compute. לקוחות ששולחים תעבורת נתונים לכתובת ה-IP מסוג Anycast הזו מנותבים למיקום הקרוב ביותר של Google שבו כתובת ה-IP מפורסמת. שער חיצוני גלובלי זמין רק במסלול הפרימיום של שירותי הרשת.
- שער חיצוני אזורי: השער הזה משתמש בכתובת IP אזורית כחלק הקדמי של השער. ההתנהגות של השער הזה תלויה במסלול שירות הרשת שתבחרו:
- אם בוחרים במסלול הרגיל של שירותי הרשת (ברירת המחדל), כתובת ה-IP האזורית מפורסמת רק באזור Google Cloud Compute המקומי שבו נפרס שער חיצוני אזורי. תעבורת נתונים מלקוחות שנשלחת לכתובת ה-IP הזו מנותבת על ידי ספק האינטרנט המקומי שלהם דרך האינטרנט הציבורי, לפני שהיא מגיעה לאזור של Google שבו כתובת ה-IP מפורסמת.
- אם בוחרים במסלול הפרימיום של שירות הרשת, כתובת ה-IP האזורית מפורסמת בכל הרשת הגלובלית של Google. כלומר, תעבורת הנתונים של הלקוח נכנסת לרשת הגלובלית האיכותית של Google בשדרה המרכזית בנקודת קישור בין רשתות שכנות (peering) בקצה של Google, הכי קרוב שאפשר ללקוח, גם אם היעד הוא כתובת IP אזורית. המיקום הזה מפחית באופן משמעותי את זמן האחזור ומשפר את הביצועים, כי הוא מצמצם את המרחק שהתנועה עוברת באינטרנט הציבורי.
פריסת שער חיצוני גלובלי
בדוגמה הבאה אפשר לראות איך חושפים אפליקציה בחנות עם כמה אישורים שמצורפים לשער החיצוני הגלובלי ומקובצים במפת אישורים באמצעות Certificate Manager ו-HTTPRoute.
יצירת מיפוי אישורים
Google ממליצה להשתמש בCertificate Manager כדי לנהל אישורים כשצריך 15 אישורים או יותר לכל שער, או כשצריך להשתמש באישור כללי.
אפשר גם לאבטח את שער הכניסה החיצוני באמצעות סודות של Kubernetes או אישורי SSL בניהול Google. מידע נוסף זמין במאמר בנושא אבטחת שערים.
בקטע הזה מוסבר איך ליצור אישורים באמצעות Certificate Manager כדי לאבטח את האפליקציות שפועלות באשכול.
מפעילים את Certificate Manager API:
gcloud services enable certificatemanager.googleapis.comיוצרים מיפוי אישורים:
gcloud beta certificate-manager maps create store-example-com-mapטוענים את האישור והמפתחות שמנוהלים על ידי 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: השם של קובץ המפתח הפרטי.
מידע נוסף זמין במאמר יצירת מפתח פרטי ותעודה.
-
יוצרים
CertificateMapEntryשבו מוקצה האישור למיפוי האישורים:gcloud beta certificate-manager maps entries create store-example-com-map-entry \ --map=store-example-com-map \ --hostname=store.example.com \ --certificates=store-example-com-cert
כדי ללמוד איך לאבטח שער באמצעות מקורות אחרים לאישורים, כמו סודות של Kubernetes או אישורי SSL, אפשר לעיין במאמר בנושא אבטחת שער.
יצירת שער
משאב Gateway מייצג מישור נתונים שמנתב תעבורה ב-Kubernetes. שער יכול לייצג סוגים שונים של איזון עומסים וניתוב, בהתאם ל-GatewayClass שבו הוא משתמש.
מידע נוסף על משאב שער זמין בתיאור משאב שער או במפרט ה-API.
בקטע הזה יוצרים שער. צוותי אפליקציות יכולים להשתמש ב-Gateway כדי לחשוף את האפליקציות שלהם לאינטרנט על ידי פריסת מסלולים באופן עצמאי וצירוף שלהם בצורה מאובטחת ל-Gateway.
שומרים את המניפסט הבא בקובץ בשם
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.-
מחילים את המניפסט על האשכול:
kubectl apply -f gateway.yamlיכול להיות שיחלפו כמה דקות עד ש-GKE יפרוס את המשאבים.
מוודאים שהפריסה של שער הגישה בוצעה בהצלחה:
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 הנלווה כדי לחשוף את האפליקציה שלו דרך שער external-http שנוצר בקטע הקודם.
מידע נוסף על שדות HTTPRoute זמין במפרט ה-API.
פורסים את האפליקציה לדוגמה באשכול:
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.מוודאים שהפריסה של האפליקציה הצליחה:
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מוודאים שהשירותים נפרסו בהצלחה:
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
משאבי ניתוב מגדירים כללים ספציפיים לפרוטוקול למיפוי תנועה משערים (Gateway) לשרתי קצה עורפיים של Kubernetes. רכיב HTTPRoute מבצע התאמה וסינון של תנועת HTTP ו-HTTPS, ונתמך על ידי כל רכיבי gke-l7-* GatewayClass.
בקטע הזה, פורסים HTTPRoute, שמגדיר את ה-Gateway עם כללי הניתוב שנדרשים כדי להגיע לאפליקציית הדוגמה.
שומרים את המניפסט הבא בקובץ בשם
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-httpGateway.מחילים את המניפסט על האשכול:
kubectl apply -f store-route-external.yamlHTTPRoute
storeקשור ל-Gatewayexternal-httpבאמצעות המאפייןparentRefs. בתרשים הבא מוצגים כללי הניתוב שהוגדרו במאזן העומסים הבסיסי:כללי הניתוב מעבדים תנועת HTTP באופן הבא:
- תנועה אל מסלולי
store.example.com/deאל שירותstore-german. - תנועת נתונים אל
store.example.comעם כותרת HTTP"env: canary"מנותבת אל שירותstore-v2. - התנועה שנותרה אל
store.example.comמנותבת לשירותstore-v1.
- תנועה אל מסלולי
מוודאים שרכיב ה-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", ...מוודאים ש-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.
שליחת תנועה לאפליקציה
עכשיו, אחרי שפרסתם את שער הכניסה, המסלול והאפליקציה באשכול, אתם יכולים להעביר תנועה לאפליקציה.
קבלת כתובת ה-IP של השער:
kubectl get gateways.gateway.networking.k8s.io external-http -o=jsonpath="{.status.addresses[0].value}"הפלט הוא כתובת IP.
יוצרים מכונה וירטואלית:
gcloud cloud-shell sshשליחת תנועה לכתובת ה-IP של השער מהמכונה הווירטואלית. צריך להגדיר את כותרת המארח באופן ידני כי אתם לא הבעלים של שם המארח
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" }כדי לבדוק את ההתאמה לנתיב, עוברים לגרסה הגרמנית של שירות
storeבכתובתstore.example.com/de:curl https://store.example.com/de --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -vהפלט מאשר שהבקשה הוגשה על ידי
store-germanPod:{ "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" }שליחת תנועה לגרסת הקנרי של שירות
storeבאמצעות כותרת ה-HTTPenv: canary:curl -H "env: canary" https://store.example.com --resolve store.example.com:443:GATEWAY_IP_ADDRESS --cacert cacert.pem -vהפלט מאשר שהבקשה הוגשה על ידי
store-v2Pod:{ "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" }
פריסת שער חיצוני אזורי
בדוגמה הבאה מוצג אופן החשיפה של אפליקציית חנות עם כמה אישורים שמצורפים לשער חיצוני אזורי באמצעות אישורים בניהול עצמי ו-HTTPRoute.
יצירת תת-רשת של שרת proxy לשער אזורי
כדי ליצור שער שמשתמש במאזן עומסים חיצוני אזורי של אפליקציות, צריך קודם להגדיר רשת משנה לשימוש פרוקסי בלבד. לכל אזור ברשת VPC שבה משתמשים במאזן עומסים חיצוני אזורי של אפליקציות (ALB) צריך להיות external_managed_proxy רשת משנה. רשת המשנה הזו מספקת כתובות IP פנימיות לשרתי ה-proxy של מאזן העומסים.
יצירת אישור לאבטחת תנועת הלקוחות
אתם יכולים להשתמש באישור שהונפק ואומת על ידי רשות האישורים (CA) שלכם או ליצור אישור עם חתימה עצמית. מידע נוסף על יצירת אישור זמין במאמר בנושא אחסון אישור ב-Kubernetes Secret.
כדי לאבטח את התעבורה בין הלקוחות לבין השער האזורי, אפשר להשתמש בשיטות הבאות:
- אישורים שמנוהלים על ידי Google או שמנוהלים באופן עצמאי ב-Certificate Manager
- אישורי SSL אזוריים בניהול עצמי
- סודות של Kubernetes
CertificateMap או אישורי SSL בניהול Google לא נתמכים עם שערים אזוריים.
מידע נוסף זמין במאמר בנושא אישורים ומאזני עומסים. Google Cloud
יצירת שער HTTP(S) חיצוני אזורי
יוצרים כתובת IP סטטית אזורית למאזן העומסים החיצוני.
gcloud compute addresses create IP_ADDRESS_NAME \ --region=COMPUTE_REGION \ --network-tier=STANDARDמחליפים את מה שכתוב בשדות הבאים:
-
IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה. -
COMPUTE_REGION: האזור ב-Compute Engine שבו האשכול פועל.
-
יוצרים שער אזורי חיצוני של מאזן עומסים של אפליקציות באמצעות אישור בניהול עצמי באופן הבא ושומרים את המניפסט כ-
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החלת מניפסט
regional-gateway:kubectl apply -f regional-gateway.yamlמאמתים את ההגדרה.
kubectl get gatewayהפלט אמור להיראות כך:
NAME CLASS ADDRESS READY AGE external-http gke-l7-regional-external-managed 35.118.32.224 True 49sכדי לקבל פרטים נוספים, משתמשים בפקודה describe:
kubectl describe gatewayהפלט אמור להיראות כך:
Name: external-regional-http Namespace: default Labels: <none> ... Spec: Gateway Class Name: gke-l7-regional-external-managed Listeners: Allowed Routes: Namespaces: From: Same Name: https Port: 443 Protocol: HTTPS Tls: Certificate Refs: Group: Kind: Secret Name: store-example-com Mode: Terminate ...
פריסת אפליקציית ההדגמה
אתם יכולים לפרוס את האפליקציות והמסלולים שלכם בנפרד מהפריסה של שערים.
מידע נוסף על פריסת אפליקציות ההדגמה זמין במאמר פריסת אפליקציות ההדגמה.
יצירת HTTPRoute
כדי להתאים ולסנן תנועה של HTTP ו-HTTPS, צריך ליצור HTTPRoute.
שליחת תנועה לאפליקציה
אחרי שפורסים את האפליקציה ויוצרים HTTPRoutes, אפשר להעביר תנועה לאפליקציה.
מידע נוסף על שליחת תעבורה לאפליקציה זמין במאמר בנושא שליחת תעבורה לאפליקציה.
שימוש בשערי גישה משותפים
Gateway API משתמש במשאבים נפרדים, משאבי Gateways ו-Route, כדי לפרוס מאזני עומסים וכללי ניתוב. ההגדרה הזו שונה מ-Ingress, שמשלבת את הכול במשאב אחד. ה-Gateway מאפשר לפצל את האחריות בין המשאבים, כך שניתן לפרוס את מאזן העומסים ואת כללי הניתוב שלו בנפרד, ומשתמשים או צוותים שונים יכולים לפרוס אותם. כך שערים יכולים להפוך לשערים משותפים שמצורפים למסלולים שונים רבים, שאפשר להיות הבעלים שלהם ולנהל אותם על ידי צוותים עצמאיים, גם במרחבי שמות שונים.
פריסת מסלולים מול שער משותף
הדוגמה הזו מבוססת על internal-http השער שנפרס בפריסת שער פנימי.
בדוגמה הזו, צוות האתר פורס את האפליקציה, את השירותים ואת HTTPRoute כדי להתאים את התנועה מהשער לשירותים האלה.
מפעילים את האפליקציה לדוגמה:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/app/site.yamlשומרים את המניפסט הבא בקובץ בשם
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.מחילים את המניפסט על האשכול:
kubectl apply -f site-route-internal.yamlמוודאים ש-HTTPRoute מצורף ל-Gateway:
kubectl describe httproute.gateway.networking.k8s.io site-internalהפלט אמור להיראות כך:
Status: Parents: Conditions: Last Transition Time: 2023-01-09T15:05:43Z Message: Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-01-09T15:05:43Z Message: Reason: ReconciliationSucceeded Status: True Type: Reconciled Controller Name: networking.gke.io/gateway Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: internal-http ...אם התנאי
Acceptedשל שער הכניסה הואTrue, ה-HTTPRoute נקשר בהצלחה לשער הכניסה. מידע נוסף על השדה 'סטטוס' זמין במאמר בנושא סטטוס המסלול.מוודאים שהתנועה אל שער הכניסה מנותבת בצורה נכונה:
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.
הגדרת מסלול רשת
אתם יכולים לציין את מסלול הרשת של כתובת המאזין של מאזן עומסים חיצוני אזורי של אפליקציות באמצעות השדה type במערך addresses[] בהגדרת שער. אם לא מציינים מסלול רשת, כברירת מחדל מוגדרת כתובת IP ארעית במסלול הרגיל לשער.
משתמשים בערכים הבאים בשדה type:
-
networking.gke.io/premium-ephemeral-ipv4-address: מקצה כתובת IP ברמת פרימיום. -
networking.gke.io/standard-ephemeral-ipv4-address: מקצה כתובת IP ברמה Standard.
כדי להקצות כתובות IP משני מסלולי הרשת, מציינים את שני הסוגים בשדה addresses.
בדוגמה הבאה אפשר לראות איך להקצות כתובת IP ברמת מסלול פרימיום לשער. Google Cloud כדי להקצות כתובת IP במסלול הרגיל, משתמשים ב-networking.gke.io/standard-ephemeral-ipv4-address.
שומרים את קובץ המניפסט לדוגמה הבא בשם
external-regional-http.yaml:kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-regional-http spec: # Name of an existing GatewayClass. gatewayClassName: gke-l7-regional-external-managed # Listen for HTTPS traffic on port 443. listeners: - name: https protocol: HTTPS port: 443 tls: # Terminate the TLS session with the client at the Gateway. mode: Terminate # Certificates for the Gateway to use to create a new TLS session. certificateRefs: - name: store-example-com addresses: # Request a Premium Tier ephemeral IPv4 address for the Gateway. - type: networking.gke.io/premium-ephemeral-ipv4-addressהחלת המניפסט לדוגמה:
kubectl apply -f external-regional-http.yaml
הגדרת קצה עורפי שמוגדר כברירת מחדל בשער
כל ה-GatewayClasses gke-l7-* מחזירים HTTP 404 לתנועה שלא תואמת. אפשר להגדיר את קצה העורף (backend) כברירת מחדל באמצעות מסלול ברירת מחדל מפורש ששולח תנועה לא תואמת לשירות שסופק על ידי המשתמש.
הגדרנו את השערים כך שיטפלו בקודי שגיאה כמו 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 הזה תואם לכל התנועה משער מסוים. אפשר להגדיר רק כלל אחד כזה לכל שער, אחרת הכללים יתנגשו וסדר העדיפות יחול.
אתם יכולים להשתמש בשרת קצה עורפי שמוגדר כברירת מחדל כדי למנוע ממישהו ליצור נתיב ברירת מחדל שרת קצה עורפי שמנתב את כל התנועה של שער. ל-HTTPRoute מפורש תמיד יש עדיפות על פני HTTPRoute חדש עם כללי ניתוב סותרים.
הגדרת כתובת IP סטטית לשער
לכל שער יש כתובת IP שמשמשת אותו להאזנה לתנועה. אם לא מציינים כתובת IP בשער, בקר השער מספק כתובת IP באופן אוטומטי. אפשר גם ליצור כתובת IP סטטית, כך שכתובת ה-IP תתקיים ללא תלות במחזור החיים של שער הרשת.
אחרי פריסת שער, כתובת ה-IP שלו מופיעה בשדה הסטטוס:
kind: Gateway
...
status:
addresses:
- value: 10.15.32.3
בהתאם ל-GatewayClass, כתובת ה-IP מוקצית מרשתות המשנה הבאות:
| GatewayClasses | מאגר כתובות IP שמוגדר כברירת מחדל |
|---|---|
|
|
כתובות IP פרטיות אזוריות מטווח כתובות ה-IPv4/IPv6 של הצומת הראשי |
|
|
כתובות IP ציבוריות אזוריות מטווחים אזוריים של כתובות IPv4/IPv6 חיצוניות של Google |
|
|
כתובות IP ציבוריות גלובליות מטווחים גלובליים של IPv4/IPv6 חיצוניים של Google |
בשדה addresses.NamedAddress אפשר לציין כתובת IP בנפרד מהשער. אפשר ליצור משאב של כתובת IP סטטית לפני פריסת שער, והמשאב מפנה אל NamedAddress. אפשר לעשות שימוש חוזר בכתובת ה-IP הסטטית גם אם השער נמחק.
שימוש בכתובת IP עם שם
אפשר להגדיר כתובת IPv4 או IPv6 על ידי ציון NamedAddress. לפני שיוצרים שער, צריך להקצות כתובת IP סטטית.
יוצרים משאב של כתובת IP סטטית:
gcloud compute addresses create IP_ADDRESS_NAME \ --purpose=SHARED_LOADBALANCER_VIP \ --region=COMPUTE_REGION \ --subnet=SUBNET \ --project=PROJECT_IDמחליפים את מה שכתוב בשדות הבאים:
-
IP_ADDRESS_NAME: השם של כתובת ה-IP הסטטית החדשה -
COMPUTE_REGION: עבור שערים אזוריים, האזור ב-Compute Engine שבו האשכול פועל. אין צורך בדגל הזה בשערים גלובליים חיצוניים. -
SUBNET: רשת המשנה של כתובת ה-IP. אין צורך בדגל הזה בשערים גלובליים חיצוניים. -
PROJECT_ID: הפרויקט שבו פועל אשכול GKE.
-
שומרים את המניפסט הבא בקובץ בשם
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 שצוינה בשם.
מחילים את המניפסט על האשכול:
kubectl apply -f named-ip-gateway.yamlמאמתים את כתובת ה-IP של השער:
kubectl describe gateway internal-httpהפלט אמור להיראות כך:
Name: internal-http Namespace: default Labels: <none> ... Spec: Addresses: Type: NamedAddress Value: IP_ADDRESS_NAME Gateway Class Name: gke-l7-rilb Listeners: Allowed Routes: Namespaces: From: Same Name: http Port: 80 Protocol: HTTP Status: Addresses: Type: IPAddress Value: 10.15.32.103
הגדרת הפניות אוטומטיות מ-HTTP ל-HTTPS
שירות Cloud Load Balancing מציע פונקציונליות של הפניה אוטומטית מ-HTTP ל-HTTPS. מאזן עומסים חיצוני של אפליקציות מפנה בקשות 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 ממרחב שמות של תשתית
במקרים מסוימים, אין הבחנה ברורה בין צוות האדמינים של התשתית או הפלטפורמה לבין צוותי האפליקציות, ולכן יכול להיות קשה למנוע שימוש לרעה בשער.
בדוגמה הבאה מוצגת הגבלה נוספת של השימוש במאזין HTTP כדי למנוע שימוש לא מכוון בפרוטוקול לא מאובטח מצד צוותי האפליקציה. בדוגמה הזו מוגדר שער שיאפשר ל-HTTPRoute להשתמש במאזין HTTP רק אם המסלול נמצא במרחב שמות עם התווית otherInfra: httpToHttps. עם זאת,
השער מאפשר ל-HTTPRoutes בכל מרחב שמות להשתמש במאזין HTTPS. אפשר להגביל את מרחב השמות http-redirect באמצעות Kubernetes RBAC, כדי שצוותי פיתוח אפליקציות לא יוכלו ליצור בטעות HTTPRoute במרחב השמות הזה.
יוצרים את מרחב השמות של שער. שומרים את קובץ המניפסט בשם
gateway-namespace.yaml:apiVersion: v1 kind: Namespace metadata: name: gateway-infraהחלת המניפסט:
kubectl apply -f gateway-namespace.yamlיוצרים את מרחב השמות של שער ושומרים את המניפסט כ-
redirect-namespace.yaml:apiVersion: v1 kind: Namespace metadata: name: http-redirect labels: otherInfra: httpToHttpsמרחב השמות
http-redirectכולל את התוויתotherInfra: httpToHttps.החלת המניפסט:
kubectl apply -f redirect-namespace.yamlכדי להגביל את השימוש במאזין http, יוצרים Gateway באמצעות המניפסט הבא. שומרים את קובץ המניפסט בשם
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.
החלת המניפסט:
kubectl apply -f external-gateway.yamlכדי לכפות את ההפניה האוטומטית ל-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מורה ל-Gateway להתאים רק ל-http listener. המסנןRequestRedirectכופה את ההפניה למאזין https.
- השדה
החלת המניפסט:
kubectl apply -f http-redirect.yamlיוצרים שירות לאפליקציה באמצעות המניפסט הבא. שומרים את קובץ המניפסט בשם
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"החלת המניפסט:
kubectl apply -f service-deployment.yamlיוצרים 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החלת המניפסט:
kubectl apply -f http-route.yaml
הגדרת הפניות אוטומטיות של נתיבים ושכתוב של כתובות URL
הפניות אוטומטיות של נתיבים כוללות הפניה אוטומטית של בקשה נכנסת מנתיב כתובת URL אחד לנתיב אחר. הפניות נתיב מאפשרות לשנות את מבנה כתובת ה-URL כשצריך לטפל בכתובות URL מיושנות או שהוצאו משימוש.
שינוי כתובות URL עוזר לשנות את כתובת ה-URL הנכנסת לפני העיבוד שלה בשרת. היא מאפשרת לשנות את המבנה או הפורמט של כתובת ה-URL בלי לשנות בפועל את התוכן או את מבנה הקובץ. שיכתוב כתובות URL מועיל ליצירת כתובות URL ידידותיות למשתמש ולקידום אתרים (SEO), שקל לזכור ולהבין. כברירת מחדל, הפניות אוטומטיות של נתיבים ושכתוב של כתובות URL לא מוגדרים, ולכן צריך להגדיר אותן באופן מפורש באמצעות מסנן ב-HTTPRoute.
GKE Gateway תומך בהפניות אוטומטיות של נתיבים ובשכתוב של כתובות URL. מידע נוסף זמין במאמר בנושא הפניות אוטומטיות ושכתוב של נתיבי HTTP.
הגדרת הפניות אוטומטיות של נתיבים
אפשר להגדיר הפניות אוטומטיות של נתיבים כך שיחליפו את הנתיב כולו או רק את הקידומת בכתובת ה-URL.
החלפת הנתיב כולו
כדי להחליף נתיב שלם, מגדירים מסנן ב-HTTPRoute שמחליף כל כתובת URL שמכילה את הקידומת
/any-pathבנתיב כתובת ה-URL בערך המדויק/new-path.יוצרים קובץ מניפסט
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/(strict).החלת המניפסט:
kubectl apply -f store.yaml
כלל הניתוב הזה פועל לפי כלל הפניה קפדני, כלומר הדפדפן לא מנסה לשמור במטמון את ההפניה, אלא מפנה לגרסה העדכנית ביותר.
החלפת קידומת בלבד
כדי להחליף רק קידומת, מגדירים מסנן ב-HTTPRoute שמחליף כל כתובת URL שמכילה את הקידומת
/any-prefixבנתיב כתובת ה-URL בערך המדויק/new-prefix.יוצרים קובץ מניפסט
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/...(בלבד).החלת המניפסט:
kubectl apply -f store.yaml
כלל הניתוב הזה פועל לפי כלל ההפניה האוטומטית היחיד, שמבטיח שהדפדפן תמיד יפנה אתכם לאותו דף שרציתם להגיע אליו.
הגדרת כתיבה מחדש של כתובות URL
הגדרת כתיבה מחדש של כתובות URL כדי לשנות את האופן שבו כתובת URL מוצגת למשתמשים. אפשר להשתמש בשכתוב כתובות URL כדי להפוך אותן לידידותיות יותר למשתמשים, כדי לשפר את ה-SEO או כדי להפנות משתמשים לדף חדש.
לשכתב את שם המארח כולו
כדי לשכתב את שם המארח כולו:
מגדירים מסנן ב-HTTPRoute שמורה ל-Gateway להחליף את המידע
Hostבכותרת הבקשה מ-www.example.comל-store.example.comלפני העברת הבקשה לשירות לקצה העורפי.יוצרים קובץ מניפסט
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.החלת המניפסט:
kubectl apply -f www.yaml
כתיבה מחדש באמצעות משני נתיבים
אפשר לשלב בין שינוי כתובות URL לבין שינוי נתיבים כדי לבצע שינויים מתקדמים בכתובות URL ובנתיבים לפני העברת הבקשה לשירות לקצה העורפי.
כדי לשכתב באמצעות משני נתיבים:
מגדירים מסנן ב-HTTPRoute שמורה ל-Gateway להחליף את פרטי ה-Host בכותרת הבקשה מ-www.example.com
to store.example.comולהחליף את הערך/storeב-/לפני העברת הבקשה לשירות הקצה העורפי.יוצרים קובץ מניפסט
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.החלת המניפסט:
kubectl apply -f www.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
הגדרת כותרות מותאמות אישית של בקשות ותגובות
כותרות מותאמות אישית של בקשות ותגובות מאפשרות לכם לציין כותרות נוספות לבקשות ולתגובות של 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
אימות ההגדרות את ההגדרות
כדי לאמת את ההגדרה אחרי שמגדירים כותרות מותאמות אישית של בקשות ותגובות:
kubectl get httprouteהפלט אמור להיראות כך:
NAME HOSTNAMES AGE store ["store.example.com"] 4d23hכדי לקבל פרטים נוספים, משתמשים בפקודה 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: <...>
סטטוס המסלול
משאבי HTTPRoute פולטים תנאים ואירועים כדי לעזור למשתמשים להבין אם משאב HTTPRoute נקשר בהצלחה לשער אחד או יותר או אם הוא נדחה.
תנאים של HTTPRoute
תנאי HTTPRoute מציינים את הסטטוס של המסלול והשערים שהוא משויך אליהם. מכיוון שאפשר לקשר מסלול לכמה שערים, זוהי רשימה של שערים והתנאים הספציפיים בין המסלול לכל שער.
-
Accepted=Trueמציין ש-HTTPRoute קשור בהצלחה ל-Gateway. -
Accepted=Falseמציין ש-HTTPRoute נדחה מקישור ל-Gateway הזה.
אם אין שערים שמופיעים מתחת לכותרת Gateway bindings, יכול להיות שתוויות ה-HTTPRoute ובוררי התוויות של השער לא תואמים. מצב כזה יכול לקרות אם אף שער לא בוחר את המסלול שלכם.
אירועים של HTTPRoute
אירועי HTTPRoute מספקים פרטים על הסטטוס של HTTPRoute. האירועים מקובצים לפי הסיבות הבאות:
ADDאירועים מופעלים כשמוסיפים משאב.- אירועי
UPDATEמופעלים כשמשאב מתעדכן. - אירועי
SYNCמופעלים על ידי התאמה תקופתית.
מיזוג נתיבים, קדימות ואימות
קדימות של מסלולים
Gateway API מגדיר כללי קדימות מחמירים לגבי האופן שבו תנועה מותאמת לנתיבים עם כללי ניתוב חופפים. הקדימות בין שני נתיבי HTTP חופפים היא כדלקמן:
- מיזוג של שמות מארחים: ההתאמה הארוכה או הספציפית ביותר של שם המארח.
- מיזוג נתיבים: ההתאמה לנתיב הארוך או הספציפי ביותר.
- מיזוג כותרות: המספר הגדול ביותר של כותרות HTTP שתואמות.
- התנגשות: אם שלוש הכללים הקודמים לא קובעים סדר עדיפות, סדר העדיפות נקבע לפי משאב HTTPRoute עם חותמת הזמן הכי ישנה.
מיזוג מסלולים
ב-gke-l7 GatewayClasses, כל ה-HTTPRoutes של Gateway נתון ממוזגים לאותו משאב של מפת URL. אופן המיזוג של רכיבי HTTPRoutes תלוי בסוג החפיפה ביניהם. כדי להמחיש את מיזוג המסלולים ואת סדר העדיפויות, אפשר לפצל את HTTPRoute מהדוגמה הקודמת לשלושה HTTPRoute נפרדים:
- מיזוג של נתיבים: כל שלושת נתיבי ה-HTTP מצורפים לאותו
internal-httpGateway, ולכן הם ממוזגים יחד. - מיזוג של שמות מארחים: כל שלושת המסלולים תואמים ל-
store.example.com, ולכן כללי שם המארח שלהם ממוזגים. - מיזוג נתיבים: הנתיב store-german-route הוא ספציפי יותר
/de, ולכן הוא לא עובר מיזוג נוסף. הנתיבים store-v1-route ו-store-v2-route תואמים שניהם לנתיב/*זהה, ולכן הם עוברים מיזוג בנתיב. - מיזוג כותרות: ל-store-v2-route יש קבוצה ספציפית יותר של התאמות כותרות HTTP מאשר ל-store-v1-route, ולכן הן לא ממוזגות יותר.
- התנגשות: מכיוון שאפשר למזג את המסלולים לפי שם המארח, הנתיב והכותרות, אין התנגשויות וכל כללי הניתוב חלים על התנועה.
ה-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 ואילך, מומלץ להתחיל להשתמש בשם הקצר של משאב Gateway או לציין את קבוצת ה-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 בלבד באזור
התסמין:
יכול להיות שתיתקלו בבעיה הבאה כשתיצרו שער אזורי (פנימי או חיצוני):
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 בלבד.
כבר קיימת רשת משנה מסוג 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 בלבד.
פתרון עקיף:
כדי לפתור את הבעיה, מבצעים את השלבים הבאים:
צריך לבדוק שרשת משנה מסוג proxy-only כבר קיימת באזור, ולוודא שהמטרה שלה נכונה:
מציגים את רשימת רשתות המשנה כדי לראות איזו מהן היא רשת המשנה של שרת proxy בלבד באזור:
gcloud compute networks subnets list --regions=COMPUTE_REGIONמחליפים את
COMPUTE_REGIONבאזור Compute Engine שבו רוצים ליצור את שער אזורי.מתארים את רשת המשנה של ה-proxy באזור כדי להבין מה המטרה שלה:
gcloud compute networks subnets describe PROXY_ONLY_SUBNET \ --region COMPUTE_REGION | grep -E 'name|purpose'מחליפים את
PROXY_ONLY_SUBNETברשת המשנה של ה-proxy בלבד.
GKE Gateway תומך רק ברשתות משנה של
REGIONAL_MANAGED_PROXYproxy-only עבור שערים אזוריים (פנימיים או אזוריים).אם רשת המשנה הקיימת באזור שמוגדרת רק כפרוקסי נוצרה עם מטרה
INTERNAL_HTTPS_LOAD_BALANCER, צריך להעביר את המטרה שלה ל-REGIONAL_MANAGED_PROXY.
אין מקור תקין
התסמין:
יכולה להתרחש הבעיה הבאה כשיוצרים Gateway אבל אין גישה לשירותי ה-Backend (קוד תגובה 503):
no healthy upstream
הסיבה:
הודעת השגיאה הזו מציינת שכלי הבדיקה של בדיקת תקינות לא יכול למצוא שירותי קצה עורפיים תקינים. יכול להיות שהשירותים שלכם ב-Backend תקינים, אבל תצטרכו להתאים אישית את בדיקות התקינות.
פתרון עקיף:
כדי לפתור את הבעיה, מתאימים אישית את בדיקת התקינות בהתאם לדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.
המאמרים הבאים
- מידע נוסף על בקר שער
- איך מגדירים משאבי Gateway באמצעות מדיניות
- מידע נוסף על תצורות אחרות של שערים זמין בתיעוד של Gateway API.