במאמר הזה מוסבר איך לבצע את הפעולות הבאות:
- פריסה של אפליקציות שמפוזרות גלובלית ונחשפות דרך GKE Gateway ו-Cloud Service Mesh.
- אפשר לחשוף אפליקציה לכמה לקוחות על ידי שילוב של Cloud Load Balancing עם Cloud Service Mesh.
- שילוב מאזני עומסים עם Service mesh שנפרס על פני Google Cloud אזורים.
מדריך הפריסה הזה מיועד לאדמינים של פלטפורמות. הוא מיועד גם למשתמשים מתקדמים שמריצים את Cloud Service Mesh. ההוראות רלוונטיות גם ל-Istio ב-GKE.
ארכיטקטורה
בתרשים הבא מוצגת טופולוגיית ברירת המחדל של Ingress ב-Service Mesh – מאזן עומסים חיצוני של TCP/UDP שחושף את שרתי ה-proxy של שער ה-Ingress באשכול יחיד:
במדריך הפריסה הזה נעשה שימוש במשאבי שער של Google Kubernetes Engine (GKE). הוא משתמש בשער מרובה אשכולות כדי להגדיר איזון עומסים במספר אזורים מול כמה אשכולות של Autopilot שמפוזרים בשני אזורים.
בתרשים שלמעלה מוצג איך הנתונים זורמים בתרחישים של כניסה לענן וכניסה לרשת. מידע נוסף מופיע בהסבר על דיאגרמת ארכיטקטורה במסמך הארכיטקטורה הרלוונטי.
מטרות
- פריסה של צמד אשכולות GKE Autopilot ב- Google Cloud באותו צי.
- פריסת Cloud Service Mesh מבוסס Istio לאותו צי.
- מגדירים מאזן עומסים באמצעות GKE Gateway כדי להפסיק תעבורת HTTPS ציבורית.
- הפניית תעבורת HTTPS ציבורית ישירות לאפליקציות שמתארחות ב-Cloud Service Mesh ונפרסות בכמה אשכולות ואזורים.
- פורסים את אפליקציית הדוגמה whereami בשני אשכולות Autopilot.
הוזלת עלויות
במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:
- Google Kubernetes Engine
- Cloud Load Balancing
- Cloud Service Mesh
- Multi Cluster Ingress
- Google Cloud Armor
- Certificate Manager
- Cloud Endpoints
כדי ליצור הערכת עלויות בהתאם לשימוש החזוי, אתם יכולים להשתמש במחשבון התמחור.
כשמסיימים את המשימות שמתוארות במסמך הזה אפשר למחוק את המשאבים שיצרתם כדי להימנע מחיובים נוספים. מידע נוסף זמין בקטע הסרת המשאבים.
לפני שמתחילים
-
בדף לבחירת הפרויקט במסוף Google Cloud , בוחרים פרויקט ב- Google Cloud או יוצרים אותו.
תפקידים שנדרשים כדי לבחור או ליצור פרויקט
- Select a project: כדי לבחור פרויקט לא צריך תפקיד IAM ספציפי – אפשר לבחור כל פרויקט שקיבלתם בו תפקיד.
-
יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד Project Creator (
roles/resourcemanager.projectCreator), שכולל את ההרשאהresourcemanager.projects.create. איך מקצים תפקידים
-
במסוף Google Cloud , מפעילים את Cloud Shell.
מריצים את כל פקודות הטרמינל לפריסה הזו מ-Cloud Shell.
מגדירים את Google Cloud פרויקט ברירת המחדל:
export PROJECT=PROJECT_ID export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)") gcloud config set project PROJECT_IDמחליפים את
PROJECT_IDבמזהה הפרויקט שבו רוצים להשתמש לפריסה הזו.יוצרים ספריית עבודה:
mkdir -p ${HOME}/edge-to-mesh-multi-region cd ${HOME}/edge-to-mesh-multi-region export WORKDIR=`pwd`
יצירת אשכולות GKE
בקטע הזה יוצרים אשכולות GKE לאירוח האפליקציות והתשתית התומכת, שיוצרים בהמשך מדריך הפריסה הזה.
יוצרים קובץ
kubeconfigחדש ב-Cloud Shell. השלב הזה מבטיח שלא ייווצר קונפליקט עם קובץkubeconfigהקיים (ברירת המחדל).touch edge2mesh_mr_kubeconfig export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfigהגדרת משתני הסביבה שמשמשים ליצירת אשכולות GKE והמשאבים בתוכם. משנים את ברירת המחדל של האזורים כדי להתאים אותה למטרות שלכם.
export CLUSTER_1_NAME=edge-to-mesh-01 export CLUSTER_2_NAME=edge-to-mesh-02 export CLUSTER_1_REGION=us-central1 export CLUSTER_2_REGION=us-east4 export PUBLIC_ENDPOINT=frontend.endpoints.PROJECT_ID.cloud.googמפעילים את ממשקי Google Cloud API שמשמשים לאורך המדריך הזה:
gcloud services enable \ container.googleapis.com \ mesh.googleapis.com \ gkehub.googleapis.com \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ certificatemanager.googleapis.comיצירת אשכול GKE Autopilot עם צמתים פרטיים ב-
CLUSTER_1_REGION. כדי לא לחכות עד שהאשכול הראשון יוקצה וירשם ל-Fleet, משתמשים בדגל--async:gcloud container clusters create-auto --async \ ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} \ --release-channel rapid \ --enable-private-nodes --enable-fleetיוצרים ומลงים אשכול שני של Autopilot ב-
CLUSTER_2_REGION:gcloud container clusters create-auto \ ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} \ --release-channel rapid \ --enable-private-nodes --enable-fleetמוודאים שהאשכולות פועלים. יכול להיות שיחלפו עד 20 דקות עד שכל האשכולות יפעלו:
gcloud container clusters listהפלט אמור להיראות כך:
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS STACK_TYPE edge-to-mesh-01 us-central1 1.35.5-gke.1000000 34.31.166.104 ek-standard-8 1.35.5-gke.1000000 1 RUNNING IPV4 edge-to-mesh-02 us-east4 1.35.5-gke.1000000 35.245.233.88 ek-standard-8 1.35.5-gke.1000000 1 RUNNING IPV4
אוספים את פרטי הכניסה של
CLUSTER_1_NAME.יצרתם אתCLUSTER_1_NAMEבאופן אסינכרוני כדי להפעיל פקודות נוספות בזמן שהאשכול הוקצה.gcloud container clusters get-credentials ${CLUSTER_1_NAME} \ --region ${CLUSTER_1_REGION}כדי להבהיר את השמות של הקונטקסטים של Kubernetes, משנים את השמות שלהם לשמות של האשכולות:
kubectl config rename-context gke_PROJECT_ID_${CLUSTER_1_REGION}_${CLUSTER_1_NAME} ${CLUSTER_1_NAME} kubectl config rename-context gke_PROJECT_ID_${CLUSTER_2_REGION}_${CLUSTER_2_NAME} ${CLUSTER_2_NAME}
התקנת service mesh
בקטע הזה מוסבר איך להגדיר את Cloud Service Mesh מנוהל עם Fleet API. שימוש ב-Fleet API כדי להפעיל את Cloud Service Mesh מספק גישה הצהרתית להקצאת רשת שירותים.
ב-Cloud Shell, מפעילים את Cloud Service Mesh בצי:
gcloud container fleet mesh enableהפעלה של ניהול אוטומטי של מישור הבקרה ומישור הנתונים:
gcloud container fleet mesh update \ --management automatic \ --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}ממתינים כ-20 דקות. לאחר מכן מוודאים שסטטוס מישור הבקרה הוא
ACTIVE:gcloud container fleet mesh describeהפלט אמור להיראות כך:
createTime: '2026-06-04T23:40:02.666228685Z' membershipSpecs: projects/497535075790/locations/us-central1/memberships/edge-to-mesh-01: mesh: management: MANAGEMENT_AUTOMATIC projects/497535075790/locations/us-east4/memberships/edge-to-mesh-02: mesh: management: MANAGEMENT_AUTOMATIC membershipStates: projects/497535075790/locations/us-central1/memberships/edge-to-mesh-01: servicemesh: conditions: - code: VPCSC_GA_SUPPORTED details: This control plane supports VPC-SC GA. documentationLink: http://cloud.google.com/service-mesh/docs/managed/vpc-sc severity: INFO controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: TRAFFIC_DIRECTOR state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision ready for use: asm-managed-rapid.' updateTime: '2026-06-04T23:45:52.958139396Z' projects/497535075790/locations/us-east4/memberships/edge-to-mesh-02: servicemesh: conditions: - code: VPCSC_GA_SUPPORTED details: This control plane supports VPC-SC GA. documentationLink: http://cloud.google.com/service-mesh/docs/managed/vpc-sc severity: INFO controlPlaneManagement: details: - code: REVISION_READY details: 'Ready: asm-managed-rapid' implementation: TRAFFIC_DIRECTOR state: ACTIVE dataPlaneManagement: details: - code: OK details: Service is running. state: ACTIVE state: code: OK description: 'Revision ready for use: asm-managed-rapid.' updateTime: '2026-06-04T23:45:54.621862416Z' name: projects/e2m-mc-h2c/locations/global/features/servicemesh resourceState: state: ACTIVE spec: {} updateTime: '2026-06-04T23:40:55.123874541Z'
פריסה של מאזן עומסים חיצוני של אפליקציות (ALB) ויצירה של שערי תעבורת נתונים נכנסת (ingress)
בקטע הזה פורסים מאזן עומסים של אפליקציות (ALB) חיצוני באמצעות GKE Gateway Controller ויוצרים שערי Ingress לשני האשכולות. המשאבים gateway ו-gatewayClass מבצעים אוטומציה של הקצאת מאזן העומסים ובדיקת התקינות של ה-backend. כדי לספק סיום TLS במאזן העומסים, יוצרים משאבים של Certificate Manager ומצרפים אותם למאזן העומסים. בנוסף, אתם יכולים להשתמש בנקודות קצה כדי להקצות באופן אוטומטי שם DNS ציבורי לאפליקציה.
התקנת שער כניסה בשני האשכולות
כשיטה מומלצת לאבטחה, מומלץ לפרוס את שער הכניסה במרחב שמות שונה ממישור הבקרה של הרשת.
ב-Cloud Shell, יוצרים מרחב שמות ייעודי
ingress-gatewayבכל אשכול:kubectl --context=${CLUSTER_1_NAME} create namespace ingress-gateway kubectl --context=${CLUSTER_2_NAME} create namespace ingress-gatewayמוסיפים תווית של מרחב שמות ל
ingress-gatewayמרחבי השמות:kubectl --context=${CLUSTER_1_NAME} label namespace ingress-gateway istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} label namespace ingress-gateway istio-injection=enabledהפלט אמור להיראות כך:
namespace/ingress-gateway labeled
הוספת התווית
ingress-gatewayלמרחבי השמותistio-injection=enabledמורה ל-Cloud Service Mesh להוסיף אוטומטית פרוקסי מסוג Envoy sidecar כשפורסים פוד.יצירת אישור בחתימה עצמית לשימוש עתידי:
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \ -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \ -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crtהאישור מספק שכבת הצפנה נוספת בין מאזן העומסים לבין שערי Service mesh. היא גם מפעילה תמיכה בפרוטוקולים מבוססי HTTP/2 כמו gRPC. הוראות לצירוף האישור בחתימה עצמית לשערי הכניסה מופיעות בהמשך המאמר יצירת משאבים של כתובת IP חיצונית, רשומת DNS ואישור TLS.
אם אתם רוצים להשתמש ב-HTTP/2 לחיבור בין GFE ל-mesh אבל לא צריך הצפנה משלכם, אתם יכולים להשתמש ב-H2C.
מידע נוסף על הדרישות של אישור שער הכניסה זמין במאמר הצפנה ממאזן העומסים אל השרתים העורפיים.
יוצרים סוד של Kubernetes בכל אשכול כדי לאחסן את האישור בחתימה עצמית:
kubectl --context ${CLUSTER_1_NAME} -n ingress-gateway create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt kubectl --context ${CLUSTER_2_NAME} -n ingress-gateway create secret tls \ edge2mesh-credential \ --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \ --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crtכדי לבצע שילוב עם מאזן עומסים של אפליקציות (ALB) חיצוני, צריך ליצור וריאנט של kustomize כדי להגדיר את משאבי שער הכניסה:
mkdir -p ${WORKDIR}/asm-ig/base cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base EOF mkdir ${WORKDIR}/asm-ig/variant cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: asm-ingressgateway namespace: ingress-gateway rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "watch", "list"] EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: asm-ingressgateway namespace: ingress-gateway roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: asm-ingressgateway subjects: - kind: ServiceAccount name: asm-ingressgateway EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml apiVersion: v1 kind: Service metadata: name: asm-ingressgateway namespace: ingress-gateway spec: ports: - name: status-port port: 15021 protocol: TCP targetPort: 15021 - name: http port: 80 targetPort: 8080 appProtocol: HTTP - name: https port: 443 targetPort: 8443 appProtocol: HTTP2 type: ClusterIP EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: asm-ingressgateway namespace: ingress-gateway spec: servers: - port: number: 443 name: https protocol: HTTPS hosts: - "*" # IMPORTANT: Must use wildcard here when using SSL, as SNI isn't passed from GFE tls: mode: SIMPLE credentialName: edge2mesh-credential EOF cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml namespace: ingress-gateway resources: - ../base - role.yaml - rolebinding.yaml patches: - path: service-proto-type.yaml target: kind: Service - path: gateway.yaml target: kind: Gateway EOFהחלת ההגדרות של שער הכניסה על שני האשכולות:
kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
חשיפת פודים של שער כניסה למאזן העומסים באמצעות שירות מרובה אשכולות
בקטע הזה מייצאים את ה-pods של שער הכניסה באמצעות ServiceExport
משאב בהתאמה אישית. צריך לייצא את הפודים של שער הכניסה באמצעות משאב מותאם אישית ServiceExport מהסיבות הבאות:
- מאפשר למאזן העומסים לפנות לתרמילים של שער הכניסה במספר אשכולות.
- מאפשר ל-pods של שער הכניסה להעביר בקשות לשרתים שפועלים בתוך Service mesh.
ב-Cloud Shell, מפעילים את התכונה 'שירותים מרובי אשכולות' (MCS) ב-Fleet:
gcloud container fleet multi-cluster-services enableמעניקים ל-MCS את הרשאות ה-IAM הנדרשות לפרויקט או ל-Fleet:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \ --role "roles/compute.networkViewer"יוצרים את קובץ ה-YAML
ServiceExport:cat <<EOF > ${WORKDIR}/svc_export.yaml kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: asm-ingressgateway namespace: ingress-gateway EOFמחילים את קובץ ה-YAML
ServiceExportעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yamlאם מופיעה הודעת השגיאה הבאה, צריך לחכות כמה רגעים עד להתקנה של הגדרות המשאבים המותאמים (CRD) של MCS. לאחר מכן מריצים מחדש את הפקודות כדי להחיל את קובץ ה-YAML
ServiceExportעל שני האשכולות.error: resource mapping not found for name: "asm-ingressgateway" namespace: "ingress-gateway" from "svc_export.yaml": no matches for kind "ServiceExport" in version "net.gke.io/v1" ensure CRDs are installed first
יצירת משאבים של כתובת IP חיצונית, רשומת DNS ואישור TLS
בקטע הזה יוצרים משאבי רשת שתומכים במשאבי איזון העומסים שיוצרים בהמשך הפריסה.
ב-Cloud Shell, שומרים כתובת IP חיצונית סטטית:
gcloud compute addresses create mcg-ip --globalכתובת IP סטטית משמשת את משאב GKE Gateway. כך כתובת ה-IP נשארת זהה, גם אם מאזן העומסים החיצוני נוצר מחדש.
מקבלים את כתובת ה-IP הסטטית ומאחסנים אותה כמשתנה סביבה:
export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)") echo ${MCG_IP}כדי ליצור מיפוי יציב וידידותי למשתמש לכתובת ה-IP של השער, צריך רשומת DNS ציבורית.
אתם יכולים להשתמש בכל ספק DNS ובכל תוכנית אוטומציה שתרצו. הפריסה הזו משתמשת ב-Endpoints במקום ליצור אזור DNS מנוהל. Endpoints מספקת רשומת DNS בניהול Google בחינם לכתובת IP חיצונית.
מריצים את הפקודה הבאה כדי ליצור קובץ YAML בשם
dns-spec.yaml:cat <<EOF > ${WORKDIR}/dns-spec.yaml swagger: "2.0" info: description: "Cloud Endpoints DNS" title: "Cloud Endpoints DNS" version: "1.0.0" paths: {} host: "frontend.endpoints.PROJECT_ID.cloud.goog" x-google-endpoints: - name: "frontend.endpoints.PROJECT_ID.cloud.goog" target: "${MCG_IP}" EOFקובץ
dns-spec.yamlמגדיר את רשומת ה-DNS הציבורית בפורמטfrontend.endpoints.PROJECT_ID.cloud.goog, כאשרPROJECT_IDהוא המזהה הייחודי של הפרויקט.פורסים את הקובץ
dns-spec.yamlכדי ליצור את רשומת ה-DNS. התהליך הזה נמשך כמה דקות.gcloud endpoints services deploy ${WORKDIR}/dns-spec.yamlיוצרים אישור באמצעות Certificate Manager עבור שם רשומת ה-DNS שיצרתם בשלב הקודם:
gcloud certificate-manager certificates create mcg-cert \ --domains="frontend.endpoints.PROJECT_ID.cloud.goog"אישור TLS (אבטחת שכבת התעבורה) שמנוהל על ידי Google משמש לסיום בקשות של לקוחות נכנסים במאזן העומסים.
יצירת מפת אישורים:
gcloud certificate-manager maps create mcg-cert-mapמאזן העומסים מפנה לאישור דרך רשומה במפת האישורים שיוצרים בשלב הבא.
יוצרים רשומת מיפוי לאישורים לאישור שיצרתם קודם בקטע הזה:
gcloud certificate-manager maps entries create mcg-cert-map-entry \ --map="mcg-cert-map" \ --certificates="mcg-cert" \ --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"
יצירת מדיניות של שירותים לקצה העורפי ומשאבים של מאזן עומסים
בקטע הזה תבצעו את המשימות הבאות:
- יוצרים כללי מדיניות אבטחה של Cloud Armor.
- יוצרים מדיניות שמאפשרת למאזן העומסים לבדוק את זמן התגובה של הפודים של שער הכניסה דרך קובץ ה-YAML
ServiceExportשיצרתם קודם. - משתמשים ב-GKE Gateway API כדי ליצור משאב של מאזן עומסים.
- משתמשים במשאב המותאם אישית
GatewayClassכדי להגדיר את הסוג הספציפי של איזון העומסים. - מפעילים איזון עומסים מרובה אשכולות עבור ה-Fleet ומגדירים אחד מהאשכולות כאשכול ההגדרות של ה-Fleet.
ב-Cloud Shell, יוצרים מדיניות אבטחה של Cloud Armor:
gcloud compute security-policies create edge-fw-policy \ --description "Block XSS attacks"יוצרים כלל למדיניות האבטחה:
gcloud compute security-policies rules create 1000 \ --security-policy edge-fw-policy \ --expression "evaluatePreconfiguredExpr('xss-stable')" \ --action "deny-403" \ --description "XSS attack filtering"יוצרים קובץ YAML למדיניות האבטחה ומפנים לקובץ ה-YAML של
ServiceExportבאמצעות קובץ YAML תואם שלServiceImport:cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml apiVersion: networking.gke.io/v1 kind: GCPBackendPolicy metadata: name: cloud-armor-backendpolicy namespace: ingress-gateway spec: default: securityPolicy: edge-fw-policy targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOFמחילים את מדיניות Cloud Armor על שני האשכולות:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yamlיוצרים קובץ YAML בהתאמה אישית שמאפשר למאזן העומסים לבצע בדיקות תקינות מול נקודת הקצה של Envoy לבדיקת תקינות (יציאה
15021בנתיב/healthz/ready) של הפודים של שער הכניסה בשני האשכולות:cat <<EOF > ${WORKDIR}/ingress-gateway-healthcheck.yaml apiVersion: networking.gke.io/v1 kind: HealthCheckPolicy metadata: name: ingress-gateway-healthcheck namespace: ingress-gateway spec: default: config: httpHealthCheck: port: 15021 portSpecification: USE_FIXED_PORT requestPath: /healthz/ready type: HTTP targetRef: group: net.gke.io kind: ServiceImport name: asm-ingressgateway EOFמחילים את קובץ ה-YAML בהתאמה אישית שיצרתם בשלב הקודם על שני האשכולות:
kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yamlמפעילים איזון עומסים מרובה אשכולות עבור ה-Fleet, ומגדירים את
CLUSTER_1_NAMEכאשכול ההגדרות:gcloud container fleet ingress enable \ --config-membership=${CLUSTER_1_NAME} \ --location=${CLUSTER_1_REGION}מעניקים הרשאות IAM לבקר של שער הכניסה ב-Fleet:
gcloud projects add-iam-policy-binding PROJECT_ID \ --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \ --role "roles/container.admin"יוצרים את קובץ ה-YAML של איזון העומסים באמצעות משאב בהתאמה אישית של Gateway שמפנה אל
gke-l7-global-external-managed-mcgatewayClassואל כתובת ה-IP הסטטית שיצרתם קודם:cat <<EOF > ${WORKDIR}/frontend-gateway.yaml kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: external-http namespace: ingress-gateway annotations: networking.gke.io/certmap: mcg-cert-map spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http # list the port only so we can redirect any incoming http requests to https protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 allowedRoutes: kinds: - kind: HTTPRoute addresses: - type: NamedAddress value: mcg-ip EOFמחילים את קובץ ה-YAML
frontend-gatewayעל שני האשכולות. רקCLUSTER_1_NAMEהוא המקור המוסמך, אלא אם מציינים אשכול הגדרות אחר כמקור המוסמך:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yamlיוצרים קובץ
HTTPRouteYAML בשםdefault-httproute.yamlשמכיל את ההגדרות הבאות:cat << EOF > ${WORKDIR}/default-httproute.yaml apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: default-httproute namespace: ingress-gateway spec: parentRefs: - name: external-http namespace: ingress-gateway sectionName: https rules: - backendRefs: - group: net.gke.io kind: ServiceImport name: asm-ingressgateway port: 443 EOFמחילים את קובץ ה-YAML
HTTPRouteשיצרתם בשלב הקודם על שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yamlכדי לבצע הפניות אוטומטיות מ-HTTP ל-HTTP(S), יוצרים קובץ YAML נוסף בשם
default-httproute-redirect.yaml:HTTPRoutecat << EOF > ${WORKDIR}/default-httproute-redirect.yaml kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: http-to-https-redirect-httproute namespace: ingress-gateway spec: parentRefs: - name: external-http namespace: ingress-gateway sectionName: http rules: - filters: - type: RequestRedirect requestRedirect: scheme: https statusCode: 301 EOFמחילים את קובץ ה-YAML של ההפניה האוטומטית
HTTPRouteעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yamlבודקים את משאב השער כדי לראות את התקדמות הפריסה של מאזן העומסים:
kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n ingress-gatewayבפלט מוצג המידע שהזנתם בקטע הזה.
פריסת האפליקציה לדוגמה whereami
במדריך הזה נעשה שימוש באפליקציית הדוגמה whereami כדי לספק משוב ישיר לגבי האשכולות שמשיבים לבקשות. בקטע הבא מוגדרות שתי פריסות נפרדות של whereami בשני האשכולות: פריסת frontend ופריסת backend.
פריסת frontend היא עומס העבודה הראשון שמקבל את הבקשה. לאחר מכן המערכת קוראת לפריסת backend.
המודל הזה משמש להדגמה של ארכיטקטורת אפליקציה מרובת שירותים.
שני השירותים, frontend ו-backend, נפרסים בשני האשכולות.
ב-Cloud Shell, יוצרים את מרחבי השמות של whereami
frontendושל whereamibackendבשני האשכולות ומפעילים את הזרקת מרחב השמות:kubectl --context=${CLUSTER_1_NAME} create ns frontend kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_1_NAME} create ns backend kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns frontend kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled kubectl --context=${CLUSTER_2_NAME} create ns backend kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabledיוצרים וריאנט של kustomize עבור whereami
backend:mkdir -p ${WORKDIR}/whereami-backend/base cat <<EOF > ${WORKDIR}/whereami-backend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir ${WORKDIR}/whereami-backend/variant cat <<EOF > ${WORKDIR}/whereami-backend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "False" # assuming you don't want a chain of backend calls METADATA: "backend" EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-backend/variant/kustomization.yaml nameSuffix: "-backend" namespace: backend labels: - includeSelectors: true includeTemplates: true pairs: app: whereami-backend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOFמחילים את וריאנט whereami
backendעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variantיוצרים וריאנט של kustomize עבור whereami
frontend:mkdir -p ${WORKDIR}/whereami-frontend/base cat <<EOF > ${WORKDIR}/whereami-frontend/base/kustomization.yaml resources: - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s EOF mkdir whereami-frontend/variant cat <<EOF > ${WORKDIR}/whereami-frontend/variant/cm-flag.yaml apiVersion: v1 kind: ConfigMap metadata: name: whereami data: BACKEND_ENABLED: "True" BACKEND_SERVICE: "http://whereami-backend.backend.svc.cluster.local" EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/service-type.yaml apiVersion: "v1" kind: "Service" metadata: name: "whereami" spec: type: ClusterIP EOF cat <<EOF > ${WORKDIR}/whereami-frontend/variant/kustomization.yaml nameSuffix: "-frontend" namespace: frontend labels: - includeSelectors: true includeTemplates: true pairs: app: whereami-frontend resources: - ../base patches: - path: cm-flag.yaml target: kind: ConfigMap - path: service-type.yaml target: kind: Service EOFמחילים את וריאנט whereami
frontendעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variantיוצרים קובץ YAML
VirtualServiceכדי להפנות בקשות אלfrontend:cat << EOF > ${WORKDIR}/frontend-vs.yaml apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: whereami-vs namespace: frontend spec: gateways: - ingress-gateway/asm-ingressgateway hosts: - 'frontend.endpoints.PROJECT_ID.cloud.goog' http: - route: - destination: host: whereami-frontend port: number: 80 EOFמחילים את קובץ ה-YAML
frontend-vsעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yamlאחרי שפרסתם את
frontend-vs.yamlבשני האשכולות, נסו לקרוא לנקודת הקצה הציבורית של האשכולות:curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jqהפלט אמור להיראות כך:
{ "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "8396338201253702608", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-645h", "pod_ip": "10.124.0.199", "pod_name": "whereami-backend-7cbdfd788-8mmnq", "pod_name_emoji": "📸", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-01", "gce_instance_id": "1047264075324910451", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-01-pool-2-d687e3c0-5kf2", "pod_ip": "10.54.1.71", "pod_name": "whereami-frontend-69c4c867cb-dgg8t", "pod_name_emoji": "🪴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T03:46:24", "zone": "us-central1-c" }
אם מריצים את הפקודה curl כמה פעמים, אפשר לראות שהתשובות (גם מ-frontend וגם מ-backend) מגיעות מאזורים שונים. בתגובה שלו, מאזן העומסים מספק ניתוב גיאוגרפי. כלומר, מאזן העומסים מנתב בקשות מהלקוח לאשכול הפעיל הקרוב ביותר, אבל הבקשות עדיין מגיעות באופן אקראי. כשבקשות עוברות מדי פעם מאזור אחד לאזור אחר, זמן האחזור והעלות גדלים.
בקטע הבא, מטמיעים איזון עומסים מקומי ב-Service mesh כדי שהבקשות יישארו מקומיות.
הפעלה ובדיקה של איזון עומסים לפי אזור עבור whereami
בקטע הזה מטמיעים איזון עומסים מקומי ב-Service mesh כדי שהבקשות יישארו מקומיות. אתם גם מבצעים כמה בדיקות כדי לראות איך whereami מתמודד עם תרחישי כשל שונים.
כששולחים בקשה לשירות whereami frontend, מאזן העומסים שולח את הבקשה לאשכול עם זמן האחזור הכי נמוך ביחס ללקוח. כלומר, תרמילי שער הכניסה ברשת מאזנים את בקשות הטעינה לתרמילי whereami frontend בשני האשכולות. בקטע הזה נטפל בבעיה הזו באמצעות הפעלת איזון עומסים מקומי ברשת Mesh.
ב-Cloud Shell, יוצרים קובץ YAML
DestinationRuleשמאפשר מעבר לגיבוי אזורי של איזון עומסים לפי מיקום בשירותfrontend:cat << EOF > ${WORKDIR}/frontend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: frontend namespace: frontend spec: host: whereami-frontend.frontend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOFבדוגמת הקוד שלמעלה מופעלת ניתוב מקומי רק לשירות
frontend. צריך גם הגדרה נוספת שמטפלת בקצה העורפי.מחילים את קובץ ה-YAML
frontend-drעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yamlיוצרים קובץ
DestinationRuleYAML שמפעיל מעבר ליתירות כשל אזורית של איזון עומסים לפי מיקום בשירותbackend:cat << EOF > ${WORKDIR}/backend-dr.yaml apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: backend namespace: backend spec: host: whereami-backend.backend.svc.cluster.local trafficPolicy: connectionPool: http: maxRequestsPerConnection: 0 loadBalancer: simple: LEAST_REQUEST localityLbSetting: enabled: true outlierDetection: consecutive5xxErrors: 1 interval: 1s baseEjectionTime: 1m EOFמחילים את קובץ ה-YAML
backend-drעל שני האשכולות:kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yamlאחרי שמחילים את שני קבוצות קובצי ה-YAML
DestinationRuleעל שני האשכולות, הבקשות נשארות מקומיות לאשכול שאליו הבקשה מנותבת.כדי לבדוק את המעבר לגיבוי במקרה של כשל בשירות
frontend, מצמצמים את מספר הרפליקות של שער הכניסה באשכול הראשי.מנקודת המבט של מאזן העומסים שמנוהל במספר אזורים, הפעולה הזו מדמה כשל באשכול. כתוצאה מכך, האשכול נכשל בבדיקות התקינות של מאזן העומסים. בדוגמה הזו נעשה שימוש באשכול ב-
CLUSTER_1_REGION. אמורה להופיע רק תגובה מהאשכול ב-CLUSTER_2_REGION.מצמצמים את מספר העותקים של שער הכניסה באשכול הראשי לאפס, ומתקשרים לנקודת הקצה הציבורית כדי לוודא שהבקשות עברו לאשכול השני:
kubectl --context=${CLUSTER_1_NAME} -n ingress-gateway scale --replicas=0 deployment/asm-ingressgatewayהפלט אמור להיראות כך:
$ curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq { "backend_result": { "cluster_name": "edge-to-mesh-02", "gce_instance_id": "2717459599837162415", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "whereami-backend.backend.svc.cluster.local", "metadata": "backend", "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-dxs2", "pod_ip": "10.124.1.7", "pod_name": "whereami-backend-7cbdfd788-mp8zv", "pod_name_emoji": "🏌🏽♀", "pod_namespace": "backend", "pod_service_account": "whereami-backend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }, "cluster_name": "edge-to-mesh-02", "gce_instance_id": "6983018919754001204", "gce_service_account": "e2m-mcg-01.svc.id.goog", "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog", "metadata": "frontend", "node_name": "gk3-edge-to-mesh-02-pool-3-d42ddfbf-qmkn", "pod_ip": "10.124.1.142", "pod_name": "whereami-frontend-69c4c867cb-xf8db", "pod_name_emoji": "🏴", "pod_namespace": "frontend", "pod_service_account": "whereami-frontend", "project_id": "e2m-mcg-01", "timestamp": "2023-12-01T05:41:18", "zone": "us-east4-b" }כדי לחזור לניתוב תנועה רגיל, צריך לשחזר את העותקים המשוכפלים של שער הכניסה לערך המקורי באשכול:
kubectl --context=${CLUSTER_1_NAME} -n ingress-gateway scale --replicas=3 deployment/asm-ingressgatewayמדמים כשל בשירות
backendעל ידי צמצום מספר העותקים באזור הראשי ל-0:kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backendמוודאים שהתשובות משירות
frontendמגיעות מהאזור הראשיus-central1דרך מאזן העומסים, והתשובות משירותbackendמגיעות מהאזור המשניus-east4.הפלט צריך לכלול גם תשובה לשירות
frontendמהאזור הראשי (us-central1), ותשובה לשירותbackendמהאזור המשני (us-east4), כצפוי.כדי לחזור לניתוב התנועה הרגיל, צריך לשחזר את העותקים של שירות הקצה העורפי לערך המקורי:
kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
עכשיו יש לכם מאזן עומסים גלובלי של HTTP(S) שמשמש כקצה קדמי לאפליקציה שלכם שמארחת רשת שירותים במספר אזורים.
הסרת המשאבים
כדי להימנע מחיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם בפריסה הזו, אתם יכולים למחוק את הפרויקט שמכיל את המשאבים או להשאיר את הפרויקט ולמחוק את המשאבים הספציפיים.
מחיקת הפרויקט
- במסוף Google Cloud , נכנסים לדף Manage resources.
- ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
- כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.
מחיקת המשאבים הבודדים
אם רוצים לשמור את הפרויקט Google Cloud שבו השתמשתם בפריסה הזו, צריך למחוק את המשאבים הבודדים:
ב-Cloud Shell, מוחקים את המשאבים
HTTPRoute:kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute.yamlמחיקת משאבי GKE Gateway:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yamlמחיקת כללי המדיניות:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yamlמוחקים את קובצי הייצוא של השירות:
kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yamlמוחקים את המשאבים של Cloud Armor:
gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quietמוחקים את המשאבים של Certificate Manager:
gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quietמוחקים את רשומת ה-DNS של נקודות הקצה:
gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quietמחיקת כתובת ה-IP הסטטית:
gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quietמוחקים את אשכולות GKE Autopilot. השלב הזה נמשך כמה דקות.
gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} --quiet gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} --quiet
המאמרים הבאים
- מידע נוסף על תכונות של GKE Gateway שאפשר להשתמש בהן עם רשת השירותים
- מידע על הסוגים השונים של Cloud Load Balancing שזמינים ל-GKE
- מידע על התכונות והפונקציות של Cloud Service Mesh
- לדוגמאות נוספות של ארכיטקטורות, תרשימים ושיטות מומלצות, עיינו במאמר Cloud Architecture Center.
שותפים ביצירת התוכן
מחברים:
- אלכס מטסון | מהנדס מומחה לאפליקציות
- מארק צ'ילברס | מהנדס מומחה לאפליקציות
תורמי תוכן אחרים:
- Abdelfettah Sghiouar | Cloud Developer Advocate
- Greg Bray | Customer Engineer
- Paul Revello | Cloud Solutions Architect
- Valavan Rajakumar | Key Enterprise Architect