במאמר הזה נסביר איך לפרוס אפליקציה לדוגמה בשני אשכולות GKE באזורים שונים, ואיך Gateway עם כמה אשכולות מנתב את התנועה בצורה חכמה כשהיא חורגת ממגבלות הקיבולת של השירות.
איזון עומסים על סמך קיבולת הוא תכונה של שערים מרובי אשכולות שעוזרת לכם ליצור אפליקציות אמינות ועמידות במיוחד. הגדרת הקיבולת של השירותים עוזרת להגן עליהם מפני עומס יתר, ומבטיחה חוויה עקבית למשתמשים. כשקיבולת של שירות באשכול אחד מגיעה למקסימום, מאזן העומסים מפנה אוטומטית את התנועה לאשכול אחר עם קיבולת פנויה. מידע נוסף על ניהול תנועה זמין במאמר ניהול תנועה ב-GKE.
במדריך הזה משתמשים באפליקציית store לדוגמה כדי לדמות תרחיש מהעולם האמיתי שבו שירות קניות אונליין נמצא בבעלות ובהפעלה של צוותים נפרדים, ונפרס בצי של אשכולות GKE משותפים.
לפני שמתחילים
כדי לפרוס שערים מרובי-אשכולות, צריך לבצע הכנה סביבתית. לפני שממשיכים, פועלים לפי השלבים שמפורטים במאמר הכנת הסביבה לשימוש בשערי רשת מרובי-אשכולות:
פריסה של אשכולות GKE.
רושמים את האשכולות ב-Fleet (אם הם עדיין לא רשומים).
מפעילים את בקרי השירות מרובה האשכולות והשער מרובה האשכולות.
לסיום, כדאי לעיין במגבלות ובבעיות הידועות של בקר GKE Gateway לפני שמשתמשים בבקר בסביבה שלכם.
פריסת איזון עומסים מבוסס-קיבולת
בתרגיל שבקטע הזה נדגים איזון עומסים גלובלי ומושגים שקשורים לקיבולת של שירותים, על ידי פריסת אפליקציה בשני אשכולות 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
פריסה של Service, Gateway ו-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בדוגמה הזו: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בדוגמה הזו: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 שמגדיר את השער עם כלל ניתוב שמפנה את כל התנועה אל ServiceImport של החנות.
storeServiceImport מקבץ את ה-Pods שלstoreService בשני האשכולות, ומאפשר למאזן העומסים להתייחס אליהם כאל שירות אחד.אחרי כמה דקות, אפשר לבדוק את האירועים של השער כדי לראות אם הפריסה הסתיימה:
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 בקשות לשנייה, שזה מעבר לקיבולת של השירותים בשני האשכולות.
הגדרת לוח הבקרה
משיגים את השם של ה-URLmap הבסיסי של השער:
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 בקשות לשנייה
פורסים 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 בקשות לשנייה אל השער. למרות שתעבורת הנתונים מגיעה מתוך אזור 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 בקשות לשנייה נשלחות אל
us-west1-aו-10 בקשות לשנייה נשלחות אל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 RPS. מכיוון שכל השירותים נמצאים בשימוש יתר ברחבי העולם, אין תנועה שגולשת מעבר לקיבולת והשירותים סופגים את כל התנועה שהם יכולים.

מפסיקים את מחולל העומסים באמצעות 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
פתרון בעיות
אין מקור בריא
הסימפטום:
הבעיה הבאה עשויה להתרחש כשיוצרים שער אבל אין גישה לשירותי הקצה העורפי (קוד תגובה 503):
no healthy upstream
הסיבה:
הודעת השגיאה הזו מציינת שהבדיקה של תקינות השירות לא מוצאת שירותים תקינים לקצה העורפי. יכול להיות שהשירותים שלכם בבק-אנד תקינים, אבל תצטרכו להתאים אישית את בדיקות התקינות.
פתרון עקיף:
כדי לפתור את הבעיה, צריך להתאים אישית את בדיקת תקינות בהתאם לדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.