במסמך הזה מוסבר על פריסה של שער פנימי מרובה אשכולות כדי לנתב תעבורה בתוך רשת VPC לאפליקציה שפועלת בשני אשכולות GKE שונים.
שערים מרובי אשכולות הם דרך יעילה לנהל את התעבורה של שירותים שנפרסו בכמה אשכולות GKE. באמצעות התשתית הגלובלית של Google לאיזון עומסים, אתם יכולים ליצור נקודת כניסה אחת לאפליקציות שלכם, וכך לפשט את הניהול ולשפר את המהימנות.במדריך הזה משתמשים באפליקציית store לדוגמה כדי לדמות תרחיש מהעולם האמיתי שבו שירות קניות אונליין נמצא בבעלות של צוותים נפרדים ומופעל על ידם, ונפרס בצי של אשכולות GKE משותפים.
לפני שמתחילים
כדי לפרוס שערים מרובי-אשכולות, צריך לבצע הכנה מסוימת של הסביבה. לפני שממשיכים, פועלים לפי השלבים במאמר הכנת הסביבה לשימוש בשערי גישה מרובי-אשכולות:
פריסת אשכולות GKE.
רושמים את האשכולות ב-Fleet (אם הם עדיין לא רשומים).
מפעילים את בקרי השירות מרובי האשכולות והשער מרובה האשכולות.
לבסוף, כדאי לעיין במגבלות ובבעיות הידועות של בקר GKE Gateway לפני שמשתמשים בבקר בסביבה שלכם.
פריסת שער פנימי מרובה אשכולות באזורים שונים
אתם יכולים לפרוס שערים מרובי-אשכולות שמספקים איזון עומסים פנימי בשכבה 7 באשכולות GKE בכמה אזורים. שערי ה-API האלה משתמשים ב-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) ושהאשכולות רשומים ב-Fleet.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 בלבד. נדרשת רשת משנה (subnet) מסוג proxy-only בכל אזור שבו נמצאים אשכולות 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: סוגי אובייקטים של Route שאפשר לצרף, לדוגמה,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 לשער
מגדירים משאבי 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 בלבד עבור שער פנימי
אם האירוע הבא מופיע בשער הפנימי, לא קיים תת-רשת של 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.
אין מקור תקין
תסמין:
הבעיה הבאה עלולה להתרחש כשיוצרים שער אבל אין גישה לשירותי הקצה העורפי (קוד תגובה 503):
no healthy upstream
הסיבה:
הודעת השגיאה הזו מציינת שכלי הבדיקה של בדיקת תקינות לא יכול למצוא שירותי קצה עורפיים תקינים. יכול להיות שהשירותים שלכם בבק-אנד תקינים, אבל תצטרכו להתאים אישית את בדיקות התקינות.
פתרון עקיף:
כדי לפתור את הבעיה, צריך להתאים אישית את בדיקת תקינות על סמך הדרישות של האפליקציה (לדוגמה, /health) באמצעות HealthCheckPolicy.
המאמרים הבאים
- מידע נוסף על בקר שער
- כדי להגדיר TLS מאומת בקצה העורפי של שער מרובה אשכולות, אפשר לעיין במאמר בנושא הגדרת TLS בקצה העורפי.