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

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

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

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

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

אפשר להגדיר את הצמתים ואת שרת ה-API כמשאבים פרטיים שזמינים רק ברשת של הענן הווירטואלי הפרטי (VPC) באשכולות פרטיים של GKE. הפעלת שירותים מבוזרים באשכולות פרטיים של 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 שמדמים אפליקציית בנקאות דיגיטלית. האפליקציה מורכבת מממשק קצה לאינטרנט שלקוחות יכולים לגשת אליו, ומכמה שירותי קצה עורפי כמו שירותי יתרה, ספר חשבונות וחשבון שמדמים בנק.

האפליקציה כוללת שני מסדי נתונים של 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, מישור הבקרה של Cloud Service Mesh נפרס בשני האשכולות.
  • פורסים את האפליקציה Bank of Anthos בשני האשכולות הפרטיים. כל השירותים, חוץ ממסדי הנתונים, נפרסים כשירותים מבוזרים (Pods שפועלים באשכולות פרטיים).
  • מעקב אחרי שירותים באמצעות Cloud Service Mesh.
  • הגדרת Multi Cluster Ingress בשירותי Bank of Anthosfrontend. כך לקוחות חיצוניים (לדוגמה, דפדפן האינטרנט שלכם) יכולים לגשת לשירות מבוזר שפועל במערך של אשכולות GKE פרטיים.

עלויות

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

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

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

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

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator role (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    כל הפקודות במדריך הזה מורצות מ-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)
      
  5. הכנת הסביבה

    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 פרטיים שמשמשים להרצת שירותים מבוזרים.

    לא מוקצית כתובת IP ציבורית לצמתים של אשכול GKE פרטי. לכל הצמתים באשכול GKE פרטי מוקצית כתובת IP פרטית של VPC (במרחב הכתובות RFC 1918). המשמעות היא שפודים שצריכים לגשת למשאבים חיצוניים (מחוץ לרשת ה-VPC) דורשים שער Cloud NAT. שערי Cloud NAT הם שערי NAT אזוריים שמאפשרים ל-Pods עם כתובות 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ים לבין שרת API. תקשורת בין פודים מאפשרת לשירותים המבוזרים לתקשר ביניהם בין אשכולות 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 של ה-Pod (למישור הבקרה של 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 המנוהל באשכולות, מגדירים מעקב אחרי התקנת הרשת:

      watch -g "gcloud container fleet mesh describe | grep 'code: REVISION_READY'"
      
    3. מתקינים שערים לכניסת תנועה (ingress) של 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, משכפלים את מאגר GitHub של Bank of Anthos:

      git clone https://github.com/GoogleCloudPlatform/bank-of-anthos.git ${HOME}/bank-of-anthos
      
    2. יוצרים מרחב שמות bank-of-anthos בשני האשכולות ונותנים לו תווית. התווית מאפשרת הוספה אוטומטית של פרוקסי 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. קבלת תרמילים מ-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. קבלת תרמילים מ-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 של כל אחד מהשרתים. כך תוכלו לראות שפרוקסי מסוג sidecar רואה שני פודים לכל שירות, ופוד אחד פועל בכל אשכול.

    1. ב-Cloud Shell, בודקים את רשימת נקודות הקצה של proxy-config ב-frontend Pod ב-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

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

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

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

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

    4. בתרשים בקשות לשנייה, לוחצים על פירוט לפי ואז בוחרים באפשרות מיקום.

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

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

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

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

    הגדרת Multi Cluster Ingress

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

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

    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. הפעולה הזו יוצרת את MulticlusterService ואת MulticlusterIngressCustomResourceDefinitions ‏ (CRD) באשכול.

      gcloud container fleet ingress enable \
        --config-membership=projects/${PROJECT_ID}/locations/global/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 ייצור "headless" 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. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

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

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

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

      kubectl --context ${CLUSTER_INGRESS} -n istio-system delete -f $HOME/mci.yaml
      

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

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

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

      gcloud container clusters list
      

      הפלט שיתקבל:

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

      unset KUBECONFIG
      

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