פריסת אפליקציית ASP.NET Core ב-Google Kubernetes Engine באמצעות Istio (חלק 2)

1. סקירה כללית

בחלק הראשון של ה-Lab, יצרתם אפליקציית ASP.NET Core, הכנסתם אותה לקונטיינר ופרסתם אותה ב-Google Kubernetes Engine ‏ (GKE), והגדרתם את התנועה שלה כך שתנוהל על ידי Istio.

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

מה תלמדו

  • איך שולחים שאילתות למדדים באמצעות Prometheus.
  • איך להמחיש מדדים באמצעות Grafana.
  • איך ליצור גרסה חדשה של השירות.
  • איך מצמידים שירות לגרסה ספציפית.
  • איך לפצל את התנועה בין גרסאות שונות.
  • איך להחדיר תקלות לקריאות שירות.

הדרישות

איך תשתמשו במדריך הזה?

רק לקרוא לקרוא ולבצע את התרגילים

איזה דירוג מגיע לדעתך לחוויה שלך עם Google Cloud Platform?

מתחילים ביניים מומחים

2. הגדרה ודרישות

הגדרת סביבה בקצב אישי

  1. נכנסים אל Cloud Console ויוצרים פרויקט חדש או משתמשים בפרויקט קיים. (אם עדיין אין לכם חשבון Gmail או G Suite, אתם צריכים ליצור חשבון).

H_hgylo4zxOllHaAbPKJ7VyqCKPDUnDhkr-BsBIFBsrB6TYSisg6LX-uqmMhh4sXUy_hoa2Qv87C2nFmkg-QAcCiZZp0qtpf6VPaNEEfP_iqt29KVLD-gklBWugQVeOWsFnJmNjHDw

dcCPqfBIwNO4R-0fNQLUC4aYXOOZhKhjUnakFLZJGeziw2ikOxGjGkCHDwN5x5kCbPFB8fiOzZnX-GfuzQ8Ox-UU15BwHirkVPR_0RJwl0oXrhqZmMIvZMa_uwHugBJIdx5-bZ6Z8Q

jgLzVCxk93d6E2bbonzATKA4jFZReoQ-fORxZZLEi5C3D-ubnv6nL-eP-iyh7qAsWyq_nyzzuEoPFD1wFOFZOe4FWhPBJjUDncnTxTImT3Ts9TM54f4nPpsAp52O0y3Cb19IceAEgQ

חשוב לזכור את מזהה הפרויקט, שהוא שם ייחודי בכל הפרויקטים ב-Google Cloud (השם שלמעלה כבר תפוס ולא יתאים לכם, מצטערים!). בהמשך ה-codelab הזה נתייחס אליו כאל PROJECT_ID.

  1. לאחר מכן, תצטרכו להפעיל את החיוב ב-Cloud Console כדי להשתמש במשאבים של Google Cloud.

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

מפעילים את Cloud Shell

אפשר להפעיל את Google Cloud מרחוק מהמחשב הנייד, אבל ב-codelab הזה משתמשים ב-Google Cloud Shell, סביבת שורת פקודה שפועלת ב-Google Cloud.

הפעלת Cloud Shell

  1. ב-Cloud Console, לוחצים על Activate Cloud Shell dnDTxS9j60RcXdTjea12HLB9paS9Gzf7PfFLE9RW8g0Qx1bz7nmCzyCu4rjluX3bOEwavOpDwioXEkzOf6xtZp6-ZbJa08jwJqtmeeW8jZ1tYfi2lyXqvW3WFHP0eAxDkQDfpO9Ljw.

yzBQBp2RC1EFvSSLYVkMA2m6LHqGsp22O81rUS5tGb9Y1FqlVhoRj_ka8V_uEjtpcirZRULMy1IjNr848uYvb9mC9RcGGqeayaLcXFfRwUGeXWChZPtWkHzUshTcqx_wJHis0X8viA

אם זו הפעם הראשונה שאתם מפעילים את Cloud Shell, יוצג לכם מסך ביניים (בחלק הנגלל) עם תיאור של Cloud Shell. במקרה כזה, לוחצים על המשך (והמסך הזה לא יוצג לכם יותר). כך נראה המסך החד-פעמי:

VgsaqGbKPRiqK24CqAKjSXjepuJT96PmiDqQMcySmWKx8QyW5F3G2D8JH2d08ek-YM77wWKxPvggpOFER8Hbq3aaZipTDU2o0il7A0kS3FXY_NzuujjEqDF1nsbDKkNMThrqcdMGtQ

הקצאת המשאבים והחיבור ל-Cloud Shell נמשכים רק כמה רגעים.

7RuYr-LCKzdiE1veTFmL_lYrVxsMZ6-xDoxAnfwPPc5uFA0utmFGejvu81jGmTdbqnqxrytW3KcHT6xrMIRc3bskctnDZC5nJdpqw-LRxu3r35hL4A0BSBTtbtirfh3PKv-eOKt8Rg

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 5GB והיא פועלת ב-Google Cloud, מה שמשפר מאוד את הביצועים והאימות ברשת. אפשר לבצע את רוב העבודה ב-codelab הזה, אם לא את כולה, באמצעות דפדפן או Chromebook.

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

  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שעברתם אימות:
gcloud auth list

פלט הפקודה

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

אם לא, אפשר להגדיר אותו באמצעות הפקודה הבאה:

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. בדיקת האפליקציה

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

kubectl get svc istio-ingressgateway -n istio-system

כדי לראות את האפליקציה, אפשר לפתוח את הדפדפן ולנווט אל http://<gatewayurl>:

f579a9baedc108a9.png

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

בשלב הזה, יכול להיות שאתם שואלים את עצמכם: "מה היתרון של Istio?". אם מאפשרים ל-Istio לנהל את התנועה של האפליקציה, מקבלים בחינם תכונות כמו מדדים, מעקב, ניהול דינמי של תנועה, ויזואליזציה של שירותים, הזרקת תקלות ועוד.

בשלב הבא נסביר על המדדים.

4. מדדים עם Grafana ו-Prometheus

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

Prometheus

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

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/prometheus.yaml

מוודאים ש-Prometheus פועל:

kubectl get svc prometheus -n istio-system

NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
prometheus   ClusterIP   10.31.243.62   <none>        9090/TCP   1d

כדי לשלוח עומס תנועה קל לאפליקציה, מבקרים ב-http://<gatewayurl> כמה פעמים או מריצים את פקודת ה-curl.

הגדרת העברה ליציאה אחרת לממשק המשתמש של Prometheus:

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=prometheus -o jsonpath='{.items[0].metadata.name}') 8080:9090

עכשיו אפשר להריץ שאילתה. לשם כך, לוחצים על הלחצן 'תצוגה מקדימה בדפדפן' בפינה הימנית העליונה של Cloud Shell ואז על תצוגה מקדימה ביציאה 8080:

772a5248aa493025.png

ממשק המשתמש של Prometheus יופיע בכרטיסייה חדשה:

272ee63c1fe0be16.png

מידע נוסף על Prometheus זמין במאמר שאילתות של מדדים באמצעות Prometheus.

Grafana

Grafana הוא תוסף נוסף להצגת מדדים בצורה ויזואלית.

מתקינים את Grafana. מחליפים את istio-version בגרסת Istio הנוכחית,לדוגמה, 1.0.3-gke.3:

kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.8/samples/addons/grafana.yaml

מוודאים ש-Grafana פועל:

kubectl get svc grafana -n istio-system

NAME      TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
grafana   ClusterIP   10.31.248.230   <none>        3000/TCP   1d

כדי לשלוח עומס תנועה קל לאפליקציה, מבקרים ב-http://<gatewayurl> כמה פעמים או מריצים את פקודת ה-curl.

הגדרת העברה ליציאה אחרת לממשק המשתמש של Grafana:

kubectl -n istio-system port-forward $(kubectl -n istio-system get pod -l app=grafana -o jsonpath='{.items[0].metadata.name}') 8080:3000

כדי לראות את לוחות הבקרה של Grafana, אפשר להיכנס לתצוגה המקדימה באינטרנט:

806d696d85267a37.png

524cb9f6d66f8655.png

מידע נוסף על Grafana זמין במאמר בנושא הצגת מדדים באמצעות Grafana.

5. יצירת גרסה חדשה של האפליקציה

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

קודם נשנה את האפליקציה. פותחים את עורך הקוד מ-Cloud Shell.

mxrggIJ2Zz8E47ULCEo4NywjM-EpSkZF5c3TQgfGx4nODwP2obiQXrwQjEEaXuBhJDA2jJ5evR7TuHIy1gsqqDRFm0Wh3xhZUu9tn_xb1ygFlBm1HKJqLdfz_aK7WJS33u2IBDO2oQ

עוברים אל Index.cshtml בקטע HelloWorldAspNetCore > Views > Home ומעדכנים אחת מההודעות בקרוסלה.

מחפשים את השורה הבאה:

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core 

ולשנות אותו כך:

Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core on Google Cloud

שומרים את השינויים וחוזרים אל Cloud Shell. בתוך HelloWorldAspNetCore,, יוצרים את קובץ האימג' של Docker:

docker build -t gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 . 

ומבצעים push ל-Container Registry:

docker push gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v2 

אחרי שמעבירים את קובץ אימג' של קונטיינר, אפשר לפרוס את הגרסה החדשה בשלב הבא.

6. יצירת הפריסה החדשה

כדי לפרוס את הגרסה החדשה, צריך קודם ליצור פריסה חדשה שלה ב-Kubernetes. מוסיפים את הטקסט הבא בסוף הקובץ aspnetcore.yaml:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aspnetcore-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: aspnetcore
      version: v2
  template:
    metadata:
      labels:
        app: aspnetcore
        version: v2
    spec:
      containers:
      - name: aspnetcore
        image: gcr.io/YOUR-PROJECT-ID/hello-dotnet:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080

פורסים את הגרסה החדשה במרחב השמות שמוגדר כברירת מחדל באמצעות kubectl:

kubectl apply -f aspnetcore.yaml
service "aspnetcore" unchanged
deployment.extensions "aspnetcore-v1" unchanged
deployment.extensions "aspnetcore-v2" created

מוודאים שהפודים הרצויים פועלים:

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s
aspnetcore-v2-5d765db-l9xmg   2/2       Running   0          1m

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

kubectl get svc istio-ingressgateway -n istio-system

הוא מופיע בקטע EXTERNAL-IP. פותחים דפדפן במצב פרטי ועוברים אל http://<replace-with-external-ip>

כשמרעננים, לפעמים מופיעה ההודעה 'מידע על בניית אפליקציות אינטרנט באמצעות ASP.NET Core':

11d528132dbb6cee.png

במקרים אחרים, תופיע ההודעה 'מידע על פיתוח אפליקציות אינטרנט באמצעות ASP.NET Core ב-Google Cloud':

3eb0d5be1b4cb40b.png

הסיבה לכך היא שפריסות v1 ו-v2 נחשפות מאחורי אותו שירות Kubernetes ‏ (aspnetcore-service), וה-VirtualService שיצרתם במעבדה הקודמת (aspnetcore-virtualservice) משתמש בשירות הזה כמארח.

בשלב הבא, מצמידים את השירות לפריסה של v2 באמצעות DestinationRule.

7. הצמדת השירות לגרסה החדשה

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

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

יוצרים קובץ חדש בשם aspnetcore-destinationrule.yaml:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: aspnetcore-destinationrule
spec:
  host: aspnetcore-service
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

לאחר מכן, יוצרים את DestinationRule. כך נוצרים שני תת-קבוצות (v1 ו-v2) שאפשר להשתמש בהם מ-VirtualService:

kubectl apply -f aspnetcore-destinationrule.yaml
destinationrule.networking.istio.io "aspnetcore-destionationrule" created

עכשיו חוזרים לקובץ aspnetcore-virtualservice.yaml כדי לעדכן את VirtualService כך שישתמש בקבוצת המשנה v2:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v2

מעדכנים את VirtualService:

kubectl apply -f aspnetcore-virtualservice.yaml

פותחים את הדפדפן ועוברים אל http://<replace-with-external-ip>. גם אחרי כמה רענונים, אמורה להופיע ההודעה 'מידע על פיתוח אפליקציות אינטרנט באמצעות ASP.NET Core ב-Google Cloud':

3eb0d5be1b4cb40b.png

8. חלוקת התנועה בין גרסאות

לפעמים כדאי לפצל את התנועה בין גרסאות לצורך בדיקה. לדוגמה, יכול להיות שתרצו לשלוח 75% מהתנועה לגרסה v1 ו-25% מהתנועה לגרסה v2 של השירות. אפשר לעשות את זה בקלות באמצעות Istio. יוצרים קובץ aspnetcore-virtualservice-weights.yaml חדש כדי להתייחס לשתי קבוצות המשנה עם משקלים שונים:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - route:
    - destination:
        host: aspnetcore-service
        subset: v1
      weight: 75
    - destination:
        host: aspnetcore-service
        subset: v2
      weight: 25

מעדכנים את VirtualService:

kubectl apply -f aspnetcore-virtualservice-weights.yaml

עכשיו, כשמרעננים את הדפדפן, אמורות להיות מוצגות הגרסאות v1 ו-v2 ביחס של בערך 3:1.

מידע נוסף זמין במאמר בנושא פיצול תנועה ב-Istio.

9. הזרקת תקלות

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

לדוגמה, יכול להיות שתרצו להחזיר תגובה של בקשה שגויה (HTTP 400) ל-50% מהתנועה לגרסה v1. יוצרים קובץ aspnetcore-virtualservice-fault-abort.yaml שזהה לזה:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      abort:
        percentage:
          value: 50
        httpStatus: 400
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

מעדכנים את VirtualService:

kubectl apply -f aspnetcore-virtualservice-fault-abort.yaml

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

או אולי רוצים להוסיף עיכוב של 5 שניות לבקשות. יוצרים קובץ aspnetcore-virtualservice-fault-delay.yaml שזהה לזה:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: aspnetcore-virtualservice
spec:
  hosts:
  - "*"
  gateways:
  - aspnetcore-gateway
  http:
  - fault:
      delay:
        fixedDelay: 5s
        percentage:
          value: 100
    route:
    - destination:
        host: aspnetcore-service
        subset: v1

מעדכנים את VirtualService:

kubectl apply -f aspnetcore-virtualservice-fault-delay.yaml

עכשיו, כשמרעננים את הדפדפן, אמורים לראות שהבקשות מתעכבות ב-5 שניות.

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

10. מעולה!

אנחנו מקווים שקיבלתם בשיעור Lab הזה סקירה כללית על האפשרויות ש-Istio מציע לשירותים שלכם. מידע נוסף על Istio ו-GKE

השלבים הבאים

רישיון

עבודה זו מורשית תחת רישיון Creative Commons שמותנה בייחוס 2.0 כללי.

11. הסרת המשאבים

אפשר למחוק את האפליקציה ולהסיר את Istio, או פשוט למחוק את אשכול Kubernetes.

מחיקת האפליקציה

כדי למחוק את האפליקציה:

kubectl delete -f aspnetcore-gateway.yaml
kubectl delete -f aspnetcore-virtualservice.yaml
kubectl delete -f aspnetcore-destinationrule.yaml
kubectl delete -f aspnetcore.yaml

כדי לוודא שהאפליקציה נעלמה:

kubectl get gateway 
kubectl get virtualservices
kubectl get destinationrule
kubectl get pods

הסרת ההתקנה של Istio

כדי למחוק את Istio:

kubectl delete -f install/kubernetes/istio-demo-auth.yaml

כדי לוודא ש-Istio הוסר:

kubectl get pods -n istio-system

מחיקת אשכול Kubernetes

gcloud container clusters delete hello-dotnet-cluster