Cloud Service Mesh est un outil puissant de gestion et de surveillance des applications distribuées. Pour tirer le meilleur parti de Cloud Service Mesh, il est utile de comprendre ses abstractions sous-jacentes, y compris les conteneurs et Kubernetes. Ce tutoriel explique comment préparer une application pour Cloud Service Mesh du code source à un conteneur s'exécutant sur GKE, jusqu'au point juste avant d'installer Cloud Service Mesh.
Si vous connaissez déjà les concepts de Kubernetes et du maillage de services, vous pouvez ignorer ce tutoriel et passer directement au guide d'installation de Cloud Service Mesh.
Objectifs
- découvrir une application "Hello World" simple et multiservice ;
- exécuter l'application à partir de la source ;
- conteneuriser l'application ;
- créer un cluster Kubernetes ;
- déployer les conteneurs sur le cluster.
Avant de commencer
Pour activer l'API Cloud Service Mesh, procédez comme suit :- Accédez à la page Kubernetes Engine dans la console Google Cloud.
- Créez ou sélectionnez un projet.
- Patientez le temps de l'activation de l'API et des services associés. Cette opération peut prendre plusieurs minutes.
-
Make sure that billing is enabled for your Google Cloud project.
Ce tutoriel utilise Cloud Shell, qui provisionne une machine virtuelle (VM) g1-small Compute Engine exécutant un système d'exploitation Linux basé sur Debian.
Préparer Cloud Shell
Les avantages liés à l'utilisation de Cloud Shell sont les suivants :
- Les environnements de développement Python 2 et Python 3 (y compris
virtualenv
) sont tous configurés. - Les outils de ligne de commande
gcloud
,docker
,git
etkubectl
utilisés dans ce tutoriel sont déjà installés. Nous vous proposons plusieurs éditeurs de texte :
Éditeur de code, auquel vous accédez en cliquant sur en haut de la fenêtre Cloud Shell.
Emacs, Vim ou Nano, auxquels vous accédez depuis la ligne de commande dans Cloud Shell.
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
Télécharger l'exemple de code
Téléchargez le code source
helloserver
:git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
Accédez au répertoire de l'exemple de code :
cd anthos-service-mesh-samples/docs/helloserver
Explorer l'application multiservice
L'exemple d'application est écrit dans Python et comporte deux composants qui communiquent à l'aide de REST :
server
: un serveur simple avec un point de terminaisonGET
,/
, qui affiche "hello world" dans la console.loadgen
: script qui envoie le trafic versserver
, avec un nombre configurable de requêtes par seconde (RPS).
Exécuter l'application à partir de la source
Pour vous familiariser avec l'exemple d'application, exécutez-le dans Cloud Shell.
À partir du répertoire
sample-apps/helloserver
, exécutez la commandeserver
:python3 server/server.py
Au démarrage,
server
affiche les éléments suivants :INFO:root:Starting server...
Ouvrez une autre fenêtre de terminal pour pouvoir envoyer des requêtes vers
server
. Cliquez sur pour ouvrir une autre session.Envoyez une requête vers
server
:curl http://localhost:8080
Le
server
répond :Hello World!
Dans le répertoire dans lequel vous avez téléchargé l'exemple de code, accédez au répertoire qui contient le fichier
loadgen
:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/loadgen
Créez les variables d'environnement suivantes :
export SERVER_ADDR=http://localhost:8080 export REQUESTS_PER_SECOND=5
Lancez
virtualenv
:virtualenv --python python3 env
Activez l'environnement virtuel :
source env/bin/activate
Installez les éléments requis pour
loadgen
:pip3 install -r requirements.txt
Exécutez la commande
loadgen
:python3 loadgen.py
Au démarrage,
loadgen
génère un message semblable à celui-ci :Starting loadgen: 2019-05-20 10:44:12.448415 5 request(s) complete to http://localhost:8080
Dans l'autre fenêtre de terminal, le
server
écrit des messages dans la console, comme suit :127.0.0.1 - - [21/Jun/2019 14:22:01] "GET / HTTP/1.1" 200 - INFO:root:GET request, Path: / Headers: Host: localhost:8080 User-Agent: python-requests/2.22.0 Accept-Encoding: gzip, deflate Accept: */*
Du point de vue de la mise en réseau, l'ensemble de l'application s'exécute désormais sur le même hôte. De ce fait, vous pouvez utiliser
localhost
pour envoyer des requêtes versserver
.Pour arrêter
loadgen
etserver
, saisissezCtrl-c
dans chaque fenêtre de terminal.Dans la fenêtre de terminal
loadgen
, désactivez l'environnement virtuel :deactivate
Conteneuriser l'application
Pour exécuter l'application sur GKE, vous devez empaqueter l'exemple d'application (server
et loadgen
) dans des conteneurs. Un conteneur permet de regrouper une application de manière à l'isoler de l'environnement sous-jacent.
Pour conteneuriser l'application, vous avez besoin d'un fichier Dockerfile
. Dockerfile
est un fichier texte qui définit les commandes nécessaires pour assembler le code source de l'application et ses dépendances dans un image Docker). Après avoir créé l'image, vous l'importez vers un registre de conteneurs, tel que Docker Hub ou Container Registry.
L'exemple est fourni avec Dockerfile
pour server
et loadgen
avec toutes les commandes requises pour créer les images. Voici le fichier Dockerfile
pour server
:
- La commande
FROM python:3-slim as base
demande à Docker d'utiliser la dernière image Python 3 comme image de base. - La commande
COPY . .
copie les fichiers sources dans le répertoire de travail actuel (dans ce cas, simplementserver.py
) dans le système de fichiers du conteneur. - Le fichier
ENTRYPOINT
définit la commande utilisée pour exécuter le conteneur. Dans ce cas, la commande est presque identique à celle que vous avez utilisée pour exécuterserver.py
à partir du code source. - La commande
EXPOSE
indique queserver
écoute sur le port8080
. Cette commande n'expose aucun port, mais sert de documentation pour ouvrir le port8080
lorsque vous exécutez le conteneur.
Préparation pour la conteneurisation de l'application
Définissez les variables d'environnement suivantes. Remplacez
PROJECT_ID
par l'ID de votre projet Google Cloud.export PROJECT_ID="PROJECT_ID"
export GCR_REPO="asm-ready"
Vous utilisez les valeurs
PROJECT_ID
etGCR_REPO
pour baliser l'image Docker lors de la création, puis la transférer vers votre Container Registry privé.Définissez le projet Google Cloud par défaut pour la Google Cloud CLI.
gcloud config set project $PROJECT_ID
Définissez la zone par défaut pour Google Cloud CLI.
gcloud config set compute/zone us-central1-b
Assurez-vous que le service Container Registry est activé dans votre projet Google Cloud.
gcloud services enable containerregistry.googleapis.com
Conteneurisation de server
Accédez au répertoire dans lequel se trouve l'exemple
server
:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
Créez l'image à l'aide de
Dockerfile
et des variables d'environnement que vous avez définies précédemment :docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1 .
L'option
-t
représente le tag Docker. Il s'agit du nom de l'image que vous utilisez lorsque vous déployez le conteneur.Stockez l'image dans Container Registry :
docker push gcr.io/$PROJECT_ID/$GCR_REPO/helloserver:v0.0.1
Conteneurisation de loadgen
Accédez au répertoire où se trouve l'exemple
loadgen
:cd ../loadgen
Créez l'image comme suit :
docker build -t gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1 .
Stockez l'image dans Container Registry :
docker push gcr.io/$PROJECT_ID/$GCR_REPO/loadgen:v0.0.1
Répertoriage des images
Obtenez la liste des images du dépôt pour confirmer que les images ont été envoyées :
gcloud container images list --repository gcr.io/$PROJECT_ID/asm-ready
La commande répond avec les noms d'image que vous venez de transférer :
NAME gcr.io/PROJECT_ID/asm-ready/helloserver gcr.io/PROJECT_ID/asm-ready/loadgen
Créer un cluster GKE
Vous pouvez exécuter ces conteneurs sur la VM de Cloud Shell à l'aide de la commande docker run
. Cependant, en production, vous devez orchestrer les conteneurs de manière plus unifiée. Par exemple, vous avez besoin d'un système qui s'assure que les conteneurs sont toujours en cours d'exécution, et vous avez besoin d'un moyen pour effectuer un scaling à la hausse et démarrer les instances supplémentaires d'un conteneur pour gérer l'augmentation du trafic.
Vous pouvez utiliser GKE pour exécuter des applications en conteneur. GKE est une plate-forme d'orchestration de conteneurs qui connecte les VM pour former un cluster. Chaque VM est appelée nœud. Les clusters GKE sont basés sur le système de gestion de clusters Open Source Kubernetes. Les mécanismes de Kubernetes vous permettent d'interagir avec votre cluster.
Pour créer un cluster GKE, procédez comme suit :
Créez le cluster :
gcloud container clusters create asm-ready \ --cluster-version latest \ --machine-type=n1-standard-4 \ --num-nodes 4
La commande
gcloud
crée un cluster dans le projet Google Cloud et la zone que vous avez définis précédemment. Pour exécuter Cloud Service Mesh, nous vous recommandons d'utiliser au moins quatre nœuds et le type de machine n1-standard-4.La commande permettant la création d'un cluster prend quelques minutes. Lorsque le cluster est prêt, la commande affiche un message semblable à celui-ci :
NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS asm-ready us-central1-b 1.13.5-gke.10 203.0.113.1 n1-standard-2 1.13.5-gke.10 4 RUNNING
Fournissez les identifiants à l'outil de ligne de commande
kubectl
afin de pouvoir l'utiliser pour gérer le cluster :gcloud container clusters get-credentials asm-ready
Vous pouvez maintenant utiliser
kubectl
pour communiquer avec Kubernetes. Par exemple, vous pouvez exécuter la commande suivante pour obtenir l'état des nœuds :kubectl get nodes
La commande répond avec une liste des nœuds, semblable à la suivante :
NAME STATUS ROLES AGE VERSION gke-asm-ready-default-pool-dbeb23dc-1vg0 Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-36z5 Ready <none> 100s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-fj7s Ready <none> 99s v1.13.6-gke.13 gke-asm-ready-default-pool-dbeb23dc-wbjw Ready <none> 99s v1.13.6-gke.13
Comprendre les concepts clés de Kubernetes
Le schéma suivant illustre l'application s'exécutant sur GKE :
Avant de déployer les conteneurs sur GKE, vous pouvez passer en revue certains concepts clés de Kubernetes. La fin de ce tutoriel fournit des liens vous permettant d'en savoir plus sur chaque concept.
Nœuds et clusters : dans GKE, un nœud est une VM. Sur d'autres plates-formes Kubernetes, un nœud peut être une machine physique ou virtuelle. Un cluster est un ensemble de nœuds pouvant être traités ensemble, comme une seule machine, sur laquelle vous déployez une application conteneurisée.
Pods : dans Kubernetes, les conteneurs s'exécutent dans un pod. Un pod est l'unité atomique de Kubernetes. Un pod contient un ou plusieurs conteneurs. Vous déployez les conteneurs
server
etloadgen
chacun dans leur propre pod. Lorsqu'un pod exécute plusieurs conteneurs (par exemple, un serveur d'applications et un serveur proxy), les conteneurs sont gérés comme une seule entité et partagent les ressources du pod.Déploiements : un déploiement est un objet Kubernetes qui représente un ensemble de pods identiques. Un déploiement exécute plusieurs instances dupliquées des pods répartis entre les nœuds d'un cluster. Un déploiement remplace automatiquement tous les pods qui échouent ou ne répondent pas.
Service Kubernetes : l'exécution du code d'application dans GKE modifie la mise en réseau entre
loadgen
etserver
. Lorsque vous avez exécuté les services dans une VM de Cloud Shell, vous pouviez envoyer des requêtes àserver
à l'aide de l'adresselocalhost:8080
. Une fois le déploiement effectué sur GKE, les pods sont programmés pour s'exécuter sur les nœuds disponibles. Par défaut, vous ne pouvez pas contrôler le nœud sur lequel le pod est en cours d'exécution. Par conséquent, les pods ne disposent pas d'adresses IP stables.Pour obtenir une adresse IP pour
server
, vous devez définir une abstraction de mise en réseau au-dessus des pods appelés service Kubernetes. Un service Kubernetes fournit un point de terminaison de mise en réseau stable pour un ensemble de pods. Il existe plusieurs types de services.server
utiliseLoadBalancer
, qui expose une adresse IP externe afin que vous puissiez accéder àserver
en dehors du cluster.Kubernetes dispose également d'un système DNS intégré qui attribue des noms DNS (par exemple,
helloserver.default.cluster.local
) aux services. Cela permet aux pods du cluster d'atteindre d'autres pods du cluster avec une adresse stable. Vous ne pouvez pas utiliser ce nom DNS en dehors du cluster, par exemple depuis Cloud Shell.
Fichiers manifestes Kubernetes
Lorsque vous avez exécuté l'application à partir du code source, vous avez utilisé une commande impérative : python3 server.py
Impérative, car elle s'appuie sur l'action : "faire cela".
En revanche, Kubernetes fonctionne sur un modèle déclaratif. Cela signifie que, plutôt que de dire exactement à Kubernetes ce qu'il faut faire, vous indiquez à Kubernetes l'état souhaité. Par exemple, Kubernetes démarre et arrête les pods selon les besoins afin que l'état réel du système corresponde à l'état souhaité.
Vous spécifiez l'état souhaité dans un ensemble de fichiers manifestes ou de fichiers YAML. Un fichier YAML contient la spécification pour un ou plusieurs objets Kubernetes.
L'exemple contient un fichier YAML pour server
et loadgen
. Chaque fichier YAML spécifie l'état souhaité pour l'objet et le service de déploiement de Kubernetes.
Serveur
kind
indique le type d'objet.metadata.name
spécifie le nom du déploiement.- Le premier champ
spec
contient une description de l'état souhaité. spec.replicas
spécifie le nombre de pods souhaités.- La section
spec.template
définit un modèle de pod. Dans la spécification pour les pods, le champimage
correspond au nom de l'image à extraire de Container Registry.
Le service est défini comme suit :
LoadBalancer
: les clients envoient des requêtes à l'adresse IP d'un équilibreur de charge réseau, qui possède une adresse IP stable et qui est accessible en dehors du cluster.targetPort
: rappelez-vous que la commandeEXPOSE 8080
deDockerfile
n'expose pas de ports. Exposez le port8080
afin d'atteindre le conteneurserver
en dehors du cluster. Dans ce cas,hellosvc.default.cluster.local:80
(nom abrégé :hellosvc
) correspond au port8080
de l'adresse IP du podhelloserver
).port
: numéro de port utilisé par les autres services du cluster lors de l'envoi de requêtes.
Générateur de charge
L'objet Déploiement dans loadgen.yaml
est semblable à server.yaml
. Une différence notable est que l'objet Déploiement contient une section appelée env
. Cette section définit les variables d'environnement requises par loadgen
, que vous avez définies précédemment lors de l'exécution de l'application à partir de la source.
Étant donné que loadgen
n'accepte pas les requêtes entrantes, le champ type
est défini sur ClusterIP
. Ce type fournit une adresse IP stable que les services du cluster peuvent utiliser, mais qui n'est pas exposée aux clients externes.
Déployer les conteneurs sur GKE
Accédez au répertoire où se trouve l'exemple
server
:cd YOUR_WORKING_DIRECTORY/anthos-service-mesh-samples/docs/helloserver/server/
Ouvrez
server.yaml
dans un éditeur de texte.Remplacez le nom du champ
image
par le nom de votre image Docker.image: gcr.io/PROJECT_ID/asm-ready/helloserver:v0.0.1
Remplacez
PROJECT_ID
par l'ID de votre projet Google Cloud.Enregistrez et fermez le fichier
server.yaml
.Déployez le fichier YAML sur Kubernetes :
kubectl apply -f server.yaml
En cas de réussite, la commande renvoie la réponse suivante :
deployment.apps/helloserver created service/hellosvc created
Accédez au répertoire où se trouve
loadgen
.cd ../loadgen
Ouvrez
loadgen.yaml
dans un éditeur de texte.Remplacez le nom du champ
image
par le nom de votre image Docker.image: gcr.io/PROJECT_ID/asm-ready/loadgen:v0.0.1
Remplacez
PROJECT_ID
par l'ID de votre projet Google Cloud.Enregistrez et fermez
loadgen.yaml
, puis fermez l'éditeur de texte.Déployez le fichier YAML sur Kubernetes :
kubectl apply -f loadgen.yaml
En cas de réussite, la commande renvoie la réponse suivante :
deployment.apps/loadgenerator created service/loadgensvc created
Vérifiez l'état des pods :
kubectl get pods
La commande renvoie un état semblable au suivant :
NAME READY STATUS RESTARTS AGE helloserver-69b9576d96-mwtcj 1/1 Running 0 58s loadgenerator-774dbc46fb-gpbrz 1/1 Running 0 57s
Récupérez les journaux de l'application à partir du pod
loadgen
. RemplacezPOD_ID
par l'identifiant de la sortie précédente.kubectl logs loadgenerator-POD_ID
Récupérez les adresses IP externes de
hellosvc
:kubectl get service
La réponse de la commande est semblable à la suivante :
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hellosvc LoadBalancer 10.81.15.158 192.0.2.1 80:31127/TCP 33m kubernetes ClusterIP 10.81.0.1 <none> 443/TCP 93m loadgensvc ClusterIP 10.81.15.155 <none> 80/TCP 4m52s
Envoyez une requête à
hellosvc
. RemplacezEXTERNAL_IP
par l'adresse IP externe de votrehellosvc
.curl http://EXTERNAL_IP
Prêt pour Cloud Service Mesh
Vous avez maintenant déployé l'application sur GKE. loadgen
peut utiliser le DNS Kubernetes (hellosvc:80
) pour envoyer des requêtes à server
, et vous pouvez envoyer des requêtes à server
avec une adresse IP externe. Bien que Kubernetes vous fournisse de nombreuses fonctionnalités, certaines informations concernant les services sont manquantes :
- Comment les services interagissent-ils ? Quelle est la relation entre les services ? Comment le trafic circule-t-il entre les services ? Vous savez que
loadgen
envoie des requêtes àserver
, mais imaginez que vous ne connaissez pas l'application. Vous ne pouvez pas répondre à ces questions en consultant la liste des pods en cours d'exécution sur GKE. - Statistiques : combien de temps faut-il pour que
server
réponde aux requêtes entrantes ? Combien de requêtes par seconde (RPS) sont entrantes versserver
? Existe-t-il des réponses d'erreur ? - Informations de sécurité: le trafic est-il compris entre
loadgen
et leserver
brutHTTP
ou mTLS ?
Cloud Service Mesh peut répondre à ces questions. Cloud Service Mesh est une version gérée par Google Cloud du projet Istio Open Source. Cloud Service Mesh fonctionne en plaçant un proxy side-car Envoy dans chaque pod. Le proxy Envoy intercepte tout le trafic entrant et sortant vers les conteneurs d'applications. Cela signifie que server
et loadgen
disposent chacune d'un proxy side-car Envoy, et tout le trafic de loadgen
vers server
est diffusé par les proxys Envoy. Les connexions entre ces proxys Envoy forment le maillage de services. Cette architecture de maillage de services fournit une couche de contrôle en plus de Kubernetes.
Étant donné que les proxys Envoy s'exécutent dans leurs propres conteneurs, vous pouvez installer Cloud Service Mesh sur un cluster GKE sans apporter de modifications importantes à votre code d'application. Cependant, il existe plusieurs moyens clés avec lesquels vous avez préparé l'application pour être instrumentée avec Cloud Service Mesh:
- Services pour tous les conteneurs : les déploiements
server
etloadgen
sont associés à un service Kubernetes. Mêmeloadgen
, qui ne reçoit aucune requête entrante, dispose d'un service. - Les ports des services doivent être nommés: bien que GKE vous permette de définir des ports de service sans nom, Cloud Service Mesh vous demande de fournir un nom pour un port correspondant au protocole du port. Dans le fichier YAML, le port pour
server
est nomméhttp
, carserver
utilise le protocole de communicationHTTP
. Siservice
utilisegRPC
, vous devez nommer le portgrpc
. - Les déploiements sont libellés: cela vous permet d'utiliser les fonctionnalités de gestion du trafic de Cloud Service Mesh, telles que la division du trafic entre les différentes versions du même service.
Installer Cloud Service Mesh
Consultez le guide d'installation de Cloud Service Mesh et suivez les instructions pour installer Cloud Service Mesh sur votre cluster.
Effectuer un nettoyage
Pour éviter que les ressources utilisées lors de ce tutoriel soient facturées sur votre compte Google Cloud, supprimez le projet contenant les ressources, ou conservez le projet et les ressources individuelles.
Pour le nettoyage, supprimez le cluster GKE. La suppression du cluster supprime toutes les ressources qui constituent le cluster de conteneurs, telles que les instances de calcul, les disques et les ressources réseau.
gcloud container clusters delete asm-ready
Étape suivante
En savoir plus sur les technologies utilisées dans ce tutoriel :
En savoir plus sur les outils :
En savoir plus les concepts Kubernetes :