نشر تطبيق ASP.NET Core على Google Kubernetes Engine باستخدام Istio (الجزء 1)

1. نظرة عامة

ASP.NET Core هو إطار عمل مفتوح المصدر ومتوافق مع عدة أنظمة أساسية لإنشاء تطبيقات حديثة مستندة إلى السحابة الإلكترونية ومتصلة بالإنترنت باستخدام لغة البرمجة C#.

‫Kubernetes هو نظام مفتوح المصدر لأتمتة عمليات نشر التطبيقات وتوسيع نطاقها وإدارتها ضِمن الحاويات. Istio هو إطار عمل مفتوح المصدر لربط الخدمات وتأمينها وإدارتها ومراقبتها.

في هذا الجزء الأول من المختبر، ستنشئ تطبيق ASP.NET Core بسيطًا على Kubernetes يعمل على Google Kubernetes Engine (GKE) وتضبطه ليتم إدارته بواسطة Istio.

في الجزء الثاني من التمرين العملي، ستستكشف المزيد من ميزات 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 (الاسم أعلاه مستخدَم حاليًا ولن يكون متاحًا لك، نأسف لذلك). سيتم الإشارة إليه لاحقًا في هذا الدرس العملي باسم PROJECT_ID.

  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد Google Cloud.

لن تكلفك تجربة هذا الدرس التطبيقي حول الترميز الكثير من المال، إن لم تكلفك شيئًا على الإطلاق. احرص على اتّباع أي تعليمات في قسم "التنظيف" الذي ينصحك بكيفية إيقاف الموارد حتى لا تتحمّل رسومًا تتجاوز هذا البرنامج التعليمي. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.

بدء Cloud Shell

على الرغم من إمكانية تشغيل Google Cloud عن بُعد من الكمبيوتر المحمول، ستستخدم في هذا الدرس العملي Google Cloud Shell، وهي بيئة سطر أوامر تعمل في Google Cloud.

تفعيل Cloud Shell

  1. من Cloud Console، انقر على تفعيل Cloud Shell 4292cbf4971c9786.png.

bce75f34b2c53987.png

إذا لم يسبق لك بدء Cloud Shell، ستظهر لك شاشة وسيطة (الجزء السفلي غير المرئي من الصفحة) توضّح ماهيته. في هذه الحالة، انقر على متابعة (ولن تظهر لك مرة أخرى). في ما يلي الشكل الذي ستظهر به هذه الشاشة لمرة واحدة:

70f315d7b402b476.png

يستغرق توفير Cloud Shell والاتصال به بضع لحظات فقط.

fbe3a0674c982259.png

يتم تحميل هذا الجهاز الافتراضي بجميع أدوات التطوير التي تحتاج إليها. توفّر هذه الخدمة دليلًا رئيسيًا دائمًا بسعة 5 غيغابايت وتعمل في Google Cloud، ما يؤدي إلى تحسين أداء الشبكة والمصادقة بشكل كبير. يمكن إنجاز معظم العمل في هذا الدرس التطبيقي حول الترميز، إن لم يكن كله، باستخدام متصفّح أو جهاز 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، يمكنك التأكّد من أنّ أداة سطر الأوامر ‎.NET مثبّتة حاليًا من خلال التحقّق من إصدارها. من المفترض أن يؤدي ذلك إلى طباعة إصدار أداة سطر الأوامر 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"]

أحد الإعدادات المهمة المضمّنة في ملف Dockerfile هو المنفذ الذي يستمع إليه التطبيق لتلقّي الزيارات الواردة (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 :

Screenshot from 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

في هذا الدرس التطبيقي حول الترميز، سننزّل 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 الجانبية في كل وحدة من وحدات الخدمة.

ولكي ينجح ذلك، عليك تفعيل ميزة "إدخال الحاويات الجانبية" لمساحة الاسم (default) التي تستخدمها لخدماتك المصغّرة. يمكنك إجراء ذلك من خلال تطبيق تصنيف:

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 وبوابات الدخول والخروج (التي يمكنك اعتبارها "خوادم وكيل جانبية لبقية الإنترنت")، ويُطلق عليها اسم 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، لذا يمكن الوصول إليه من الإنترنت، بينما لا تحتاج الأنواع الأخرى إلى إمكانية الوصول إليها إلا من داخل المجموعة.

بعد ذلك، تأكَّد من نشر وحدات Kubernetes المتطابقة وأنّ جميع الحاويات تعمل:

kubectl get pods -n istio-system

بعد تشغيل جميع الوحدات، يمكنك المتابعة.

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 تتعامل مع إعداد وبرمجة البرامج المساعدة للخادم الوكيل، واكتشاف الخدمات، وتوزيع الشهادات، وإضافة البرامج المساعدة
  • 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

تأكَّد من أنّ وحدات pod قيد التشغيل:

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

البوابة وVirtualService

للسماح لحركة المرور الواردة بالوصول إلى الشبكة المتداخلة، عليك إنشاء بوابة وVirtualService.

تُعدّ البوابة جهاز موازنة حمل لحركة بيانات HTTP/TCP، وتعمل عادةً على حافة الشبكة المتداخلة لتفعيل حركة البيانات الواردة إلى أحد التطبيقات. تحدّد VirtualService القواعد التي تتحكّم في كيفية توجيه طلبات الخدمة داخل شبكة خدمات 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، مثل المقاييس والتتبُّع وإدارة الزيارات الديناميكية وعرض الخدمات وتضمين الأخطاء.

الخطوات التالية

الترخيص

يخضع هذا العمل لترخيص المشاع الإبداعي مع نسب العمل إلى مؤلفه 2.0 Generic License.

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