הפעלת שירותים מבוזרים באשכולות פרטיים של GKE באמצעות Cloud Service Mesh

במאמר הזה מוסבר איך להריץ שירותים מבוזרים בכמה אשכולות של Google Kubernetes Engine ‏ (GKE) ב- Google Cloud באמצעות Cloud Service Mesh. בנוסף, מוסבר איך לחשוף שירות מבוזר באמצעות Multi Cluster Ingress ו-Cloud Service Mesh. אתם יכולים להשתמש במסמך הזה כדי להגדיר אשכולות GKE לא פרטיים. המסמך מדגיש את ההגדרות שמיועדות רק לאשכולות פרטיים.

המסמך הזה מיועד למנהלי פלטפורמות ולמפעילי שירותים שיש להם ידע בסיסי ב-Kubernetes. מומלץ להכיר את רשת השירות, אבל לא חובה. ‫Cloud Service Mesh מבוסס על טכנולוגיית Istio בקוד פתוח. מידע נוסף על Service mesh ו-Istio זמין בכתובת istio.io.

שירות מבוזר הוא שירות Kubernetes שפועל כשירות לוגי יחיד. שירותים מבוזרים עמידים יותר משירותי Kubernetes כי הם פועלים בכמה אשכולות Kubernetes באותו מרחב שמות. שירות מבוזר ממשיך לפעול גם אם אשכול GKE אחד או יותר מושבתים, כל עוד האשכולות התקינים יכולים לשרת את העומס הרצוי.

שירותי Kubernetes מוכרים רק לשרת ה-API של Kubernetes באשכול שבו הם פועלים. אם אשכול Kubernetes מושבת (למשל, במהלך תחזוקה מתוזמנת), כל שירותי Kubernetes שפועלים באשכול הזה מושבתים גם הם. הפעלת שירותים מבוזרים מקלה על ניהול מחזור החיים של האשכולות, כי אפשר להשבית אשכולות לצורך תחזוקה או שדרוגים בזמן שאשכולות אחרים מטפלים בתנועה. כדי ליצור שירות מבוזר, משתמשים בפונקציונליות של רשת השירותים ש-Cloud Service Mesh מספק, כדי לקשר בין שירותים שפועלים בכמה אשכולות כך שיפעלו כשירות לוגי אחד.

אשכולות פרטיים ב-GKE מאפשרים להגדיר את הצמתים ואת שרת ה-API כמשאבים פרטיים שזמינים רק ברשת של הענן הווירטואלי הפרטי (VPC). הפעלת שירותים מבוזרים באשכולות פרטיים של GKE מספקת לארגונים שירותים מאובטחים ואמינים.

ארכיטקטורה

המדריך הזה משתמש בארכיטקטורה שמוצגת בתרשים הבא:

ארכיטקטורה של שירותים מבוזרים באשכולות פרטיים של GKE באמצעות Cloud Service Mesh

בתרשים שלמעלה, הארכיטקטורה כוללת את האשכולות הבאים:

  • שני אשכולות (gke-central-priv ו-gke-west-priv) פועלים כאשכולות פרטיים זהים של GKE בשני אזורים שונים.
  • אשכול נפרד (ingress-config) משמש כאשכול של מישור הבקרה שמגדיר את Multi Cluster Ingress.

במדריך הזה תפרסו את האפליקציה לדוגמה Bank of Anthos בשני אשכולות פרטיים של GKE (‏gke-central-priv ו-gke-west-priv). Bank of Anthos היא אפליקציה לדוגמה של מיקרו-שירותים, שמורכבת מכמה מיקרו-שירותים ומסדי נתונים של SQL שמדמים אפליקציה של בנקאות דיגיטלית. האפליקציה מורכבת מ-frontend באינטרנט שלקוחות יכולים לגשת אליו, ומכמה שירותים לקצה העורפי כמו שירותי יתרה, ספר חשבונות וחשבון שמדמים בנק.

האפליקציה כוללת שני מסדי נתונים של PostgreSQL שמותקנים ב-Kubernetes כ-StatefulSets. מסד נתונים אחד משמש לעסקאות, ומסד הנתונים השני משמש לחשבונות משתמשים. כל השירותים, מלבד שני מסדי הנתונים, פועלים כשירותים מבוזרים. כלומר, Pods של כל השירותים פועלים בשני אשכולות האפליקציות (באותו מרחב שמות), ו-Cloud Service Mesh מוגדר כך שכל שירות מופיע כשירות לוגי יחיד.

מטרות

  • יוצרים שלושה אשכולות GKE.
  • מגדירים שניים מאשכולות ה-GKE כאשכולות פרטיים (gke-central-priv ו-gke-west-priv).
  • מגדירים אשכול GKE אחד (ingress-config) כאשכול ההגדרות המרכזי. האשכול הזה משמש כאשכול הגדרות ל-Multi Cluster Ingress.
  • מגדירים את הרשת (שערי NAT,‏ Cloud Router וכללי חומת אש) כדי לאפשר תעבורת נתונים בין אשכולות ותעבורת נתונים יוצאת משני אשכולות ה-GKE הפרטיים.
  • מגדירים רשתות מורשות כדי לאפשר גישה לשירות ה-API מ-Cloud Shell לשני אשכולות ה-GKE הפרטיים.
  • פורסים ומגדירים את Cloud Service Mesh עם כמה אשכולות בשני האשכולות הפרטיים במצב multi-primary. במצב Multi-primary, מישור הבקרה של Cloud Service Mesh נפרס בשני האשכולות.
  • פורסים את האפליקציה Bank of Anthos בשני האשכולות הפרטיים. כל השירותים, חוץ ממסדי הנתונים, נפרסים כשירותים מבוזרים (Pods שפועלים בשני האשכולות הפרטיים).
  • מעקב אחרי שירותים באמצעות Cloud Service Mesh.
  • מגדירים Multi Cluster Ingress בשירותי frontend של Bank of Anthos. כך לקוחות חיצוניים (לדוגמה, דפדפן האינטרנט) יכולים לגשת לשירות מבוזר שפועל ב-fleet של אשכולות GKE פרטיים.

עלויות

במסמך הזה משתמשים ברכיבים הבאים של Google Cloud, והשימוש בהם כרוך בתשלום:

בעזרת מחשבון העלויות אתם יכולים להעריך את העלויות בהתאם לשימוש הצפוי.

משתמשים חדשים של Google Cloud ? יכול להיות שאתם זכאים לתקופת ניסיון בחינם.

לפני שמתחילים

  1. בדף לבחירת הפרויקט במסוף Google Cloud , בוחרים פרויקט ב- Google Cloud או יוצרים אותו.

    התפקידים שנדרשים כדי לבחור או ליצור פרויקט

    • בחירת פרויקט: כדי לבחור פרויקט לא נדרש תפקיד IAM ספציפי – אתם יכולים לבחור כל פרויקט שקיבלתם בו תפקיד.
    • יצירת פרויקט: כדי ליצור פרויקט, צריך את התפקיד "יצירת פרויקטים" (roles/resourcemanager.projectCreator), שכולל את ההרשאה resourcemanager.projects.create. איך מקצים תפקידים?

    כניסה לדף לבחירת הפרויקט

  2. מוודאים שהחיוב מופעל בפרויקט ב- Google Cloud .

  3. מפעילים את Cloud Shell במסוף Google Cloud .

    הפעלת Cloud Shell

    בחלק התחתון של מסוף Google Cloud יתחיל סשן של Cloud Shell ותופיע הודעה של שורת הפקודה. Cloud Shell היא סביבת מעטפת שבה ה-CLI של Google Cloud מותקן ומוגדרים ערכים לפרויקט הקיים. הסשן יופעל תוך כמה שניות.

    כל הפקודות במדריך הזה מופעלות מ-Cloud Shell.

  4. מגדירים את משתני הסביבה שמשמשים במדריך הזה. המשתנים מגדירים את שמות האשכולות, האזורים, התחומים, כתובות ה-IP והגרסאות של Cloud Service Mesh שבהם משתמשים במדריך הזה.

    1. מחליפים את YOUR_PROJECT_ID במזהה הפרויקט:

      export PROJECT_ID=YOUR_PROJECT_ID
      gcloud config set project ${PROJECT_ID}
      
    2. מגדירים את משתני הסביבה הנותרים:

      export CLUSTER_1=gke-west-priv
      export CLUSTER_2=gke-central-priv
      export CLUSTER_1_ZONE=us-west2-a
      export CLUSTER_1_REGION=us-west2
      export CLUSTER_1_MASTER_IPV4_CIDR=172.16.0.0/28
      export CLUSTER_2_ZONE=us-central1-a
      export CLUSTER_2_REGION=us-central1
      export CLUSTER_2_MASTER_IPV4_CIDR=172.16.1.0/28
      export CLUSTER_INGRESS=gke-ingress
      export CLUSTER_INGRESS_ZONE=us-west1-a
      export CLUSTER_INGRESS_REGION=us-west1
      export CLUSTER_INGRESS_MASTER_IPV4_CIDR=172.16.2.0/28
      export WORKLOAD_POOL=${PROJECT_ID}.svc.id.goog
      export ASM_VERSION=1.10
      export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
      

הכנת הסביבה

  1. ב-Cloud Shell, מפעילים את ממשקי ה-API:

    gcloud services enable \
      --project=${PROJECT_ID} \
      container.googleapis.com \
      mesh.googleapis.com \
      gkehub.googleapis.com
    
  2. מפעילים את Cloud Service Mesh Fleet בפרויקט:

    gcloud container fleet mesh enable --project=${PROJECT_ID}
    

הכנת הרשת לאשכולות GKE פרטיים

בקטע הזה תכינו את הרשת לאשכולות הפרטיים של GKE, שבהם תשתמשו כדי להריץ שירותים מבוזרים.

לצמתים של אשכול GKE פרטי לא מוקצית כתובת IP ציבורית. לכל הצמתים באשכול GKE פרטי מוקצית כתובת IP פרטית של VPC (במרחב הכתובות RFC 1918). המשמעות היא שפודים שצריכים לגשת למשאבים חיצוניים (מחוץ לרשת ה-VPC) צריכים שער Cloud NAT. שערי Cloud NAT הם שערי NAT אזוריים שמאפשרים לפודים עם כתובות IP פנימיות לתקשר עם האינטרנט. במדריך הזה תגדירו שער Cloud NAT בכל אחד משני האזורים. כמה אשכולות באזור יכולים להשתמש באותו שער NAT.

  1. ב-Cloud Shell, יוצרים ושומרים שתי כתובות IP חיצוניות לשני שערי ה-NAT:

    gcloud compute addresses create ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION}
    
    gcloud compute addresses create ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION}
    
  2. שומרים את כתובת ה-IP ואת השם של כתובות ה-IP במשתנים:

    export NAT_REGION_1_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION} \
      --format='value(address)')
    
    export NAT_REGION_1_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_1_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_1_REGION} \
      --format='value(name)')
    
    export NAT_REGION_2_IP_ADDR=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION} \
      --format='value(address)')
    
    export NAT_REGION_2_IP_NAME=$(gcloud compute addresses describe ${CLUSTER_2_REGION}-nat-ip \
      --project=${PROJECT_ID} \
      --region=${CLUSTER_2_REGION} \
      --format='value(name)')
    
  3. יוצרים שערי Cloud NAT בשני האזורים של אשכולות ה-GKE הפרטיים:

    gcloud compute routers create rtr-${CLUSTER_1_REGION} \
      --network=default \
      --region ${CLUSTER_1_REGION}
    
    gcloud compute routers nats create nat-gw-${CLUSTER_1_REGION} \
      --router=rtr-${CLUSTER_1_REGION} \
      --region ${CLUSTER_1_REGION} \
      --nat-external-ip-pool=${NAT_REGION_1_IP_NAME} \
      --nat-all-subnet-ip-ranges \
      --enable-logging
    
    gcloud compute routers create rtr-${CLUSTER_2_REGION} \
      --network=default \
      --region ${CLUSTER_2_REGION}
    
    gcloud compute routers nats create nat-gw-${CLUSTER_2_REGION} \
      --router=rtr-${CLUSTER_2_REGION} \
      --region ${CLUSTER_2_REGION} \
      --nat-external-ip-pool=${NAT_REGION_2_IP_NAME} \
      --nat-all-subnet-ip-ranges \
      --enable-logging
    
  4. יוצרים כלל של חומת אש שמאפשר תקשורת בין Pod ל-Pod ותקשורת בין Pod לשרת API. תקשורת בין Pod ל-Pod מאפשרת לשירותים המבוזרים לתקשר זה עם זה בין אשכולות GKE. תקשורת בין Pod לשרת API מאפשרת למישור הבקרה של Cloud Service Mesh לשלוח שאילתות לאשכולות GKE לצורך זיהוי שירותים.

    gcloud compute firewall-rules create all-pods-and-master-ipv4-cidrs \
      --project ${PROJECT_ID} \
      --network default \
      --allow all \
      --direction INGRESS \
      --source-ranges 10.0.0.0/8,${CLUSTER_1_MASTER_IPV4_CIDR},${CLUSTER_2_MASTER_IPV4_CIDR},${CLUSTER_INGRESS_MASTER_IPV4_CIDR}
    

עכשיו הרשת מוכנה. במדריך הזה משתמשים בכל טווח כתובות ה-IP של 10.0.0.0/8, שכולל את כל טווחי ה-Pod. מומלץ ליצור כלל חומת אש מחמיר יותר בסביבת הייצור, על סמך התנאים והדרישות שלכם.

יצירת אשכולות GKE פרטיים

בקטע הזה יוצרים את שני אשכולות ה-GKE הפרטיים שבהם נפרסת האפליקציה לדוגמה. במדריך הזה, לצמתים של אשכול GKE הפרטי יש כתובות IP פרטיות, ולשרת ה-API יש נקודת קצה ציבורית. עם זאת, הגישה לשרת ה-API מוגבלת באמצעות רשתות מורשות.

  1. ב-Cloud Shell, יוצרים שני אשכולות פרטיים עם רשתות מורשות. מגדירים את האשכולות כך שתתאפשר גישה מטווח ה-CIDR של כתובות ה-IP של הפודים (למישור הבקרה של Cloud Service Mesh) ומ-Cloud Shell, כדי שתוכלו לגשת לאשכולות מהמסוף.

    gcloud container clusters create ${CLUSTER_1} \
      --project ${PROJECT_ID} \
      --zone=${CLUSTER_1_ZONE} \
      --machine-type "e2-standard-4" \
      --num-nodes "3" --min-nodes "3" --max-nodes "5" \
      --enable-ip-alias --enable-autoscaling \
      --workload-pool=${WORKLOAD_POOL} \
      --enable-private-nodes \
      --master-ipv4-cidr=${CLUSTER_1_MASTER_IPV4_CIDR} \
      --enable-master-authorized-networks \
      --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
    
    gcloud container clusters create ${CLUSTER_2} \
      --project ${PROJECT_ID} \
      --zone=${CLUSTER_2_ZONE} \
      --machine-type "e2-standard-4" \
      --num-nodes "3" --min-nodes "3" --max-nodes "5" \
      --enable-ip-alias --enable-autoscaling \
      --workload-pool=${WORKLOAD_POOL} \
      --enable-private-nodes \
      --master-ipv4-cidr=${CLUSTER_2_MASTER_IPV4_CIDR} \
      --enable-master-authorized-networks \
      --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
    

    הרשתות המורשות מכילות את כתובות ה-IP הציבוריות בשערי Cloud NAT. מכיוון שנקודת הקצה של שרת ה-API באשכול פרטי היא נקודת קצה ציבורית, פודים שפועלים באשכול פרטי צריכים להשתמש בשער Cloud NAT כדי לגשת לנקודות הקצה הציבוריות של שרת ה-API.

    כתובת ה-IP של Cloud Shell היא גם חלק מהרשתות המורשות, מה שמאפשר לכם לגשת לאשכולות ולנהל אותם מהטרמינל של Cloud Shell. כתובות ה-IP הציבוריות של Cloud Shell הן דינמיות, כך שבכל פעם שתפעילו את Cloud Shell, יכול להיות שתקבלו כתובת IP ציבורית אחרת. כשמקבלים כתובת IP חדשה, מאבדים את הגישה לאשכולות כי כתובת ה-IP החדשה לא נכללת ברשתות המורשות של שני האשכולות.

    אם איבדתם את הגישה לאשכולות, עדכנו את הרשתות המורשות של האשכולות כך שיכללו את כתובת ה-IP החדשה של Cloud Shell:

    1. משיגים את כתובת ה-IP הציבורית המעודכנת של Cloud Shell:

      export CLOUDSHELL_IP=$(dig +short myip.opendns.com @resolver1.opendns.com)
      
    2. מעדכנים את הרשתות המורשות של שני האשכולות:

      gcloud container clusters update ${CLUSTER_1} \
        --zone=${CLUSTER_1_ZONE} \
        --enable-master-authorized-networks \
        --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
      
      gcloud container clusters update ${CLUSTER_2} \
        --zone=${CLUSTER_2_ZONE} \
        --enable-master-authorized-networks \
        --master-authorized-networks $NAT_REGION_1_IP_ADDR/32,$NAT_REGION_2_IP_ADDR/32,$CLOUDSHELL_IP/32
      
  2. מוודאים שכל האשכולות פועלים:

    gcloud container clusters list
    

    הפלט אמור להיראות כך:

    NAME              LOCATION       MASTER_VERSION    MASTER_IP      MACHINE_TYPE   NODE_VERSION      NUM_NODES  STATUS
    gke-central-priv  us-central1-a  1.16.15-gke.6000  35.238.99.104  e2-standard-4  1.16.15-gke.6000  3          RUNNING
    gke-west-priv     us-west2-a     1.16.15-gke.6000  34.94.188.180  e2-standard-4  1.16.15-gke.6000  3          RUNNING
    
  3. מתחברים לשני האשכולות כדי ליצור רשומות בקובץ kubeconfig:

    touch ~/asm-kubeconfig && export KUBECONFIG=~/asm-kubeconfig
    gcloud container clusters get-credentials ${CLUSTER_1} --zone ${CLUSTER_1_ZONE}
    gcloud container clusters get-credentials ${CLUSTER_2} --zone ${CLUSTER_2_ZONE}
    

    אתם משתמשים בקובץ kubeconfig כדי לאמת את האשכולות, על ידי יצירת משתמש והקשר לכל אשכול. אחרי שיוצרים רשומות בקובץ kubeconfig, אפשר לעבור במהירות בין הקשרים של אשכולות.

  4. משנים את השמות של ההקשרים של האשכולות כדי שיהיה קל יותר לזהות אותם:

    kubectl config rename-context \
    gke_${PROJECT_ID}_${CLUSTER_1_ZONE}_${CLUSTER_1} ${CLUSTER_1}
    
    kubectl config rename-context \
    gke_${PROJECT_ID}_${CLUSTER_2_ZONE}_${CLUSTER_2} ${CLUSTER_2}
    
  5. מוודאים ששני ההקשרים של האשכולות מוגדרים ושהשמות שלהם שונו כמו שצריך:

    kubectl config get-contexts --output="name"
    

    הפלט אמור להיראות כך:

    gke-central-priv
    gke-west-priv
    
  6. רושמים את האשכולות ל-fleet:

    gcloud container fleet memberships register ${CLUSTER_1} --gke-cluster=${CLUSTER_1_ZONE}/${CLUSTER_1} --enable-workload-identity
    gcloud container fleet memberships register ${CLUSTER_2} --gke-cluster=${CLUSTER_2_ZONE}/${CLUSTER_2} --enable-workload-identity
    

עכשיו יצרתם את אשכולות ה-GKE הפרטיים ושיניתם את השמות שלהם.

התקנת Cloud Service Mesh

בקטע הזה תתקינו את Cloud Service Mesh בשני אשכולות GKE ותגדירו את האשכולות לזיהוי שירותים בין אשכולות.

  1. ב-Cloud Shell, מתקינים את Cloud Service Mesh בשני האשכולות באמצעות fleet API:

    gcloud container fleet mesh update --management automatic --memberships ${CLUSTER_1},${CLUSTER_2}
    
  2. אחרי שמפעילים את Cloud Service Mesh המנוהל באשכולות, מגדירים מעקב אחרי התקנת רשת ה-Mesh:

    watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
    
  3. מתקינים את שערי הכניסה של Cloud Service Mesh בשני האשכולות:

    kubectl --context=${CLUSTER_1} create namespace asm-ingress
    kubectl --context=${CLUSTER_1} label namespace asm-ingress istio-injection=enabled --overwrite
    kubectl --context=${CLUSTER_2} create namespace asm-ingress
    kubectl --context=${CLUSTER_2} label namespace asm-ingress istio-injection=enabled --overwrite
    
    cat <<'EOF' > asm-ingress.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      type: LoadBalancer
      selector:
        asm: ingressgateway
      ports:
      - port: 80
        name: http
      - port: 443
        name: https
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      selector:
        matchLabels:
          asm: ingressgateway
      template:
        metadata:
          annotations:
            # This is required to tell Anthos Service Mesh to inject the gateway with the
            # required configuration.
            inject.istio.io/templates: gateway
          labels:
            asm: ingressgateway
        spec:
          containers:
          - name: istio-proxy
            image: auto # The image will automatically update each time the pod starts.
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: asm-ingressgateway-sds
      namespace: asm-ingress
    rules:
    - apiGroups: [""]
      resources: ["secrets"]
      verbs: ["get", "watch", "list"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: asm-ingressgateway-sds
      namespace: asm-ingress
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: asm-ingressgateway-sds
    subjects:
    - kind: ServiceAccount
      name: default
    EOF
    
    kubectl --context=${CLUSTER_1} apply -f asm-ingress.yaml
    kubectl --context=${CLUSTER_2} apply -f asm-ingress.yaml
    
  4. מוודאים ששערי הכניסה של Cloud Service Mesh נפרסו:

    kubectl --context=${CLUSTER_1} get pod,service -n asm-ingress
    kubectl --context=${CLUSTER_2} get pod,service -n asm-ingress
    

    הפלט של שני האשכולות אמור להיראות כך:

    NAME                                        READY   STATUS    RESTARTS   AGE
    pod/asm-ingressgateway-5894744dbd-zxlgc   1/1     Running   0          84s
    
    NAME                           TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)                      AGE
    service/asm-ingressgateway   LoadBalancer   10.16.2.131   34.102.100.138   80:30432/TCP,443:30537/TCP   92s
    

    אחרי שמתקינים את מישור הבקרה של Cloud Service Mesh ואת שערי הכניסה לשני האשכולות, מפעילים את זיהוי השירותים בין האשכולות באמצעות Fleet API. זיהוי שירותים בין אשכולות מאפשר לשני האשכולות לזהות נקודות קצה של שירותים מהאשכול המרוחק. שירותים מבוזרים פועלים בכמה אשכולות באותו מרחב שמות.

    כדי ששני מישורי הבקרה של Cloud Service Mesh יזהו את כל נקודות הקצה של שירות מבוזר, ל-Cloud Service Mesh צריכה להיות גישה לכל האשכולות שבהם פועל השירות המבוזר. בדוגמה הזו יש שני אשכולות, ולכן שניהם צריכים להיות מסוגלים לשלוח שאילתות לאשכול המרוחק לגבי נקודות קצה של שירותים. כשמפעילים את Cloud Service Mesh מנוהל באמצעות Fleet API, נקודת הקצה מוגדרת באופן אוטומטי.

האשכולות ו-Cloud Service Mesh מוגדרים עכשיו.

פריסת האפליקציה Bank of Anthos

  1. ב-Cloud Shell, משכפלים את מאגר Bank of Anthos ב-GitHub:

    git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
    
  2. יוצרים מרחב שמות של bank-of-anthos בשני האשכולות ומוסיפים לו תווית. התווית מאפשרת הזרקה אוטומטית של שרתי ה-proxy של Envoy ב-sidecar בכל Pod במרחב השמות המסומן בתווית.

    # cluster_1
    kubectl create --context=${CLUSTER_1} namespace bank-of-anthos
    kubectl label --context=${CLUSTER_1} namespace bank-of-anthos istio-injection=enabled
    
    # cluster_2
    kubectl create --context=${CLUSTER_2} namespace bank-of-anthos
    kubectl label --context=${CLUSTER_2} namespace bank-of-anthos istio-injection=enabled
    
  3. פורסים את האפליקציה Bank of Anthos בשני האשכולות במרחב השמות bank-of-anthos.

    # The following secret is used for user account creation and authentication
    kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml
    kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/extras/jwt/jwt-secret.yaml
    
    # Deploy all manifests to both clusters
    kubectl --context=$CLUSTER_1 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
    kubectl --context=$CLUSTER_2 -n bank-of-anthos apply -f ${HOME}/bank-of-anthos/kubernetes-manifests
    

    שירותי Kubernetes צריכים להיות בשני האשכולות כדי לגלות את השירות. כששירות באחד מהאשכולות מנסה לשלוח בקשה, הוא קודם מבצע חיפוש DNS של שם המארח כדי לקבל את כתובת ה-IP. ב-GKE, שרת kube-dns שפועל באשכול מטפל בחיפוש הזה, ולכן נדרשת הגדרה של שירות.

  4. מוחקים את StatefulSets מאשכול אחד, כדי ששני מסדי הנתונים של PostgreSQL יהיו קיימים רק באחד מהאשכולות:

    # Delete the two DB statefulSets from Cluster2
    kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset accounts-db
    kubectl --context=$CLUSTER_2 -n bank-of-anthos delete statefulset ledger-db
    
  5. מוודאים שכל ה-Pods פועלים בשני האשכולות:

    1. משיגים Pods מ-cluster_1:

      kubectl --context=${CLUSTER_1} -n bank-of-anthos get pod
      

      הפלט אמור להיראות כך:

      NAME                                  READY   STATUS    RESTARTS   AGE
      accounts-db-0                         2/2     Running   0          9m54s
      balancereader-c5d664b4c-xmkrr         2/2     Running   0          9m54s
      contacts-7fd8c5fb6-wg9xn              2/2     Running   1          9m53s
      frontend-7b7fb9b665-m7cw7             2/2     Running   1          9m53s
      ledger-db-0                           2/2     Running   0          9m53s
      ledgerwriter-7b5b6db66f-xhbp4         2/2     Running   0          9m53s
      loadgenerator-7fb54d57f8-g5lz5        2/2     Running   0          9m52s
      transactionhistory-7fdb998c5f-vqh5w   2/2     Running   1          9m52s
      userservice-76996974f5-4wlpf          2/2     Running   1          9m52s
      
    2. משיגים Pods מ-cluster_2:

      kubectl --context=${CLUSTER_2} -n bank-of-anthos get pod
      

      הפלט אמור להיראות כך:

      NAME                                  READY   STATUS    RESTARTS   AGE
      balancereader-c5d664b4c-bn2pl         2/2     Running   0          9m54s
      contacts-7fd8c5fb6-kv8cp              2/2     Running   0          9m53s
      frontend-7b7fb9b665-bdpp4             2/2     Running   0          9m53s
      ledgerwriter-7b5b6db66f-297c2         2/2     Running   0          9m52s
      loadgenerator-7fb54d57f8-tj44v        2/2     Running   0          9m52s
      transactionhistory-7fdb998c5f-xvmtn   2/2     Running   0          9m52s
      userservice-76996974f5-mg7t6          2/2     Running   0          9m51s
      
  6. פורסים את ההגדרות של Cloud Service Mesh בשני האשכולות. הפעולה הזו יוצרת Gateway במרחב השמות asm-ingress ו-VirtualService במרחבי השמות bank-of-anthos של השירות frontend, ומאפשרת תעבורת נתונים נכנסת (ingress) לשירות frontend.

    בדרך כלל, Gateways נמצאים בבעלות של האדמינים של הפלטפורמה או של צוות האדמינים של הרשת. לכן, המשאב Gateway נוצר במרחב השמות של Ingress Gateway שבבעלות מנהל הפלטפורמה, ואפשר להשתמש בו במרחבי שמות אחרים באמצעות רשומות VirtualService משלהם. זהו מודל של "שער משותף".

    cat <<'EOF' > asm-vs-gateway.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: asm-ingressgateway
      namespace: asm-ingress
    spec:
      selector:
        asm: ingressgateway
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - "*"
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: frontend
      namespace: bank-of-anthos
    spec:
      hosts:
      - "*"
      gateways:
      - asm-ingress/asm-ingressgateway
      http:
      - route:
        - destination:
            host: frontend
            port:
              number: 80
    EOF
    
    kubectl --context=$CLUSTER_1 apply -f asm-vs-gateway.yaml
    
    kubectl --context=$CLUSTER_2 apply -f asm-vs-gateway.yaml
    

עכשיו פרסתם את האפליקציה Bank of Anthos בשני אשכולות GKE פרטיים. כל השירותים פועלים כשירותים מבוזרים, חוץ ממסד הנתונים.

בדיקת שירותים מבוזרים

בקטע הזה משתמשים בכלי istioctl כדי לבדוק את ה-proxy-config של כל אחד מהפרוקסי. כך תוכלו לראות שקובצי העזר החיצוניים רואים שני Pods לכל שירות, כש-Pod אחד פועל בכל אשכול.

  1. ב-Cloud Shell, בודקים את רשימת נקודות הקצה של proxy-config ב-Pod‏ frontend ב-cluster_1:

    export FRONTEND1=$(kubectl get pod -n bank-of-anthos -l app=frontend \
      --context=${CLUSTER_1} -o jsonpath='{.items[0].metadata.name}')
    istioctl proxy-config endpoints \
    --context $CLUSTER_1 -n bank-of-anthos $FRONTEND1 | grep bank-of-anthos
    

    הפלט אמור להיראות כך:

    10.12.0.6:5432                   HEALTHY     OK                outbound|5432||accounts-db.bank-of-anthos.svc.cluster.local
    10.12.0.7:8080                   HEALTHY     OK                outbound|8080||balancereader.bank-of-anthos.svc.cluster.local
    10.12.0.8:8080                   HEALTHY     OK                outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local
    10.12.0.9:8080                   HEALTHY     OK                outbound|8080||userservice.bank-of-anthos.svc.cluster.local
    10.12.1.10:8080                  HEALTHY     OK                outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
    10.12.1.9:8080                   HEALTHY     OK                outbound|8080||contacts.bank-of-anthos.svc.cluster.local
    10.12.2.11:5432                  HEALTHY     OK                outbound|5432||ledger-db.bank-of-anthos.svc.cluster.local
    10.12.2.13:8080                  HEALTHY     OK                outbound|80||frontend.bank-of-anthos.svc.cluster.local
    10.76.1.10:8080                  HEALTHY     OK                outbound|8080||transactionhistory.bank-of-anthos.svc.cluster.local
    10.76.1.8:8080                   HEALTHY     OK                outbound|8080||balancereader.bank-of-anthos.svc.cluster.local
    10.76.1.9:8080                   HEALTHY     OK                outbound|80||frontend.bank-of-anthos.svc.cluster.local
    10.76.2.10:8080                  HEALTHY     OK                outbound|8080||userservice.bank-of-anthos.svc.cluster.local
    10.76.2.8:8080                   HEALTHY     OK                outbound|8080||contacts.bank-of-anthos.svc.cluster.local
    10.76.2.9:8080                   HEALTHY     OK                outbound|8080||ledgerwriter.bank-of-anthos.svc.cluster.local
    

    בפלט שלמעלה, לכל שירות מבוזר יש שתי כתובות IP של נקודות קצה. אלה כתובות ה-IP של Pod, אחת לכל אשכול.

גישה ל-Bank of Anthos

כדי לגשת לאפליקציית Bank of Anthos, אתם יכולים להשתמש בכתובת ה-IP הציבורית של השירות asm-ingressgateway מכל אחד מהאשכולות.

  1. משיגים את כתובות ה-IP של asm-ingressgateway משני האשכולות:

    kubectl --context ${CLUSTER_1} \
    --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
    
    kubectl --context ${CLUSTER_2} \
    --namespace asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"
    
    

    הפלט אמור להיראות כך:

    {"ingress":[{"ip":"35.236.4.18"}]}
    {"ingress":[{"ip":"34.68.94.81"}]}
    

    מעתיקים את אחת מכתובות ה-IP כדי להשתמש בה בשלב הבא.

  2. פותחים כרטיסייה חדשה בדפדפן אינטרנט ועוברים לאחת מכתובות ה-IP מהפלט הקודם. אמור להופיע ממשק המשתמש של Bank of Anthos, שבו אתם יכולים להתחבר, להפקיד כספים בחשבון ולהעביר כספים לחשבונות אחרים. האפליקציה צריכה להיות פעילה באופן מלא.

המחשה חזותית של שירותים מבוזרים

אתם יכולים להציג באופן חזותי שירותים מבוזרים ב-Cloud Service Mesh.

  1. כדי לראות את השירותים, נכנסים לדף Service Mesh במסוף Google Cloud .

    כניסה לדף Service Mesh

    אפשר להציג את השירותים בתצוגת Table או בתצוגת Topology. תצוגת ברירת המחדל היא תצוגת טבלה, שבה מוצגים כל השירותים המבוזרים שפועלים בפורמט טבלאי. כדי לשנות את התצוגה, לוחצים על התצוגה שרוצים להציג.

  2. בתצוגה טבלאות, לוחצים על frontend distributed service. כשלוחצים על שירות מסוים, רואים תצוגה מפורטת של השירות ושל השירותים שמקושרים אליו.

    בתצוגת פרטי השירות, אפשר ליצור יעדי SLO ולראות את ציר הזמן ההיסטורי של השירות בלחיצה על Show Timeline.

  3. כדי לראות את האותות החשובים, לוחצים על Metrics בחלונית הצדדית.

  4. בתרשים Requests per seconds, לוחצים על Breakdown By ובוחרים באפשרות Location.

    בתוצאות מוצגות הבקשות לשנייה משני האשכולות בשני האזורים. השירות המבוזר תקין ושתי נקודות הקצה מטפלות בתנועה.

  5. כדי לראות את הטופולוגיה של רשת השירות, בחלונית הצדדית לוחצים על Anthos Service Mesh ואז על Topology View.

  6. כדי לראות נתונים נוספים, העבירו את סמן העכבר מעל השירות frontend. כאן מוצג מידע כמו בקשות לשנייה אל החזית ומהחזית לשירותים אחרים.

  7. כדי לראות פרטים נוספים, לוחצים על הרחבה בשירות frontend. מוצגים שירות ועומס עבודה. אפשר להרחיב את עומס העבודה לשני פריסות, להרחיב את הפריסות ל-ReplicaSets ולהרחיב את ה-ReplicaSets לפודים. כשמרחיבים את כל הרכיבים, אפשר לראות את השירות המבוזר frontend, שהוא למעשה שירות ושני Pods.

הגדרת Multi Cluster Ingress

בקטע הזה, יוצרים Multi Cluster Ingress ששולח תנועה לשירותי Bank of GKE Enterprise frontend שפועלים בשני האשכולות. אתם משתמשים ב-Cloud Load Balancing כדי ליצור מאזן עומסים שמשתמש בשירותי asm-ingressgateway בשני האשכולות כ-backends. אשכול ingress-config משמש לתזמור של הגדרת Multi Cluster Ingress.

כדי ליצור את מאזן העומסים, משתמשים ב-MultiClusterIngress ובאחד או יותר מ-MultiClusterServices. האובייקטים MultiClusterIngress ו-MultiClusterService הם מקבילים מרובי-אשכולות למשאבי Ingress ו-Service הקיימים של Kubernetes, שמשמשים בהקשר של אשכול יחיד.

  1. מפעילים את ממשקי ה-API הנדרשים של GKE Enterprise,‏ GKE Fleet ו-Multi Cluster Ingress:

    gcloud services enable \
      anthos.googleapis.com \
      multiclusterservicediscovery.googleapis.com \
      multiclusteringress.googleapis.com
    
  2. יוצרים את האשכול ingress-config. אפשר להשתמש בכל אשכול, אבל מומלץ ליצור אשכול נפרד למטרה הזו.

    gcloud container clusters create ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} \
      --num-nodes=1 \
      --enable-ip-alias \
      --workload-pool=${WORKLOAD_POOL}
    
  3. מקבלים את פרטי הכניסה לאשכול ומשנים את שם ההקשר לנוחות:

    gcloud container clusters get-credentials ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} --project ${PROJECT_ID}
    
    kubectl config rename-context \
      gke_${PROJECT_ID}_${CLUSTER_INGRESS_ZONE}_${CLUSTER_INGRESS} ${CLUSTER_INGRESS}
    
  4. כדי להשתמש ב-Multi Cluster Ingress, צריך לרשום את כל האשכולות המשתתפים ב-GKE Enterprise Fleet, כולל אשכול ההגדרות האישיות:

  5. רושמים את אשכול ההגדרות:

    gcloud container fleet memberships register ${CLUSTER_INGRESS} \
      --project=${PROJECT_ID} \
      --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS} \
      --enable-workload-identity
    
  6. מוודאים שכל האשכולות רשומים ב-GKE Enterprise Fleet:

    gcloud container fleet memberships list
    

    הפלט אמור להיראות כך:

    NAME            EXTERNAL_ID
    gke-west        7fe5b7ce-50d0-4e64-a9af-55d37b3dd3fa
    gke-central     6f1f6bb2-a3f6-4e9c-be52-6907d9d258cd
    gke-ingress     3574ee0f-b7e6-11ea-9787-42010a8a019c
    
  7. הפעלת תכונות של Multi Cluster Ingress באשכול ingress-config. הפעולה הזו יוצרת את CustomResourceDefinitions (CRDs) של MulticlusterService ו-MulticlusterIngress באשכול.

    gcloud container fleet ingress enable \
      --config-membership=projects/${PROJECT_ID}/locations/${CLUSTER_INGRESS_REGION}/memberships/${CLUSTER_INGRESS}
    
  8. מוודאים ש-Multi Cluster Ingress מופעל באשכול ingress-config:

    gcloud container fleet ingress describe
    

    הפלט אמור להיראות כך:

    membershipStates:
      projects/986443280307/locations/global/memberships/gke-central-priv:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972748202Z'
      projects/986443280307/locations/global/memberships/gke-ingress:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972744692Z'
      projects/986443280307/locations/global/memberships/gke-west-priv:
        state:
          code: OK
          updateTime: '2022-09-29T13:57:02.972746497Z'
    
  9. מוודאים ששני ה-CRD נפרסו באשכול ingress-config:

    kubectl --context=${CLUSTER_INGRESS} get crd | grep multicluster
    

    הפלט אמור להיראות כך:

    multiclusteringresses.networking.gke.io     2020-10-29T17:32:50Z
    multiclusterservices.networking.gke.io      2020-10-29T17:32:50Z
    
  10. יוצרים את מרחב השמות asm-ingress באשכול ingress-config:

    kubectl --context ${CLUSTER_INGRESS} create namespace asm-ingress
    
  11. יוצרים את המשאב MultiClusterIngress:

    cat <<EOF > ${HOME}/mci.yaml
    apiVersion: networking.gke.io/v1beta1
    kind: MultiClusterIngress
    metadata:
      name: asm-ingressgateway-multicluster-ingress
    spec:
      template:
        spec:
          backend:
           serviceName: asm-ingressgateway-multicluster-svc
           servicePort: 80
    EOF
    
  12. יוצרים את המשאב MultiClusterService:

    cat <<'EOF' > $HOME/mcs.yaml
    apiVersion: networking.gke.io/v1beta1
    kind: MultiClusterService
    metadata:
      name: asm-ingressgateway-multicluster-svc
      annotations:
        beta.cloud.google.com/backend-config: '{"ports": {"80":"gke-ingress-config"}}'
    spec:
      template:
        spec:
          selector:
            asm: ingressgateway
          ports:
          - name: frontend
            protocol: TCP
            port: 80 # servicePort defined in Multi Cluster Ingress
      clusters:
      - link: "us-west2-a/gke-west-priv"
      - link: "us-central1-a/gke-central-priv"
    EOF
    
  13. יוצרים את המשאב BackendConfig לבדיקות תקינות:

    cat <<EOF > $HOME/backendconfig.yaml
    apiVersion: cloud.google.com/v1beta1
    kind: BackendConfig
    metadata:
      name: gke-ingress-config
    spec:
      healthCheck:
        type: HTTP
        port: 15021
        requestPath: /healthz/ready
    EOF
    
  14. מחילים את המניפסטים BackendConfig,‏ MultiClusterService ו-MultiClusterIngress:

    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/backendconfig.yaml
    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mci.yaml
    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress apply -f ${HOME}/mcs.yaml
    
  15. ה-MultiClusterService שפרסתם באשכול ה-Ingress ייצור Service "ללא ראש" באשכול 1 ובאשכול 2. מוודאים שנוצר Services "ללא ממשק משתמש":

    kubectl --context=${CLUSTER_1} -n asm-ingress \
      get services | grep multicluster-svc
    kubectl --context=${CLUSTER_2} -n asm-ingress \
      get services | grep multicluster-svc
    

    הפלט אמור להיראות כך:

    mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw   ClusterIP      None          <none>          80/TCP         77s
    mci-frontend-multi-cluster-service-svc-f7rcyqry22iq8nmw   ClusterIP      None          <none>          80/TCP         78s
    
  16. מריצים את הפקודה הבאה וממתינים עד שמקבלים כתובת IP של Cloud Load Balancing:

    watch kubectl --context ${CLUSTER_INGRESS} -n asm-ingress get multiclusteringress \
      -o jsonpath="{.items[].status.VIP}"
    

    הפלט אמור להיראות כך:

    35.35.23.11
    

    כדי לצאת מהפקודה watch, מקישים על Ctrl+C.

  17. בדפדפן אינטרנט, נכנסים לכתובת ה-IP של Cloud Load Balancing כדי להגיע לממשק של Bank of Anthos:

    kubectl --context ${CLUSTER_INGRESS} \
      -n asm-ingress get multiclusteringress \
      -o jsonpath="{.items[].status.VIP}"
    

    אם מופיעה שגיאת 404 (או שגיאת 502), המתינו כמה דקות ורעננו את הדף בדפדפן האינטרנט.

הסרת המשאבים

כדי להימנע מחיובים בחשבון, צריך למחוק את הפרויקט או את האשכולות.

מחיקת הפרויקט

הדרך הקלה ביותר לבטל את החיוב היא למחוק את הפרויקט שיצרתם בשביל המדריך.

  1. במסוף Google Cloud , נכנסים לדף Manage resources.

    כניסה לדף Manage resources

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete.
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.

מחיקת האשכולות

  1. ב-Cloud Shell, מבטלים את הרישום של האשכולות הפרטיים ומוחקים אותם:

    gcloud container fleet memberships unregister ${CLUSTER_1} \
      --project=${PROJECT_ID} \
      --gke-cluster=${CLUSTER_1_ZONE}/${CLUSTER_1}
    gcloud container clusters delete ${CLUSTER_1} \
      --zone ${CLUSTER_1_ZONE} \
      --quiet
    
    gcloud container fleet memberships unregister ${CLUSTER_2} \
      --project=${PROJECT_ID} \
      --gke-cluster=${CLUSTER_2_ZONE}/${CLUSTER_2}
    gcloud container clusters delete ${CLUSTER_2} \
      --zone ${CLUSTER_2_ZONE} \
      --quiet
    
  2. מוחקים את המשאב MuticlusterIngress מהאשכול ingress-config:

    kubectl --context ${CLUSTER_INGRESS} -n asm-ingress delete -f $HOME/mci.yaml
    

    הפעולה הזו מוחקת את המשאבים של Cloud Load Balancing מהפרויקט.

  3. מבטלים את הרישום של האשכול ingress-config ומוחקים אותו:

    gcloud container fleet memberships unregister ${CLUSTER_INGRESS} \
      --project=${PROJECT_ID} \
      --gke-cluster=${CLUSTER_INGRESS_ZONE}/${CLUSTER_INGRESS}
    gcloud container clusters delete ${CLUSTER_INGRESS} \
      --zone ${CLUSTER_INGRESS_ZONE} \
      --quiet
    
  4. מוודאים שכל האשכולות נמחקו:

    gcloud container clusters list
    

    הפלט שיתקבל:

    <null>
  5. מאפסים את הקובץ kubeconfig:

    unset KUBECONFIG
    

המאמרים הבאים