במסמך הזה מוסבר איך לפרוס אפליקציה לדוגמה בשני אשכולות GKE באזורים שונים, ואיך שער רב-אשכולות מנתב תעבורה בצורה חכמה כשהיא חורגת ממגבלות הקיבולת של השירות.
איזון עומסים מבוסס-קיבולת הוא תכונה של שערים מרובי אשכולות שעוזרת לכם ליצור אפליקציות אמינות ועמידות במיוחד. הגדרת הקיבולת של השירותים עוזרת להגן עליהם מפני עומס יתר ומבטיחה חוויה עקבית למשתמשים. כשקיבולת של שירות באחד האשכולות מגיעה למקסימום, מאזן העומסים מפנה אוטומטית את התנועה לאשכול אחר עם קיבולת פנויה. מידע נוסף על ניהול תנועה זמין במאמר ניהול תנועה ב-GKE.
במדריך הזה משתמשים באפליקציית store לדוגמה כדי לדמות תרחיש מהעולם האמיתי שבו שירות קניות אונליין נמצא בבעלות ובהפעלה של צוותים נפרדים, ונפרס בצי של אשכולות GKE משותפים.
לפני שמתחילים
כדי לפרוס שערים מרובי-אשכולות, צריך לבצע הכנה מסוימת של הסביבה. לפני שממשיכים, פועלים לפי השלבים שמפורטים במאמר הכנת הסביבה לשימוש בשערי גישה מרובי-אשכולות:
פריסה של אשכולות GKE.
רושמים את האשכולות ב-Fleet (אם הם עדיין לא רשומים).
מפעילים את בקרי השירות מרובי האשכולות והשער מרובה האשכולות.
לבסוף, מומלץ לעיין במגבלות ובבעיות הידועות של GKE Gateway Controller לפני שמשתמשים בבקר בסביבה שלכם.
פריסת איזון עומסים מבוסס-קיבולת
בתרגיל שבקטע הזה נדגים איזון עומסים גלובלי ומושגים שקשורים לקיבולת של שירותים, על ידי פריסת אפליקציה בשני אשכולות GKE באזורים שונים. התעבורה שנוצרת נשלחת ברמות שונות של בקשות לשנייה (RPS) כדי להראות איך מתבצע איזון עומסים של התעבורה בין אשכולות ואזורים.
התרשים הבא מציג את הטופולוגיה שתפרסו ואת האופן שבו תעבורת נתונים גולשת בין אשכולות ואזורים כשתעבורת הנתונים חורגת מהקיבולת של השירות:
הכנת הסביבה
כדי להכין את הסביבה, פועלים לפי ההוראות שבמאמר הכנת הסביבה לשימוש בשערי גישה מרובי-אשכולות.
מוודאים שמשאבי GatewayClass מותקנים באשכול ההגדרות:
kubectl get gatewayclasses --context=gke-west-1הפלט אמור להיראות כך:
NAME CONTROLLER ACCEPTED AGE gke-l7-global-external-managed networking.gke.io/gateway True 16h gke-l7-global-external-managed-mc networking.gke.io/gateway True 14h gke-l7-gxlb networking.gke.io/gateway True 16h gke-l7-gxlb-mc networking.gke.io/gateway True 14h gke-l7-regional-external-managed networking.gke.io/gateway True 16h gke-l7-regional-external-managed-mc networking.gke.io/gateway True 14h gke-l7-rilb networking.gke.io/gateway True 16h gke-l7-rilb-mc networking.gke.io/gateway True 14h
פריסת אפליקציה
פורסים את שרת אפליקציית האינטרנט לדוגמה בשני האשכולות:
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
הפלט אמור להיראות כך:
namespace/store created
deployment.apps/store created
פריסת שירות, שער ו-HTTPRoute
מחילים את מניפסט
Serviceהבא על אשכולותgke-west-1ו-gke-east-1:cat << EOF | kubectl apply --context gke-west-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOFcat << EOF | kubectl apply --context gke-east-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOFהשירות מסומן ב-
max-rate-per-endpointעם הערך 10 בקשות לשנייה. עם 2 רפליקות לכל אשכול, לכל שירות יש קיבולת של 20 RPS לכל אשכול.מידע נוסף על בחירת רמת הקיבולת של השירות זמין במאמר קביעת הקיבולת של השירות.
מחילים את
Gatewayהמניפסטgke-west-1הבא על אשכול ההגדרות,gke-west-1בדוגמה הזו:cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOFקובץ המניפסט מתאר שער חיצוני גלובלי מרובה-אשכולות שמפעיל מאזן עומסים של אפליקציות (ALB) חיצוני עם כתובת IP שנגישה לכולם.
מחילים את
HTTPRouteהמניפסטgke-west-1הבא על אשכול ההגדרות,gke-west-1בדוגמה הזו:cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test labels: gateway: store spec: parentRefs: - kind: Gateway namespace: traffic-test name: store rules: - backendRefs: - name: store group: net.gke.io kind: ServiceImport port: 8080 EOFקובץ המניפסט מתאר HTTPRoute שמגדיר את ה-Gateway עם כלל ניתוב שמפנה את כל התנועה אל ServiceImport של החנות. הקבוצה
storeServiceImport מקבצת אתstoreService Pods בשני האשכולות ומאפשרת למאזן העומסים להתייחס אליהם כשירות יחיד.אפשר לבדוק את האירועים של השער אחרי כמה דקות כדי לראות אם הפריסה הסתיימה:
kubectl describe gateway store -n traffic-test --context gke-west-1הפלט אמור להיראות כך:
... Status: Addresses: Type: IPAddress Value: 34.102.159.147 Conditions: Last Transition Time: 2023-10-12T21:40:59Z 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: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit 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 Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit 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 Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 12m mc-gateway-controller traffic-test/store Normal SYNC 6m43s mc-gateway-controller traffic-test/store Normal UPDATE 5m40s (x4 over 12m) mc-gateway-controller traffic-test/store Normal SYNC 118s (x6 over 10m) mc-gateway-controller SYNC on traffic-test/store was a successהפלט הזה מראה שהפריסה של שער הגישה בוצעה בהצלחה. יכול להיות שיחלפו כמה דקות עד שהתנועה תתחיל לעבור אחרי פריסת שער. שימו לב לכתובת ה-IP בפלט הזה, כי תצטרכו אותה בשלב הבא.
אישור התנועה
כדי לוודא שהתנועה עוברת לאפליקציה, בודקים את כתובת ה-IP של השער באמצעות פקודת curl:
curl GATEWAY_IP_ADDRESS
הפלט אמור להיראות כך:
{
"cluster_name": "gke-west-1",
"host_header": "34.117.182.69",
"pod_name": "store-54785664b5-mxstv",
"pod_name_emoji": "👳🏿",
"project_id": "project",
"timestamp": "2021-11-01T14:06:38",
"zone": "us-west1-a"
}
בפלט הזה מוצגים המטא-נתונים של ה-Pod, שמציינים את האזור שממנו הבקשה נשלחה.
אימות התנועה באמצעות בדיקות עומס
כדי לוודא שמאזן העומסים פועל, אפשר לפרוס מחולל תנועה באשכול gke-west-1. מחולל התנועה יוצר תנועה ברמות עומס שונות כדי להדגים את הקיבולת ואת יכולות הגלישה של מאזן העומסים. השלבים הבאים מראים שלוש רמות של עומס:
- 10 בקשות לשנייה, שזה מתחת לקיבולת של שירות החנות ב-
gke-west-1. - 30 בקשות לשנייה, שזו חריגה מהקיבולת של שירות החנות
gke-west-1וגורמת לעומס תנועה בשירותgke-east-1. - 60 RPS, שזה מעל הקיבולת של השירותים בשני האשכולות.
הגדרת לוח הבקרה
מקבלים את השם של מיפוי כתובות ה-URL הבסיסי בשער:
kubectl get gateway store -n traffic-test --context=gke-west-1 -o=jsonpath="{.metadata.annotations.networking\.gke\.io/url-maps}"הפלט אמור להיראות כך:
/projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1tנכנסים לדף Metrics explorer במסוף Google Cloud .
בקטע Select a metric (בחירת מדד), לוחצים על CODE: MQL (קוד: MQL).
מזינים את השאילתה הבאה כדי לראות את מדדי התנועה של שירות החנות בשני האשכולות:
fetch https_lb_rule | metric 'loadbalancing.googleapis.com/https/backend_request_count' | filter (resource.url_map_name == 'GATEWAY_URL_MAP') | align rate(1m) | every 1m | group_by [resource.backend_scope], [value_backend_request_count_aggregate: aggregate(value.backend_request_count)]מחליפים את
GATEWAY_URL_MAPבשם של מיפוי ה-URL מהשלב הקודם.לוחצים על Run query. אחרי שמפעילים את מחולל העומסים שמתואר בקטע הבא, צריך להמתין לפחות 5 דקות עד שהמדדים יופיעו בתרשים.
בדיקה עם 10 RPS
פריסת Pod באשכול
gke-west-1:kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 10'מחליפים את
GATEWAY_IP_ADDRESSבכתובת ה-IP של השער מהשלב הקודם.הפלט אמור להיראות כך, ולציין שמחולל התנועה שולח תנועה:
If you don't see a command prompt, try pressing enter.מחולל העומסים שולח באופן רציף 10 בקשות לשנייה (RPS) אל שער הכניסה. למרות שתעבורת הנתונים מגיעה מאזור Google Cloud , מאזן העומסים מתייחס אליה כתעבורת נתונים של לקוחות שמגיעה מהחוף המערבי של ארה"ב. כדי לדמות מגוון לקוחות ריאליסטי, מחולל העומסים שולח כל בקשת HTTP כחיבור TCP חדש, מה שאומר שהתנועה מתחלקת בין ה-Pods של ה-Backend בצורה שווה יותר.
תהליך יצירת התנועה למרכז הבקרה יימשך עד 5 דקות.
צפייה בלוח הבקרה של Metrics Explorer. מופיעות שתי שורות שמציינות כמה תנועה מאוזנת בעומס לכל אחד מהאשכולות:

אפשר לראות ש-
us-west1-aמקבלת תנועה של כ-10 בקשות לשנייה, ואילוus-east1-bלא מקבלת תנועה. מכיוון שגנרטור התנועה פועל ב-us-west1, כל התנועה נשלחת לשירות באשכולgke-west-1.מפסיקים את מחולל העומסים באמצעות Ctrl+C, ואז מוחקים את ה-pod:
kubectl delete pod loadgen --context gke-west-1
בדיקה עם 30 בקשות לשנייה
מפעילים מחדש את מחולל העומסים, אבל מגדירים אותו לשליחת 30 בקשות לשנייה:
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 30'תהליך יצירת התנועה למרכז הבקרה יימשך עד 5 דקות.
צופים במרכז הבקרה של Cloud Ops.

אמור להופיע ש-20 RPS נשלחים אל
us-west1-aו-10 RPS אלus-east1-b. המשמעות היא שהשירות ב-gke-west-1נמצא בשימוש מלא, ו-10 בקשות לשנייה של תעבורת נתונים מועברות לשירות ב-gke-east-1.מפסיקים את מחולל העומסים באמצעות Ctrl+C, ואז מוחקים את ה-Pod:
kubectl delete pod loadgen --context gke-west-1
בדיקה עם 60 בקשות לשנייה
פורסים את מחולל העומסים שהוגדר לשליחת 60 בקשות לשנייה:
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 60'ממתינים 5 דקות ומציגים את לוח הבקרה של Cloud Ops. עכשיו אמור להופיע ששני האשכולות מקבלים בערך 30 בקשות לשנייה. מכיוון שכל השירותים נמצאים בשימוש יתר ברחבי העולם, אין תנועה שגולשת מעבר לקיבולת והשירותים סופגים את כל התנועה שהם יכולים.

מפסיקים את מחולל העומסים באמצעות Ctrl+C, ואז מוחקים את ה-Pod:
kubectl delete pod loadgen --context gke-west-1
הסרת המשאבים
אחרי שתסיימו את התרגילים במסמך הזה, תצטרכו לפעול לפי השלבים הבאים כדי להסיר משאבים ולמנוע חיובים לא רצויים בחשבון:
ביטול הרישום של האשכולות ב-Fleet אם אין צורך לרשום אותם למטרה אחרת.
השבתת התכונה
multiclusterservicediscovery:gcloud container fleet multi-cluster-services disableהשבתת Multi Cluster Ingress:
gcloud container fleet ingress disableמשביתים את ממשקי ה-API:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
פתרון בעיות
אין מקור תקין
התסמין:
יכולה להתרחש הבעיה הבאה כשיוצרים Gateway אבל אין גישה לשירותי ה-Backend (קוד תגובה 503):
no healthy upstream
הסיבה:
הודעת השגיאה הזו מציינת שכלי הבדיקה של בדיקת תקינות לא יכול למצוא שירותי קצה עורפיים תקינים. יכול להיות שהשירותים שלכם ב-Backend תקינים, אבל תצטרכו להתאים אישית את בדיקות התקינות.
פתרון עקיף:
כדי לפתור את הבעיה, מתאימים אישית את בדיקת התקינות בהתאם לדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.