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

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

ASP.NET Core היא מסגרת קוד פתוח בפלטפורמות שונות ליצירת אפליקציות מודרניות מבוססות-ענן ומחוברות לאינטרנט באמצעות שפת התכנות C#.

Kubernetes היא מערכת קוד פתוח לאוטומציה של פריסה, התאמה לעומס (scaling) וניהול של אפליקציות בקונטיינרים. ‫Istio הוא מסגרת קוד פתוח לחיבור, לאבטחה, לניהול ולניטור של שירותים.

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

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

מה תלמדו

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

הדרישות

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

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

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

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

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

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

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

חשוב לזכור את מזהה הפרויקט, שהוא שם ייחודי בכל הפרויקטים ב-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 4292cbf4971c9786.png.

bce75f34b2c53987.png

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

70f315d7b402b476.png

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

fbe3a0674c982259.png

המכונה הווירטואלית הזו כוללת את כל הכלים שדרושים למפתחים. יש בה ספריית בית בנפח מתמיד של 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`
  1. מריצים את הפקודה הבאה ב-Cloud Shell כדי לוודא שפקודת gcloud מכירה את הפרויקט:
gcloud config list project

פלט הפקודה

[core]
project = <PROJECT_ID>

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

gcloud config set project <PROJECT_ID>

פלט הפקודה

Updated property [core/project].

3. יצירת אפליקציית ASP.NET Core ב-Cloud Shell

בשורת הפקודה של Cloud Shell, אפשר לבדוק את הגרסה של כלי שורת הפקודה dotnet כדי לוודא שהוא כבר מותקן. הפקודה הזו אמורה להדפיס את הגרסה של כלי שורת הפקודה dotnet שהותקן:

dotnet --version

בשלב הבא, יוצרים אפליקציית אינטרנט בסיסית חדשה ב-ASP.NET Core.

dotnet new mvc -o HelloWorldAspNetCore

ייווצר פרויקט ויחסי התלות ישוחזרו. אמורה להופיע הודעה דומה לזו שכאן למטה.

Restore completed in 11.44 sec for HelloWorldAspNetCore.csproj.

Restore succeeded.

4. הפעלת אפליקציית ASP.NET Core

כמעט סיימנו להכין את האפליקציה להרצה. עוברים לתיקיית האפליקציה.

cd HelloWorldAspNetCore

לבסוף, מפעילים את האפליקציה.

dotnet run --urls=http://localhost:8080

האפליקציה מתחילה להאזין ביציאה 8080.

Hosting environment: Production
Content root path: /home/atameldev/HelloWorldAspNetCore
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.

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

Capture.PNG

יוצג דף האינטרנט שמוגדר כברירת מחדל ב-ASP.NET Core:

f579a9baedc108a9.png

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

5. אריזת אפליקציית ASP.NET Core בקונטיינר של Docker

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

בספריית הבסיס של האפליקציה, יוצרים קובץ Dockerfile כדי להגדיר את קובץ אימג' של Docker.

touch Dockerfile

מוסיפים את הקוד הבא ל-Dockerfile באמצעות העורך המועדף (vim, nano,emacs או עורך הקוד של Cloud Shell).

# Use Microsoft's official build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS build
WORKDIR /app

# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore

# Copy local code to the container image.
COPY . ./
WORKDIR /app

# Build a release artifact.
RUN dotnet publish -c Release -o out

# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/aspnet:5.0-alpine AS runtime
WORKDIR /app
COPY --from=build /app/out ./

# Make sure the app binds to port 8080
ENV ASPNETCORE_URLS http://*:8080

# Run the web service on container startup.
ENTRYPOINT ["dotnet", "HelloWorldAspNetCore.dll"]

אחת מההגדרות החשובות שכלולות ב-קובץ Docker הוא הפורט שבו האפליקציה מאזינה לתעבורה נכנסת (8080). כדי לעשות את זה, מגדירים את משתנה הסביבה ASPNETCORE_URLS, שאפליקציות ASP.NET Core משתמשות בו כדי לקבוע באיזה פורט להאזין.

שמירת Dockerfile. עכשיו ניצור את התמונה:

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

אחרי שהתהליך יסתיים (ייקח זמן להוריד ולחלץ את כל הנתונים), תוכלו לראות שהתמונה נוצרה ונשמרה באופן מקומי:

docker images

REPOSITORY                             TAG   
gcr.io/yourproject-XXXX/hello-dotnet   v1            

בודקים את קובץ האימג' של הקונטיינר באופן מקומי באמצעות הפקודה הבאה, שתריץ קונטיינר של Docker באופן מקומי ביציאה 8080 מקובץ האימג' החדש של הקונטיינר שיצרתם:

docker run -p 8080:8080 gcr.io/${GOOGLE_CLOUD_PROJECT}/hello-dotnet:v1

ושוב, אפשר להשתמש בתכונה 'תצוגה מקדימה באינטרנט' של Cloud Shell :

Screenshot from 2015-11-03 17:20:22.png

דף האינטרנט של ASP.NET Core שמוגדר כברירת מחדל אמור להופיע בכרטיסייה חדשה.

f579a9baedc108a9.png

אחרי שמוודאים שהאפליקציה פועלת בצורה תקינה באופן מקומי בקונטיינר Docker, אפשר לעצור את הקונטיינר הפועל באמצעות Ctrl-> C.

עכשיו, אחרי שקובץ האימג' פועל כמו שרציתם, אתם יכולים להעביר אותו בדחיפה אל Google Container Registry, מאגר פרטי של קובצי Docker שאפשר לגשת אליו מכל פרויקט בענן (אבל גם מחוץ ל-Google Cloud Platform) :

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

אם הכול ילך כשורה, אחרי כמה דקות קובץ אימג' של קונטיינר יופיע בקטע Container Registry. בשלב הזה, יש לכם קובץ אימג' של Docker שזמין בכל הפרויקט, ו-Kubernetes יכולה לגשת אליו ולתזמן אותו, כפי שתראו בעוד כמה דקות.

73558f3a54ce1c0c.png

אם אתם רוצים, אתם יכולים לעיין בתמונות של הקונטיינרים כפי שהן מאוחסנות ב-Google Cloud Storage. לשם כך, צריך ללחוץ על הקישור הזה: https://console.cloud.google.com/storage/browser/ (הקישור המלא שיווצר צריך להיות מהצורה הזו: https://console.cloud.google.com/project/PROJECT_ID/storage/browser/).

6. יצירת אשכול GKE עם Istio

קודם כל, מוודאים ש-Kubernetes Engine API מופעל:

gcloud services enable container.googleapis.com

יוצרים אשכול Kubernetes. אם רוצים, אפשר לשנות את האזור למקום שקרוב אליכם:

gcloud container clusters create hello-istio \
  --cluster-version=latest \
  --machine-type=n1-standard-2 \
  --num-nodes=4 \
  --region europe-west1

מחכים כמה רגעים עד שהאשכול מוגדר. הוא יוצג בקטע Kubernetes Engine במסוף Google Cloud Platform.

e46fd9c6ee82bcc4.png

ב-Codelab הזה נוריד ונתקין את Istio מ-istio.io. יש אפשרויות התקנה נוספות, כולל התוסף Istio ל-GKE ו-Anthos Service Mesh. השלבים הבאים בהגדרת האפליקציה יפעלו בכל התקנה של Istio.

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

curl -L https://istio.io/downloadIstio | sh -

הסקריפט יציג את הגרסה של Istio שהורדה:

Istio has been successfully downloaded into the istio-1.8.1 folder on your system.

ספריית ההתקנה מכילה אפליקציות לדוגמה ואת הקובץ הבינארי של לקוח istioctl. עוברים לספרייה הזו:

cd istio-1.8.1

מעתיקים את הפקודה שמופיעה למעלה ומדביקים אותה כדי להוסיף את הספרייה bin ל-PATH, וכך תוכלו להשתמש ב-istioctl:

export PATH="$PATH:/home/<YOURHOMEID>/istio-1.8.1/bin"

כדי לוודא ש-istioctl זמין, בודקים שהאשכול מוכן ל-Istio:

istioctl x precheck

אמורה להופיע ההודעה Install Pre-Check passed! The cluster is ready for Istio installation.

מתקינים את Istio עם פרופיל הדגמה:

istioctl install --set profile=demo

‫Istio מותקן עכשיו באשכול.

הוספה אוטומטית של קובץ sidecar

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

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

kubectl label namespace default istio-injection=enabled

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

kubectl get namespace -L istio-injection

הפלט מאשר שהזרקת sidecar מופעלת במרחב השמות שמוגדר כברירת מחדל:

NAME              STATUS   AGE    ISTIO-INJECTION
default           Active   3m     enabled
istio-system      Active   63s    disabled
...

7. אימות ההתקנה

‫Istio מגיע עם שלושה שירותים: istiod מישור הבקרה, ושערי כניסה ויציאה (שאפשר לחשוב עליהם כעל "קובץ עזר חיצוני לשאר האינטרנט") , שנקראים istio-ingressgateway ו-istio-egressgateway בהתאמה.

kubectl get svc -n istio-system

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

NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP                                                                     AGE
istio-egressgateway    ClusterIP      10.55.252.182   <none>
istio-ingressgateway   LoadBalancer   10.55.250.185   35.233.118.42
istiod                 ClusterIP      10.55.253.217   <none>

ל-Ingress Gateway יש סוג של LoadBalancer ולכן אפשר לגשת אליו מהאינטרנט. לשאר הרכיבים צריך להיות אפשר לגשת רק מתוך האשכול.

לאחר מכן, מוודאים שה-pods המתאימים של Kubernetes נפרסו וכל הקונטיינרים פועלים:

kubectl get pods -n istio-system

אחרי שכל ה-pods יפעלו, תוכלו להמשיך.

NAME                                    READY   STATUS
istio-egressgateway-674988f895-m6tk4    1/1     Running
istio-ingressgateway-6996f7dcc8-7lvm2   1/1     Running
istiod-6bf5fc8b64-j79hj                 1/1     Running
  • istiod: מישור הבקרה של Istio. הוא מטפל בהגדרה ובתכנות של תוספי ה-proxy, בזיהוי השירותים, בהפצת האישורים ובהוספת תוספי ה-proxy
  • ingress gateway: מטפל בבקשות נכנסות מחוץ לאשכול.
  • egress gateway: מטפל בבקשות יוצאות לנקודות קצה מחוץ לאשכול.

8. פריסת האפליקציה

אחרי שמוודאים ש-Istio מותקן ופועל, אפשר לפרוס את אפליקציית ASP.NET Core.

פריסה ושירות

קודם יוצרים קובץ aspnetcore.yaml באמצעות העורך המועדף (vim, nano,emacs או עורך הקוד של Cloud Shell) ומגדירים את הפריסה והשירות של Kubernetes לאפליקציה:

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

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

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

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

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

kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
aspnetcore-v1-6cf64748-mddb   2/2       Running   0          34s

Gateway ו-VirtualService

כדי לאפשר לתעבורת נתונים נכנסת (ingress) להגיע לרשת, צריך ליצור שער וVirtualService.

שער מגדיר מאזן עומסים לתעבורת HTTP/TCP, ולרוב הוא פועל בקצה של הרשת כדי לאפשר תעבורת נתונים נכנסת (ingress) לאפליקציה. ‫VirtualService מגדיר את הכללים שקובעים איך בקשות לשירות מנותבות בתוך Service mesh של Istio.

יוצרים קובץ aspnetcore-gateway.yaml כדי להגדיר את השער:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: aspnetcore-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

יוצרים קובץ aspnetcore-virtualservice.yaml כדי להגדיר את VirtualService:

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

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

kubectl apply -f aspnetcore-gateway.yaml

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

gateway.networking.istio.io "aspnetcore-gateway" created

לאחר מכן, מריצים את הפקודה הבאה כדי לפרוס את VirtualService:

kubectl apply -f aspnetcore-virtualservice.yaml

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

virtualservice.networking.istio.io "aspnetcore-virtualservice" created

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

kubectl get gateway
NAME                      AGE
aspnetcore-gateway   28s
kubectl get virtualservice
NAME                             AGE
aspnetcore-virtualservice   33s

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

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

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

kubectl get svc istio-ingressgateway -n istio-system

מייצאים את כתובת ה-IP החיצונית והיציאה למשתנה GATEWAY_URL:

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')

export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT

משתמשים ב-curl כדי לבדוק את האפליקציה. השירות אמור להגיב עם קוד תגובה 200:

curl -o /dev/null -s -w "%{http_code}\n" http://${GATEWAY_URL}/

אפשר גם לפתוח את הדפדפן, לעבור אל http://<gatewayurl> כדי לראות את האפליקציה:

f579a9baedc108a9.png

10. מעולה!

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

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

השלבים הבאים

רישיון

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

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

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

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

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

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

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

kubectl get gateway 
kubectl get virtualservices 
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-istio