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

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

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

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

בחלק הראשון של שיעור ה-Lab, פרסתם אפליקציה פשוטה של 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 ויוצרים פרויקט חדש או עושים שימוש חוזר בפרויקט קיים. אם אין לכם עדיין חשבון Gmail או חשבון Google Workspace, עליכם ליצור חשבון.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

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

  1. בשלב הבא צריך להפעיל את החיוב במסוף Cloud כדי להשתמש במשאבים של Google Cloud.

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

הפעלת Cloud Shell

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

הפעלת Cloud Shell

  1. במסוף Cloud, לוחצים על 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 כבר מותקן, בודקים את הגרסה שלו. הפקודה הזו אמורה להדפיס את הגרסה של כלי שורת הפקודה Docnet המותקן:

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

ושוב תוכלו לנצל את תכונת התצוגה המקדימה באינטרנט של CloudShell :

צילום מסך מ-2015-11-03 17:20:22.png

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

f579a9baedc108a9.png

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

עכשיו, כשהתמונה פועלת כמו שצריך, אפשר להעביר אותה ל-Google Container Registry – מאגר פרטי של תמונות Docker שאפשר לגשת אליהן מכל פרויקט ב-Google Cloud (אבל גם מחוץ ל-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. יצירת אשכול Kubernetes/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 כולל פריטי מידע שנוצרו בתהליך פיתוח (Artifact) להורדה של כמה מערכות הפעלה. במקרה שלנו, נוכל להשתמש בפקודה נוחה כדי להוריד ולחלץ את הגרסה האחרונה עבור הפלטפורמה הנוכחית שלנו:

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 מותקן עכשיו באשכול שלך.

החדרה אוטומטית לרכב משני

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

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

kubectl label namespace default istio-injection=enabled

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

kubectl get namespace -L istio-injection

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

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

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

Istio כולל שלושה שירותים: מישור הבקרה istiod ושערי תעבורת הנתונים היוצאת (ingress) ותעבורת הנתונים היוצאת (egress) (אפשר להתייחס אליהם כאל שרתי proxy לשאר האינטרנט) , שנקראים 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) הוא מסוג LoadBalancer ולכן הוא נגיש מהאינטרנט; האחרים צריכים להיות נגישים רק מתוך האשכול.

בשלב הבא, צריך לוודא שהקבוצות המתאימות של 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, גילוי שירותים, הפצת אישורים והחדרת צדדיים לרכב
  • 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

תוכן הקובץ הוא Deployments and Services (פריסות ושירותים) סטנדרטיים לפריסת האפליקציה והוא לא מכיל שום תוכן ספציפי ל-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 כדי לפרוס את Gateway באמצעות:

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 ינהל את האפליקציה הזו. בחלק השני של שיעור ה-Lab, נבחן לעומק תכונות של Istio, כמו מדדים, מעקב, ניהול דינמי של תעבורת נתונים, תרשים להמחשת שירותים והחדרת תקלות.

השלבים הבאים

רישיון

היצירה הזו בשימוש ברישיון Creative Commons Attribution 2.0 גנרי.

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

אם לא ממשיכים לחלק השני של שיעור ה-Lab, אפשר למחוק את האפליקציה ולהסיר את 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