Cloud Service Mesh בדוגמה: פריסות קנרית

במדריך הזה נסביר על תרחיש שימוש נפוץ: הטמעה של פריסה של גרסה ראשונית (canary) באמצעות Cloud Service Mesh עם ממשקי Istio API.

מהי פריסה של גרסה ראשונית (canary)?

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

עלויות

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

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

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

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

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

פריסת Online Boutique

  1. מגדירים את ההקשר הנוכחי של kubectl לאשכול שבו מתכננים לפרוס את Online Boutique. הפקודה משתנה בהתאם לשאלה אם הקצאתם Cloud Service Mesh באשכול GKE או באשכול Kubernetes מחוץ ל-GKE:

    GKE ב-Google Cloud

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    

    ‫GKE מחוץ ל-Google Cloud

    kubectl config use-context CLUSTER_NAME 
    
  2. יוצרים את מרחב השמות לאפליקציית הדוגמה ולשער הכניסה:

    kubectl create namespace onlineboutique
    
  3. מתייגים את מרחב השמות onlineboutique כדי להחדיר אוטומטית שרתי proxy של Envoy. פועלים לפי השלבים במאמר איך מפעילים הוספה אוטומטית של קובצי sidecar.

  4. מפעילים את האפליקציה לדוגמה. במדריך הזה מפעילים את Online Boutique, אפליקציית הדגמה של מיקרו-שירות.

    kubectl apply \
    -n onlineboutique \
    -f https://raw.githubusercontent.com/GoogleCloudPlatform/anthos-service-mesh-samples/main/docs/shared/online-boutique/kubernetes-manifests.yaml
    
  5. כדי להוסיף תווית version=v1 לפריסת productcatalog, מריצים את הפקודה הבאה:

    kubectl patch deployments/productcatalogservice -p '{"spec":{"template":{"metadata":{"labels":{"version":"v1"}}}}}' \
    -n onlineboutique
    

    צופים בשירותים שפרסתם:

    kubectl get pods -n onlineboutique
    

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

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    הסמל 2/2 בעמודה READY מציין שהפוד פועל עם Envoy proxy שהוזרק בהצלחה.

  6. פריסה של VirtualService ו-DestinationRule לגרסה v1 של productcatalog:

     kubectl apply -f destination-vs-v1.yaml -n onlineboutique
    
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
    ---
    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1

    שימו לב שרק v1 מופיע במקורות המידע.

    לצפייה בDestination Rule שנוצר.

      kubectl get destinationrules -n onlineboutique
    

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

      NAME                    HOST                    AGE
      productcatalogservice   productcatalogservice   2m
    

    לצפייה בVirtualService שנוצר.

      kubectl get virtualservices -n onlineboutique
    

    התוצאה הצפויה:

      NAME                    GATEWAYS   HOSTS                       AGE
      productcatalogservice              ["productcatalogservice"]   2m
    
  7. נכנסים לאפליקציה בדפדפן באמצעות כתובת ה-IP החיצונית של שער הכניסה:

    kubectl get services -n GATEWAY_NAMESPACE
    

בקטע הבא נסביר איך אפשר לראות את המדדים בממשק המשתמש של Cloud Service Mesh.

צפייה בשירותים ב- Google Cloud Console

  1. במסוף Google Cloud , נכנסים לדף Google Kubernetes Engine (GKE) Enterprise edition Services.

    מעבר אל Google Kubernetes Engine‏ (GKE) Enterprise edition Services

  2. כברירת מחדל, השירותים מוצגים בתצוגת רשימה.

    בסקירה הכללית של הטבלה אפשר לראות את כל השירותים וגם מדדים חשובים במבט חטוף.

  3. בפינה השמאלית העליונה, לוחצים על Topology (טופולוגיה). כאן אפשר לראות את השירותים ואת האינטראקציה ביניהם.

    אפשר להרחיב את Services ולהציג את Requests per second לכל אחד מהשירותים על ידי העברת הסמן מעליהם.

  4. חוזרים לתצוגת הטבלה.

  5. בטבלת השירותים, בוחרים באפשרות productcatalogservice. הפעולה תעביר אתכם לסקירה כללית של השירות.

  6. בצד ימין של המסך, לוחצים על תנועה.

  7. מוודאים ש-100% מהתעבורה הנכנסת אל productcatalogservice מגיעה לשירות של עומס העבודה.

בקטע הבא מוסבר איך ליצור גרסה 2 של שירות productcatalog.

פריסת שירות מגרסה 2

  1. במדריך הזה, productcatalogservice-v2 מוסיף השהיה של 3 שניות לבקשות עם השדה EXTRA_LATENCY. הפעולה הזו מדמה רגרסיה בגרסה החדשה של השירות.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: productcatalogservice-v2
    spec:
      selector:
        matchLabels:
          app: productcatalogservice
      template:
        metadata:
          labels:
            app: productcatalogservice
            version: v2
        spec:
          containers:
          - env:
            - name: PORT
              value: '3550'
            - name: EXTRA_LATENCY
              value: 3s
            name: server
            image: gcr.io/google-samples/microservices-demo/productcatalogservice:v0.3.6
            livenessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            ports:
            - containerPort: 3550
            readinessProbe:
              exec:
                command: ["/bin/grpc_health_probe", "-addr=:3550"]
            resources:
              limits:
                cpu: 200m
                memory: 128Mi
              requests:
                cpu: 100m
                memory: 64Mi
          terminationGracePeriodSeconds: 5

    החלת המשאב הזה על מרחב השמות onlineboutique.

    kubectl apply -f productcatalog-v2.yaml -n onlineboutique
    
  2. בודקים את ה-pods של האפליקציה.

    kubectl get pods -n onlineboutique
    

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

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-8wqfd                  2/2     Running   0          25h
    cartservice-c77f6b866-7jwcr                 2/2     Running   0          25h
    checkoutservice-654c47f4b6-n8c6x            2/2     Running   0          25h
    currencyservice-59bc889674-l5xw2            2/2     Running   0          25h
    emailservice-5b9fff7cb8-jjr89               2/2     Running   0          25h
    frontend-77b88cc7cb-bwtk4                   2/2     Running   0          25h
    loadgenerator-6958f5bc8b-lqmnw              2/2     Running   0          25h
    paymentservice-68dd9755bb-dckrj             2/2     Running   0          25h
    productcatalogservice-84f95c95ff-ddhjv      2/2     Running   0          25h
    productcatalogservice-v2-6df4cf5475-9lwjb   2/2     Running   0          8s
    recommendationservice-64dc9dfbc8-7s7cx      2/2     Running   0          25h
    redis-cart-5b569cd47-vw7lw                  2/2     Running   0          25h
    shippingservice-5488d5b6cb-dj5gd            2/2     Running   0          25h
    

    שימו לב שמופיעים עכשיו שני productcatalogservices.

  3. משתמשים ב-DestinationRule כדי לציין את קבוצות המשנה של שירות. בתרחיש הזה, יש קבוצת משנה לגרסה 1 וקבוצת משנה נפרדת לגרסה 2 של productcatalogservice.

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: productcatalogservice
    spec:
      host: productcatalogservice
      subsets:
      - labels:
          version: v1
        name: v1
      - labels:
          version: v2
        name: v2

    שימו לב לשדה labels. הגרסאות של productcatalogservice מובחנות אחרי שהתנועה מנותבת על ידי VirtualService.

    מחילים את DestinationRule:

    kubectl apply -f destination-v1-v2.yaml -n onlineboutique
    

חלוקת התנועה בין גרסה 1 לגרסה 2

  1. משתמשים בערך VirtualService כדי להגדיר אחוז קטן של התנועה שיופנה לגרסה 2 של productcatalogservice.

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: productcatalogservice
    spec:
      hosts:
      - productcatalogservice
      http:
      - route:
        - destination:
            host: productcatalogservice
            subset: v1
          weight: 75
        - destination:
            host: productcatalogservice
            subset: v2
          weight: 25

    בשדה subset (קבוצת משנה) מצוינת הגרסה, ובשדה weight (משקל) מצוין אחוז חלוקת התנועה. ‫75% מהתנועה מגיעה לגרסה 1 של productcatalog ו-25% מגיעה לגרסה 2.

    מחילים את VirtualService:

    kubectl apply -f vs-split-traffic.yaml -n onlineboutique
    

אם תיכנסו ל-EXTERNAL_IP של ה-Ingress של האשכול, תבחינו מעת לעת שהקצה הקדמי נטען לאט יותר.

בקטע הבא, אפשר לראות את חלוקת התנועה במסוף Google Cloud .

מעקב אחר חלוקת התנועה במסוף Google Cloud

  1. חוזרים למסוף Google Cloud ועוברים לדף GKE Enterprise Services. מעבר לשירותי GKE Enterprise

  2. בפינה השמאלית העליונה, לוחצים על Topology (טופולוגיה).

    מרחיבים את עומס העבודה productcatalogservice ורושמים את הפריסות productcatalogservice ו-productcatalogservice-v2.

  3. חוזרים לתצוגת הטבלה.

  4. לוחצים על productcatalogservice בטבלת השירותים.

  5. חוזרים אל תנועה בסרגל הניווט הימני.

  6. שימו לב שהתנועה הנכנסת מחולקת בין גרסה 1 לגרסה 2 לפי האחוז שצוין בקובץ VirtualService, ושיש 2 עומסי עבודה של שירות productcatalog.

    בצד שמאל של הדף מופיעים בקשות, שיעור השגיאות ומדדי השהיה. בעזרת Cloud Service Mesh, כל שירות כולל את המדדים האלה כדי לספק לכם מדדי יכולת צפייה.

הפצה או חזרה לגרסה

אחרי שבודקים את המדדים במהלך פריסה של גרסה ראשונית (canary), אפשר להשלים את ההשקה של גרסת השירות החדשה או לחזור לגרסת השירות המקורית באמצעות משאב VirtualService.

השקה

אחרי שאתם מרוצים מההתנהגות של שירות v2, אתם יכולים להגדיל בהדרגה את אחוז התנועה שמופנה לשירות v2. בסופו של דבר, אפשר להפנות 100% מהתעבורה לשירות החדש במשאב VirtualService שיצרתם למעלה, על ידי הסרת חלוקת התנועה מהמשאב הזה.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v2

כדי להפנות את כל התנועה לגרסה 2 של productcatalogservice:

kubectl apply -f vs-v2.yaml -n onlineboutique

הוחזר למצב קודם

אם אתם צריכים לחזור לשירות v1, אתם יכולים להשתמש ב-destination-vs-v1.yaml מהשלב הקודם. ההגדרה הזו מפנה את התנועה רק לגרסה 1 של productcatalogservice.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: productcatalogservice
spec:
  hosts:
  - productcatalogservice
  http:
  - route:
    - destination:
        host: productcatalogservice
        subset: v1

כדי להפנות את כל התנועה לגרסה v1 של productcatalogservice:

kubectl apply -f vs-v1.yaml -n onlineboutique

הסרת המשאבים

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

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

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

ב-Cloud Shell, מוחקים את הפרויקט:

gcloud projects delete PROJECT_ID

מחיקת המשאבים

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

gcloud container clusters delete  CLUSTER_NAME  \
  --project=PROJECT_ID \
  --zone=CLUSTER_LOCATION 

אם רשמתם את האשכול ב-Fleet באמצעות gcloud container fleet memberships (במקום --enable-fleet או --fleet-project במהלך יצירת האשכול), צריך להסיר את החברות שפג תוקפה:

gcloud container fleet memberships delete  MEMBERSHIP  \
  --project=PROJECT_ID

אם רוצים להשאיר את האשכול מוגדר ל-Cloud Service Mesh אבל להסיר את הדוגמה Online Boutique:

  1. מוחקים את מרחבי השמות של האפליקציה:

    kubectl delete -f namespace onlineboutique
    

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

    namespace "onlineboutique" deleted
    
  2. מוחקים את רשומות השירות:

    kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend.yaml -n onlineboutique
    kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/microservices-demo/main/istio-manifests/frontend-gateway.yaml -n onlineboutique
    

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

    serviceentry.networking.istio.io "allow-egress-googleapis" deleted
    serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
    

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