Déployer une application ASP.NET Core sur Google Kubernetes Engine avec Istio (Partie 1)

1. Présentation

ASP.NET Core est un nouveau framework Open Source et multiplate-forme qui permet de créer des applications innovantes basées sur le cloud et connectées à Internet, à l'aide du langage de programmation C#.

Kubernetes est un système Open Source qui automatise le déploiement, le scaling et la gestion des applications conteneurisées. Istio est un framework Open Source permettant de connecter, sécuriser, gérer et surveiller des services.

Dans cette première partie de l'atelier, vous allez déployer une application ASP.NET Core simple sur Kubernetes, qui s'exécute sur Google Kubernetes Engine (GKE), et la configurer pour qu'elle soit gérée par Istio.

Dans la deuxième partie de l'atelier, vous explorerez plus en détail les fonctionnalités d'Istio, telles que les métriques, le traçage, la gestion dynamique du trafic, l'injection de pannes et plus encore.

Points abordés

  • Créer et empaqueter une application ASP.NET Core simple dans un conteneur Docker
  • Créer un cluster Kubernetes avec Google Kubernetes Engine (GKE)
  • Découvrez comment installer Istio sur un cluster Kubernetes sur GKE.
  • Déployer une application ASP.NET Core et configurer son trafic pour qu'il soit géré par Istio

Prérequis

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Quel est votre niveau d'expérience avec Google Cloud Platform ?

Débutant Intermédiaire Expert

2. Préparation

Configuration de l'environnement au rythme de chacun

  1. Connectez-vous à la console Cloud, puis créez un projet ou réutilisez un projet existant. (Si vous ne possédez pas encore de compte Gmail ou Google Workspace, vous devez en créer un.)

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Mémorisez l'ID du projet. Il s'agit d'un nom unique permettant de différencier chaque projet Google Cloud (le nom ci-dessus est déjà pris ; vous devez en trouver un autre). Il sera désigné par le nom PROJECT_ID tout au long de cet atelier de programmation.

  1. Vous devez ensuite activer la facturation dans Cloud Console pour pouvoir utiliser les ressources Google Cloud.

L'exécution de cet atelier de programmation est très peu coûteuse, voire sans frais. Veillez à suivre les instructions de la section "Nettoyer" qui indique comment désactiver les ressources afin d'éviter les frais une fois ce tutoriel terminé. Les nouveaux utilisateurs de Google Cloud peuvent participer au programme d'essai sans frais pour bénéficier d'un crédit de 300$.

Démarrer Cloud Shell

Bien que Google Cloud puisse être utilisé à distance depuis votre ordinateur portable, nous allons nous servir de Google Cloud Shell pour cet atelier de programmation, un environnement de ligne de commande exécuté dans Google Cloud.

Activer Cloud Shell

  1. Dans Cloud Console, cliquez sur Activer Cloud Shell 4292cbf4971c9786.png.

bce75f34b2c53987.png

Si vous n'avez jamais démarré Cloud Shell auparavant, un écran intermédiaire s'affiche en dessous de la ligne de flottaison, décrivant de quoi il s'agit. Si tel est le cas, cliquez sur Continuer. Cet écran ne s'affiche qu'une seule fois. Voici à quoi il ressemble :

70f315d7b402b476.png

Le provisionnement et la connexion à Cloud Shell ne devraient pas prendre plus de quelques minutes.

fbe3a0674c982259.png

Cette machine virtuelle contient tous les outils de développement dont vous avez besoin. Elle comprend un répertoire d'accueil persistant de 5 Go et s'exécute sur Google Cloud, ce qui améliore nettement les performances du réseau et l'authentification. Vous pouvez réaliser une grande partie, voire la totalité, des activités de cet atelier dans un simple navigateur ou sur votre Chromebook.

Une fois connecté à Cloud Shell, vous êtes en principe authentifié et le projet est défini avec votre ID de projet.

  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que vous êtes authentifié :
gcloud auth list

Résultat de la commande

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Exécutez la commande suivante dans Cloud Shell pour vérifier que la commande gcloud connaît votre projet :
gcloud config list project

Résultat de la commande

[core]
project = <PROJECT_ID>

Si vous obtenez un résultat différent, exécutez cette commande :

gcloud config set project <PROJECT_ID>

Résultat de la commande

Updated property [core/project].

3. Créer une application ASP.NET Core dans Cloud Shell

Dans l'invite Cloud Shell, vous pouvez vérifier que l'outil de ligne de commande dotnet est déjà installé en vérifiant sa version. La version de l'outil de ligne de commande dotnet installé devrait s'afficher :

dotnet --version

Ensuite, créez le squelette d'une application Web ASP.NET Core.

dotnet new mvc -o HelloWorldAspNetCore

Cette action créera un projet et restaurera ses dépendances. Un message de ce type doit s'afficher :

Restore completed in 11.44 sec for HelloWorldAspNetCore.csproj.

Restore succeeded.

4. Exécuter l'application ASP.NET Core

Nous allons bientôt pouvoir exécuter l'application. Accédez au dossier de l'application.

cd HelloWorldAspNetCore

Enfin, exécutez l'application.

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

L'application commence à écouter sur le port 8080.

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

Pour vérifier que l'application est bien en cours d'exécution, cliquez sur le bouton "Aperçu sur le Web" en haut à droite, puis sélectionnez "Prévisualiser sur le port 8080".

Capture.PNG

La page Web ASP.NET Core par défaut s'affiche :

f579a9baedc108a9.png

Une fois que vous avez vérifié que l'application est en cours d'exécution, appuyez sur Ctrl+C pour l'arrêter.

5. Empaqueter l'application ASP.NET Core dans un conteneur Docker

Préparez ensuite votre application à s'exécuter en tant que conteneur. La première étape consiste à définir le conteneur et son contenu.

Dans le répertoire de base de l'application, créez un fichier Dockerfile pour définir l'image Docker.

touch Dockerfile

À l'aide de l'éditeur de votre choix (vim,, nano,emacs ou l'éditeur de code Cloud Shell), ajoutez ce qui suit à Dockerfile.

# 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"]

Une des configurations importantes du fichier Dockerfile est le port 8080 sur lequel l'application écoute le trafic entrant. Pour ce faire, vous devez définir la variable d'environnement ASPNETCORE_URLS, qui permet aux applications ASP.NET Core de déterminer le port d'écoute.

Enregistrez ce Dockerfile. À présent, créons l'image :

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

Une fois cette opération terminée (le téléchargement et l'extraction de tous les éléments peuvent prendre un peu de temps), vous pouvez voir que l'image est créée et enregistrée localement :

docker images

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

Testez l'image en local avec la commande suivante, qui exécutera un conteneur Docker en local sur le port 8080 à partir de l'image de conteneur que vous venez de créer :

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

Exploitez une fois de plus la fonctionnalité d'aperçu sur le Web de Cloud Shell :

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

La page Web ASP.NET Core par défaut devrait s'afficher dans un nouvel onglet.

f579a9baedc108a9.png

Une fois que vous avez vérifié que l'application s'exécute correctement en local dans un conteneur Docker, vous pouvez arrêter le conteneur en cours d'exécution en saisissant Ctrl-> C.

Maintenant que l'image fonctionne comme prévu, transférez-la vers Google Container Registry, un dépôt privé pour vos images Docker accessible depuis tous les projets Google Cloud (mais également en dehors de Google Cloud Platform).

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

Si tout se passe bien, vous devriez voir l'image de conteneur listée dans la section Container Registry au bout de quelques instants. Vous disposez maintenant d'une image Docker pour l'ensemble du projet. Comme vous le verrez dans quelques minutes, vous pouvez accéder à cette image et l'orchestrer grâce à Kubernetes.

73558f3a54ce1c0c.png

Si vous êtes curieux, vous pouvez parcourir les images de conteneurs stockées dans Google Cloud Storage en cliquant sur ce lien : https://console.cloud.google.com/storage/browser/ (le lien généré doit se présenter sous la forme suivante : https://console.cloud.google.com/project/PROJECT_ID/storage/browser/).

6. Créer un cluster Kubernetes/GKE avec Istio

Commencez par vous assurer que l'API Kubernetes Engine est activée :

gcloud services enable container.googleapis.com

Créez un cluster Kubernetes. Si vous le souhaitez, vous pouvez modifier la région pour en choisir une proche de vous :

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

Attendez quelques instants pendant que le système configure votre cluster. Il sera visible dans la section "Kubernetes Engine" de la console Google Cloud Platform.

e46fd9c6ee82bcc4.png

Pour cet atelier de programmation, nous allons télécharger et installer Istio depuis istio.io. Il existe d'autres options d'installation, y compris le module complémentaire Istio pour GKE et Anthos Service Mesh. Les étapes suivantes de l'application fonctionneront sur n'importe quelle installation Istio.

Commençons par télécharger le client et les exemples Istio. La page des versions d'Istio propose de télécharger des artefacts pour plusieurs systèmes d'exploitation. Dans notre cas, nous pouvons utiliser une commande pratique pour télécharger et extraire la dernière version pour notre plate-forme actuelle :

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

Le script vous indiquera la version d'Istio qui a été téléchargée :

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

Le répertoire d'installation contient des exemples d'applications et le binaire client istioctl. Accédez à ce répertoire :

cd istio-1.8.1

Copiez et collez la commande fournie pour ajouter le répertoire bin à votre PATH afin de pouvoir utiliser istioctl :

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

Vérifiez que istioctl est disponible en vous assurant que votre cluster est prêt pour Istio :

istioctl x precheck

Le message Install Pre-Check passed! The cluster is ready for Istio installation. devrait s'afficher.

Installez Istio avec le profil de démonstration :

istioctl install --set profile=demo

Istio est maintenant installé dans votre cluster.

Injection automatique de side-car

Pour commencer à utiliser Istio, vous n'avez pas besoin de modifier l'application. Lorsque vous configurez et exécutez les services, les sidecars Envoy sont automatiquement injectés dans chaque pod du service.

Pour que cela fonctionne, vous devez activer l'injection side-car pour l'espace de noms ("default") que vous utilisez pour vos microservices. Pour ce faire, appliquez un libellé :

kubectl label namespace default istio-injection=enabled

Pour vérifier que le libellé a bien été appliqué, exécutez la commande suivante :

kubectl get namespace -L istio-injection

Le résultat confirme que l'injection side-car est activée pour l'espace de noms par défaut :

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

7. Vérifiez l'installation

Istio est fourni avec trois services : le plan de contrôle istiod, ainsi que les passerelles d'entrée et de sortie (que vous pouvez considérer comme des "proxies side-car pour le reste d'Internet") , nommées respectivement istio-ingressgateway et istio-egressgateway.

kubectl get svc -n istio-system

Vous devez normalement obtenir le résultat suivant :

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>

La passerelle d'entrée est de type LoadBalancer et est donc accessible depuis Internet. Les autres n'ont besoin d'être accessibles que depuis le cluster.

Ensuite, assurez-vous que les pods Kubernetes correspondants sont déployés et que tous les conteneurs sont opérationnels et en cours d'exécution :

kubectl get pods -n istio-system

Lorsque tous les pods sont en cours d'exécution, vous pouvez continuer.

NAME                                    READY   STATUS
istio-egressgateway-674988f895-m6tk4    1/1     Running
istio-ingressgateway-6996f7dcc8-7lvm2   1/1     Running
istiod-6bf5fc8b64-j79hj                 1/1     Running
  • istiod : plan de contrôle Istio. Gère la configuration et la programmation des proxys side-car, la découverte des services, la distribution des certificats et l'injection de side-car
  • ingress gateway : gère les requêtes entrantes provenant de l'extérieur de votre cluster.
  • egress gateway : gère les requêtes sortantes vers des points de terminaison en dehors de votre cluster.

8. Déployer l'application

Maintenant que vous avez vérifié qu'Istio est installé et en cours d'exécution, vous pouvez déployer l'application ASP.NET Core.

Déploiement et service

Commencez par créer un fichier aspnetcore.yaml à l'aide de votre éditeur favori (vim, nano,emacs ou l'éditeur de code Cloud Shell) et définissez le déploiement et le service Kubernetes pour l'application :

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

Le contenu du fichier est constitué de déploiements et de services standards pour déployer l'application. Il ne contient rien de spécifique à Istio.

Déployez les services dans l'espace de noms par défaut avec kubectl :

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

Vérifiez que les pods sont en cours d'exécution :

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

Passerelle et VirtualService

Pour autoriser le trafic entrant à accéder au maillage, vous devez créer une passerelle et un VirtualService.

Une passerelle configure un équilibreur de charge pour le trafic HTTP/TCP, qui fonctionne le plus souvent à la périphérie du maillage pour activer le trafic entrant d'une application. Un VirtualService définit les règles qui contrôlent la manière dont les requêtes pour un service sont acheminées au sein d'un maillage de services Istio.

Créez un fichier aspnetcore-gateway.yaml pour définir la passerelle :

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:
    - "*"

Créez un fichier aspnetcore-virtualservice.yaml pour définir le VirtualService :

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

Exécutez la commande kubectl pour déployer la passerelle :

kubectl apply -f aspnetcore-gateway.yaml

La commande produit le résultat suivant :

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

Exécutez ensuite la commande suivante pour déployer le VirtualService :

kubectl apply -f aspnetcore-virtualservice.yaml

La commande produit le résultat suivant :

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

Vérifiez que tout fonctionne :

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

Félicitations ! Vous venez de déployer une application compatible avec Istio. Vous verrez ensuite l'application en cours d'utilisation.

9. Tester l'application

Vous pouvez enfin voir l'application en action. Vous devez obtenir l'adresse IP externe et le port de la passerelle. Il est répertorié sous EXTERNAL-IP :

kubectl get svc istio-ingressgateway -n istio-system

Exportez l'adresse IP externe et le port vers une variable 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

Utilisez curl pour tester l'application. Le service doit répondre avec un code de réponse 200 :

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

Vous pouvez également ouvrir le navigateur et accéder à http://<gatewayurl> pour afficher l'application :

f579a9baedc108a9.png

10. Félicitations !

Vous venez de déployer une application ASP.NET Core simple sur Kubernetes, qui s'exécute sur Google Kubernetes Engine (GKE), et de la configurer pour qu'elle soit gérée par Istio.

Vous vous demandez peut-être quels sont les avantages d'Istio. C'est une excellente question. Jusqu'à présent, il n'y a aucun avantage à ce qu'Istio gère cette application. Dans la deuxième partie de l'atelier, nous explorerons plus en détail les fonctionnalités d'Istio, telles que les métriques, le traçage, la gestion dynamique du trafic, la visualisation des services et l'injection de pannes.

Étapes suivantes

Licence

Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.

11. Nettoyage

Si vous ne passez pas à la deuxième partie de l'atelier, vous pouvez supprimer l'application et désinstaller Istio, ou simplement supprimer le cluster Kubernetes.

Supprimer l'application

Pour supprimer l'application, procédez comme suit :

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

Pour vérifier que l'application a bien été supprimée :

kubectl get gateway 
kubectl get virtualservices 
kubectl get pods

Désinstaller Istio

Pour supprimer Istio :

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

Pour vérifier qu'Istio a bien été supprimé :

kubectl get pods -n istio-system

Supprimer un cluster Kubernetes

gcloud container clusters delete hello-istio