במאמר הזה מוסבר באמצעות דוגמה מעשית איך לפרוס שער פנימי של כמה אשכולות כדי לנתב תעבורה בתוך רשת ה-VPC לאפליקציה שפועלת בשני אשכולות GKE שונים.
שערים מרובי אשכולות הם דרך יעילה לנהל את התעבורה של שירותים שנפרסו בכמה אשכולות GKE. באמצעות תשתית איזון העומסים הגלובלית של Google, אתם יכולים ליצור נקודת כניסה אחת לאפליקציות שלכם, וכך לפשט את הניהול ולשפר את המהימנות.במדריך הזה משתמשים באפליקציית store לדוגמה כדי לדמות תרחיש מהעולם האמיתי שבו שירות קניות אונליין נמצא בבעלות ובהפעלה של צוותים נפרדים, ונפרס בצי של אשכולות GKE משותפים.
לפני שמתחילים
כדי לפרוס שערים מרובי-אשכולות, צריך לבצע הכנה מסוימת של הסביבה. לפני שממשיכים, פועלים לפי השלבים שמפורטים במאמר הכנת הסביבה לשימוש בשערי גישה מרובי-אשכולות:
פריסה של אשכולות GKE.
רושמים את האשכולות ב-Fleet (אם הם עדיין לא רשומים).
מפעילים את בקרי השירות מרובי האשכולות והשער מרובה האשכולות.
לבסוף, מומלץ לעיין במגבלות ובבעיות הידועות של GKE Gateway Controller לפני שמשתמשים בבקר בסביבה שלכם.
פריסת שער פנימי מרובה אשכולות באזורים שונים
אתם יכולים לפרוס שערים מרובי-אשכולות שמספקים איזון עומסים פנימי בשכבה 7 באשכולות GKE בכמה אזורים. השערים האלה משתמשים ב-gke-l7-cross-regional-internal-managed-mc GatewayClass. ה-GatewayClass הזה מספק מאזן עומסים פנימי של אפליקציות (ALB) בין אזורים שמנוהל על ידי Google Cloud ומאפשר כתובות IP וירטואליות פנימיות שלקוחות ברשת ה-VPC יכולים לגשת אליהן. אפשר לחשוף את השערים האלה דרך ממשקי קצה באזורים שתבחרו, פשוט באמצעות השער כדי לבקש כתובות באזורים האלה. ה-VIP הפנימי יכול להיות כתובת IP אחת, או כתובות IP בכמה אזורים, עם כתובת IP אחת לכל אזור שמוגדר בשער. התעבורה מנותבת לאשכול ה-GKE העורפי הקרוב ביותר שפועל בצורה תקינה ויכול לטפל בבקשה.
דרישות מוקדמות
מגדירים את הפרויקט ואת המעטפת על ידי הגדרת סביבת
gcloudעם מזהה הפרויקט:export PROJECT_ID="YOUR_PROJECT_ID" gcloud config set project ${PROJECT_ID}יצירת אשכולות GKE באזורים שונים.
בדוגמה הזו יש שני אשכולות,
gke-west-1ב-us-west1ו-gke-east-1ב-us-east1. מוודאים שממשק Gateway API מופעל (--gateway-api=standard) ושהאשכולות רשומים בצי.gcloud container clusters create gke-west-1 \ --location=us-west1-a \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standard gcloud container clusters create gke-east-1 \ --location=us-east1-c \ --workload-pool=${PROJECT_ID}.svc.id.goog \ --project=${PROJECT_ID} \ --enable-fleet \ --gateway-api=standardשינוי השם של ההקשרים כדי לגשת אליהם בקלות רבה יותר:
gcloud container clusters get-credentials gke-west-1 \ --location=us-west1-a \ --project=${PROJECT_ID} gcloud container clusters get-credentials gke-east-1 \ --location=us-east1-c \ --project=${PROJECT_ID} kubectl config rename-context gke_${PROJECT_ID}_us-west1-a_gke-west-1 gke-west1 kubectl config rename-context gke_${PROJECT_ID}_us-east1-c_gke-east-1 gke-east1הפעלת שירותים מרובי אשכולות (MCS) ותעבורת נתונים נכנסת (ingress) מרובת אשכולות (MCI/Gateway):
gcloud container fleet multi-cluster-services enable --project=${PROJECT_ID} # Set the config membership to one of your clusters (e.g., gke-west-1) # This cluster will be the source of truth for multi-cluster Gateway and Route resources. gcloud container fleet ingress enable \ --config-membership=projects/${PROJECT_ID}/locations/us-west1/memberships/gke-west-1 \ --project=${PROJECT_ID}מגדירים רשתות משנה ל-proxy בלבד. נדרשת תת-רשת של שרת proxy בלבד בכל אזור שבו נמצאים אשכולות GKE ושבו יפעל מאזן העומסים. כדי להשתמש במאזני עומסים פנימיים של אפליקציות (ALB) בין אזורים, צריך להגדיר את הייעוד של תת-הרשת הזו ל-
GLOBAL_MANAGED_PROXY.# Proxy-only subnet for us-west1 gcloud compute networks subnets create us-west1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-west1 \ --network=default \ --range=10.129.0.0/23 # Choose an appropriate unused CIDR range # Proxy-only subnet for us-east1 gcloud compute networks subnets create us-east1-proxy-only-subnet \ --purpose=GLOBAL_MANAGED_PROXY \ --role=ACTIVE \ --region=us-east1 \ --network=default \ --range=10.130.0.0/23 # Choose an appropriate unused CIDR rangeאם אתם לא משתמשים ברשת שמוגדרת כברירת מחדל, מחליפים את
defaultבשם של רשת ה-VPC. מוודאים שטווחי ה-CIDR ייחודיים ולא חופפים.פורסים את אפליקציות ההדגמה, כמו
store, בשני האשכולות. קובץ הדוגמהstore.yamlמ-gke-networking-recipesיוצר מרחב שמותstoreופריסה.kubectl apply --context gke-west1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yaml kubectl apply --context gke-east1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/main/gateway/gke-gateway-controller/multi-cluster-gateway/store.yamlכדי לייצא שירותים מכל אשכול, צריך ליצור משאבי Kubernetes
ServiceומשאביServiceExportבכל אשכול. כך השירותים יהיו זמינים לגילוי בכל צי המכונות. בדוגמה הבאה מיוצא שירות כלליstoreושירותים ספציפיים לאזור (store-west-1,store-east-1) מכל אשכול, והכול במרחב השמותstore.חל על
gke-west1:cat << EOF | kubectl apply --context gke-west1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-west-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-west-1 # Exporting the region-specific service namespace: store EOFחל על
gke-east1:cat << EOF | kubectl apply --context gke-east1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: store --- apiVersion: v1 kind: Service metadata: name: store-east-1 # Specific to this cluster namespace: store spec: selector: app: store ports: - port: 8080 targetPort: 8080 --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store-east-1 # Exporting the region-specific service namespace: store EOFבודקים את ServiceImports: מוודאים שמשאבי
ServiceImportנוצרים בכל אשכול במרחב השמותServiceImport.storeיכול להיות שיעברו כמה דקות עד שהם ייווצרו.bash kubectl get serviceimports --context gke-west1 -n store kubectl get serviceimports --context gke-east1 -n storeצריכות להופיע הרשומותstore,store-west-1ו-store-east-1(או רשומות רלוונטיות על סמך ההפצה).
הגדרת שער פנימי מרובה אזורים
הגדרה של Gateway משאב שמפנה אל gke-l7-cross-regional-internal-managed-mc GatewayClass. מחילים את המניפסט הזה על אשכול התצורה המיועד, כמו gke-west-1.
בשדה spec.addresses אפשר לבקש כתובות IP זמניות באזורים ספציפיים או להשתמש בכתובות IP סטטיות שהוקצו מראש.
כדי להשתמש בכתובות IP זמניות, שומרים את קובץ המניפסט
Gatewayהבא בתורcross-regional-gateway.yaml:# cross-regional-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway namespace: store # Namespace for the Gateway resource spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: # Addresses across regions. Address value is allowed to be empty or matching # the region name. - type: networking.gke.io/ephemeral-ipv4-address/us-west1 value: "us-west1" - type: networking.gke.io/ephemeral-ipv4-address/us-east1 value: "us-east1" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute # Only allow HTTPRoute to attachברשימה הבאה מוגדרים חלק מהשדות בקובץ ה-YAML הקודם:
-
metadata.namespace: מרחב השמות שבו נוצר משאב ה-Gateway, לדוגמה,store. -
spec.gatewayClassName: השם של GatewayClass. חייב להיותgke-l7-cross-regional-internal-managed-mc. -
spec.listeners.allowedRoutes.kinds: סוגי אובייקטים של מסלולים שאפשר לצרף, לדוגמה,HTTPRoute. spec.addresses:-
type: networking.gke.io/ephemeral-ipv4-address/REGION: בקשה לכתובת IP זמנית. -
value: מציין את האזור של הכתובת, לדוגמה,"us-west1"או"us-east1".
-
-
מחילים את המניפסט על אשכול ההגדרות, לדוגמה,
gke-west1:kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
צירוף של HTTPRoutes ל-Gateway
מגדירים משאבי HTTPRoute לניהול ניתוב התנועה ומחילים אותם על אשכול ההגדרות.
שומרים את קובץ המניפסט
HTTPRouteהבא בשםstore-route.yaml:# store-route.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store-route namespace: store labels: gateway: cross-regional-internal spec: parentRefs: - name: internal-cross-region-gateway namespace: store # Namespace where the Gateway is deployed hostnames: - "store.example.internal" # Hostname clients will use rules: - matches: # Rule for traffic to /west - path: type: PathPrefix value: /west backendRefs: - group: net.gke.io # Indicates a multi-cluster ServiceImport kind: ServiceImport name: store-west-1 # Targets the ServiceImport for the west cluster port: 8080 - matches: # Rule for traffic to /east - path: type: PathPrefix value: /east backendRefs: - group: net.gke.io kind: ServiceImport name: store-east-1 # Targets the ServiceImport for the east cluster port: 8080 - backendRefs: # Default rule for other paths (e.g., /) - group: net.gke.io kind: ServiceImport name: store # Targets the generic 'store' ServiceImport (any region) port: 8080ברשימה הבאה מוגדרים חלק מהשדות בקובץ ה-YAML הקודם:
-
spec.parentRefs: מצמיד את המסלול הזה ל-internal-cross-region-gatewayבמרחב השמותstore. -
spec.hostnames: מייצג את שם המארח שהלקוחות משתמשים בו כדי לגשת לשירות. -
spec.rules: הגדרה של לוגיקת הניתוב. בדוגמה הזו נעשה שימוש בניתוב מבוסס-נתיב:- תנועת
/westעוברת אלstore-west-1ServiceImport. - תנועת
/eastעוברת אלstore-east-1ServiceImport. - כל התנועה האחרת, כמו
/, מועברת אל ServiceImport כללי.store
- תנועת
backendRefs:-
group: net.gke.ioו-kind: ServiceImportשירותים מרובי אשכולות.
-
-
מחילים את המניפסט
HTTPRouteעל אשכול ההגדרות:kubectl apply --context gke-west1 -f store-route.yaml
אימות הסטטוס של השער והמסלול
בודקים את סטטוס השער:
kubectl get gateway internal-cross-region-gateway -n store -o yaml --context gke-west1מחפשים תנאי עם הסטטוס
type:Programmedand: True. You should see IP addresses assigned in thestatus.addressesfield, corresponding to the regions you specified (e.g., one forus-west1and one forus-east1`).בודקים את הסטטוס של HTTPRoute:
kubectl get httproute store-route -n store -o yaml --context gke-west1מחפשים תנאי ב-
status.parents[].conditionsעםtype: Accepted(אוResolvedRefs) ו-status: "True".
אישור התנועה
אחרי שמקצים את כתובות ה-IP לשער, אפשר לבדוק את התעבורה ממכונה וירטואלית של לקוח שנמצאת ברשת ה-VPC ובאחד מהאזורים, או באזור שאפשר להתחבר ממנו לכתובת ה-IP של השער.
מאחזרים את כתובות ה-IP של השער.
הפקודה הבאה מנסה לנתח את פלט ה-JSON. יכול להיות שתצטרכו לשנות את
jsonpathבהתאם למבנה המדויק.kubectl get gateway cross-region-gateway -n store --context gke-west1 -o=jsonpath="{.status.addresses[*].value}".הפלט של הפקודה הזו צריך לכלול את כתובות ה-VIP, כמו
VIP1_WEST, אוVIP2_EAST.שליחת בקשות בדיקה: ממכונה וירטואלית של לקוח ב-VPC:
# Assuming VIP_WEST is an IP in us-west1 and VIP_EAST is an IP in us-east1 # Traffic to /west should ideally be served by gke-west-1 curl -H "host: store.example.internal" http://VIP_WEST/west curl -H "host: store.example.internal" http://VIP_EAST/west # Still targets store-west-1 due to path # Traffic to /east should ideally be served by gke-east-1 curl -H "host: store.example.internal" http://VIP_WEST/east # Still targets store-east-1 due to path curl -H "host: store.example.internal" http://VIP_EAST/east # Traffic to / (default) could be served by either cluster curl -H "host: store.example.internal" http://VIP_WEST/ curl -H "host: store.example.internal" http://VIP_EAST/התגובה צריכה לכלול פרטים מהאפליקציה
storeשמציינים איזה פוד בקצה העורפי הגיב לבקשה, כמוcluster_nameאוzone.
שימוש בכתובות IP סטטיות
במקום כתובות IP ארעיות, אפשר להשתמש בכתובות IP פנימיות סטטיות שהוקצו מראש.
יוצרים כתובות IP סטטיות באזורים שבהם רוצים להשתמש:
gcloud compute addresses create cross-region-gw-ip-west --region us-west1 --subnet default --project=${PROJECT_ID} gcloud compute addresses create cross-region-gw-ip-east --region us-east1 --subnet default --project=${PROJECT_ID}אם אתם לא משתמשים ברשת המשנה שמוגדרת כברירת מחדל, מחליפים את
defaultבשם של רשת המשנה שכוללת את כתובת ה-IP שרוצים להקצות. אלה רשתות משנה רגילות, לא רשתות משנה של שרת proxy בלבד.מעדכנים את קובץ המניפסט של שער התשלומים על ידי שינוי הקטע
spec.addressesבקובץcross-regional-gateway.yaml:# cross-regional-gateway-static-ip.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: internal-cross-region-gateway # Or a new name if deploying alongside namespace: store spec: gatewayClassName: gke-l7-cross-regional-internal-managed-mc addresses: - type: networking.gke.io/named-address-with-region # Use for named static IP value: "regions/us-west1/addresses/cross-region-gw-ip-west" - type: networking.gke.io/named-address-with-region value: "regions/us-east1/addresses/cross-region-gw-ip-east" listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRouteהחלת המניפסט המעודכן של שער.
kubectl apply --context gke-west1 -f cross-regional-gateway.yaml
שיקולים מיוחדים לגבי רשתות משנה שאינן ברירת המחדל
כשמשתמשים ברשתות משנה שאינן ברירת המחדל, חשוב לקחת בחשבון את הנקודות הבאות:
אותה רשת VPC: כל המשאבים שנוצרו על ידי המשתמשים – כמו כתובות IP סטטיות, רשתות משנה של פרוקסי בלבד ואשכולות GKE – חייבים להיות באותה רשת VPC.
רשת משנה של כתובות: כשיוצרים כתובות IP סטטיות לשער, הן מוקצות מרשתות משנה רגילות באזורים שצוינו.
שמות של רשתות משנה באשכול: לכל אזור צריכה להיות רשת משנה עם אותו שם כמו רשת המשנה שבה נמצא אשכול התצורה של MCG.
- לדוגמה, אם אשכול ההגדרות
gke-west-1נמצא ב-projects/YOUR_PROJECT/regions/us-west1/subnetworks/my-custom-subnet, אז גם לאזורים שאתם מבקשים כתובות עבורם צריך להיות רשת משנהmy-custom-subnet. אם מבקשים כתובות באזוריםus-east1ו-us-centra1, צריך שיהיה גם רשת משנה בשםmy-custom-subnetבאזורים האלה.
- לדוגמה, אם אשכול ההגדרות
הסרת המשאבים
אחרי שתסיימו את התרגילים במסמך הזה, תצטרכו לפעול לפי השלבים הבאים כדי להסיר משאבים ולמנוע חיובים לא רצויים בחשבון:
ביטול הרישום של האשכולות ב-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
פתרון בעיות
לא קיימת תת-רשת לשרת proxy בלבד עבור שער פנימי
אם האירוע הבא מופיע בשער הפנימי, סימן שלא קיימת רשת משנה של פרוקסי בלבד באזור הזה. כדי לפתור את הבעיה, פורסים רשת משנה (subnet) של שרת proxy בלבד.
generic::invalid_argument: error ensuring load balancer: Insert: Invalid value for field 'resource.target': 'regions/us-west1/targetHttpProxies/gkegw-x5vt-default-internal-http-2jzr7e3xclhj'. A reserved and active subnetwork is required in the same region and VPC as the forwarding rule.
אין מקור תקין
התסמין:
יכולה להתרחש הבעיה הבאה כשיוצרים Gateway אבל אין גישה לשירותי ה-Backend (קוד תגובה 503):
no healthy upstream
הסיבה:
הודעת השגיאה הזו מציינת שכלי הבדיקה של בדיקת תקינות לא יכול למצוא שירותי קצה עורפיים תקינים. יכול להיות שהשירותים שלכם ב-Backend תקינים, אבל תצטרכו להתאים אישית את בדיקות התקינות.
פתרון עקיף:
כדי לפתור את הבעיה, מתאימים אישית את בדיקת התקינות בהתאם לדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.