Présentation des conteneurs


Si vous ne connaissez pas du tout les charges de travail conteneurisées, ce tutoriel est fait pour vous. Il vous présente les conteneurs et l'orchestration de conteneurs en vous expliquant comment configurer une application simple à partir du code source vers un conteneur exécuté sur GKE.

Ce tutoriel ne nécessite aucune expérience préalable avec les conteneurs ni avec Kubernetes. Toutefois, si vous souhaitez consulter une présentation de la terminologie de base de Kubernetes avant de commencer ce tutoriel, consultez Commencer à découvrir Kubernetes (ou si vous préférez découvrir Kubernetes sous forme de bande dessinée, consultez notre bande dessinée sur Kubernetes). Vous trouverez des ressources plus détaillées dans la section Et maintenant ? à la fin du tutoriel.

Si vous connaissez déjà les conteneurs et Kubernetes, vous pouvez ignorer ce tutoriel et commencer à découvrir GKE.

Objectifs

  1. découvrir une application "Hello World" simple et multiservice ;
  2. Exécutez l'application à partir de la source.
  3. conteneuriser l'application ;
  4. créer un cluster Kubernetes ;
  5. déployer les conteneurs sur le cluster.

Avant de commencer

Pour activer l'API Kubernetes Engine, procédez comme suit :
  1. Accédez à la page Kubernetes Engine dans la console Google Cloud .
  2. Créez ou sélectionnez un projet.
  3. Patientez le temps de l'activation de l'API et des services associés. Cette opération peut prendre plusieurs minutes.
  4. Make sure that billing is enabled for your Google Cloud project.

Préparer Cloud Shell

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.

L'utilisation de Cloud Shell présente les avantages suivants:

  • Un environnement de développement Python 3 (y compris virtualenv) est entièrement configuré.
  • Les outils de ligne de commande gcloud, docker, git et kubectl utilisés dans ce tutoriel sont déjà installés.
  • Vous pouvez choisir parmi plusieurs éditeurs de texte intégrés:

    • Éditeur Cloud Shell, auquel vous accédez en cliquant sur Ouvrir l'éditeur 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.

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

  1. Téléchargez le code source helloserver :

    git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
    
  2. Accédez au répertoire de l'exemple de code :

    cd anthos-service-mesh-samples/docs/helloserver
    

Explorer l'application multiservice

L'application exemple est écrite en Python. Elle comporte les composants suivants qui communiquent à l'aide de REST:

  • server: serveur de base avec un point de terminaison GET, / , qui affiche "hello world" dans la fenêtre du terminal.
  • loadgen : script qui envoie le trafic vers server, avec un nombre configurable de requêtes par seconde (RPS).

Exemple d'application

Exécuter l'application à partir de la source

Pour vous familiariser avec l'exemple d'application, exécutez-le dans Cloud Shell:

  1. Dans le répertoire sample-apps/helloserver, exécutez server:

    python3 server/server.py
    

    Au démarrage, server affiche les éléments suivants :

    INFO:root:Starting server...
    
  2. Ouvrez une autre fenêtre de terminal pour pouvoir envoyer des requêtes vers server. Pour ce faire dans Cloud Shell, cliquez sur Ouvrir un nouvel onglet pour ouvrir une autre session.

  3. Dans la nouvelle fenêtre de terminal, envoyez une requête à server:

    curl http://localhost:8080
    

    Le résultat de server est le suivant:

    Hello World!
    
  4. Dans le même onglet, accédez au répertoire contenant le script loadgen:

    cd anthos-service-mesh-samples/docs/helloserver/loadgen
  5. Créez les variables d'environnement suivantes :

    export SERVER_ADDR=http://localhost:8080
    export REQUESTS_PER_SECOND=5
    
  6. Lancez virtualenv :

    virtualenv --python python3 env
    
  7. Activez l'environnement virtuel :

    source env/bin/activate
    
  8. Installez les éléments requis pour loadgen :

    pip3 install -r requirements.txt
    
  9. Exécutez l'application loadgen pour générer du trafic pour le server:

    python3 loadgen.py
    

    Au démarrage, la sortie de loadgen ressemble à ce qui suit:

    Starting loadgen: 2024-10-11 09:49:51.798028
    5 request(s) complete to http://localhost:8080
    
  10. Ouvrez maintenant la fenêtre de terminal qui exécute server. Des messages semblables aux suivants doivent s'afficher:

    127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
    INFO:root:GET request,
    Path: /
    Headers:
    Host: localhost:8080
    User-Agent: python-requests/2.32.3
    Accept-Encoding: gzip, deflate
    Accept: */*
    Connection: keep-alive
    

    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, ce qui vous permet d'utiliser localhost pour envoyer des requêtes à server.

  11. Pour arrêter loadgen et server, appuyez sur Ctrl-c dans chaque fenêtre de terminal.

  12. 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 les deux composants de l'application exemple dans des conteneurs. Un conteneur est un package qui contient tous les éléments nécessaires pour que votre application s'exécute dans n'importe quel environnement. Ce tutoriel utilise Docker pour conteneuriser l'application.

Pour conteneuriser l'application avec Docker, 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 une image de conteneur. Après avoir créé l'image, vous l'importez vers un registre de conteneurs, tel que Artifact Registry.

Le code source de ce tutoriel inclut un Dockerfile pour server et loadgen avec toutes les commandes requises pour créer les images. Voici le fichier Dockerfile pour server:

FROM python:3.13-slim as base
FROM base as builder
RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        g++ \
    && rm -rf /var/lib/apt/lists/*

# Enable unbuffered logging
FROM base as final
ENV PYTHONUNBUFFERED=1

RUN apt-get -qq update \
    && apt-get install -y --no-install-recommends \
        wget

WORKDIR /helloserver

# Grab packages from builder
COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/

# Add the application
COPY . .

EXPOSE 8080
ENTRYPOINT [ "python", "server.py" ]

Dans ce fichier, vous pouvez voir les éléments suivants:

  • L'instruction FROM python:3-slim as base demande à Docker d'utiliser la dernière image Python 3 comme image de base.
  • L'instruction COPY . . copie les fichiers sources du répertoire de travail actuel (dans ce cas, server.py) dans le système de fichiers du conteneur.
  • Le fichier ENTRYPOINT définit l'instruction utilisée pour exécuter le conteneur. Dans cet exemple, l'instruction est semblable à celle que vous avez utilisée pour exécuter server.py à partir du code source.
  • L'instruction EXPOSE indique que server écoute sur le port 8080. Cette instruction n'expose aucun port, mais sert de documentation pour ouvrir le port 8080 lorsque vous exécutez le conteneur.

Préparer l'application en conteneur

Avant de conteneuriser l'application, vous devez configurer les outils et les services que vous allez utiliser:

  1. Définissez le projet Google Cloud par défaut pour la Google Cloud CLI.

    gcloud config set project PROJECT_ID
  2. Définissez la région par défaut pour Google Cloud CLI.

    gcloud config set compute/region us-central1
    

Créer le dépôt

Pour créer un dépôt d'images de conteneurs Docker dans Artifact Registry, procédez comme suit:

  1. Assurez-vous que le service Artifact Registry est activé dans votre projetGoogle Cloud .

    gcloud services enable artifactregistry.googleapis.com
    
    
  2. Créez le dépôt Artifact Registry :

    gcloud artifacts repositories create container-intro --repository-format=docker \
        --location=us-central1 \
        --description="My new Docker repository" 
    
  3. Configurez l'authentification de Docker vers Artifact Registry à l'aide de la Google Cloud CLI:

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

Conteneurisation de server

Il est maintenant temps de conteneuriser votre application. Commencez par conteneuriser le server "hello world" et transférez l'image vers Artifact Registry:

  1. Accédez au répertoire où se trouve l'exemple server :

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Créez l'image à l'aide de Dockerfile:

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
    
    • Remplacez PROJECT_ID par l'ID de votre Google Cloud projet.

    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.

  3. Transférez l'image vers Artifact Registry :

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

Conteneurisation de loadgen

Ensuite, conteneurisez le service de générateur de charge de la même manière:

  1. Accédez au répertoire où se trouve l'exemple loadgen :

    cd ../loadgen
    
  2. Créez l'image comme suit :

    docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
    
  3. Transférez l'image vers Artifact Registry :

    docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/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 us-central1-docker.pkg.dev/PROJECT_ID/container-intro

La sortie doit lister les noms des images que vous avez transférées, comme suit:

NAME
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen

Créer un cluster GKE

À ce stade, vous pouvez simplement exécuter les conteneurs sur la VM Cloud Shell à l'aide de la commande docker run. Toutefois, pour exécuter des charges de travail de production fiables, vous devez gérer les conteneurs de manière plus unifiée. Par exemple, vous devez vous assurer que les conteneurs redémarrent en cas d'échec, et vous avez besoin d'un moyen d'effectuer un scaling à la hausse et de démarrer les instances supplémentaires d'un conteneur pour gérer l'augmentation du trafic.

GKE peut vous aider à répondre à ces besoins. 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 exécuter les conteneurs sur GKE, vous devez d'abord créer un cluster, puis vous y connecter:

  1. Créez le cluster :

    gcloud container clusters create-auto container-intro
    

    La commande gcloud crée un cluster dans le projet et la région par défaut Google Cloud que vous avez définis précédemment.

    La commande permettant la création d'un cluster prend quelques minutes. Lorsque le cluster est prêt, le résultat ressemble à ce qui suit:

     NAME: container-intro
     LOCATION: us-central1
     MASTER_VERSION: 1.30.4-gke.1348000
     MASTER_IP: 34.44.14.166
     MACHINE_TYPE: e2-small
     NODE_VERSION: 1.30.4-gke.1348000
     NUM_NODES: 3
     STATUS: RUNNING
    
  2. 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 container-intro
    

Examiner les 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 fichier appelé "fichier manifeste". Les fichiers manifestes sont écrits dans des langages tels que YAML ou JSON, et contiennent la spécification d'un ou de plusieurs objets Kubernetes.

L'exemple contient un fichier manifeste pour server et loadgen. Chaque fichier manifeste spécifie l'état souhaité pour l'objet de déploiement Kubernetes (qui gère l'exécution de votre conteneur, empaqueté pour la gestion en tant que pod Kubernetes) et le service (qui fournit une adresse IP pour le pod). Un pod est la plus petite unité de calcul déployable que vous pouvez créer et gérer dans Kubernetes. Il contient un ou plusieurs conteneurs.

Le schéma suivant illustre l'application s'exécutant sur GKE :

Application conteneurisée exécutée sur GKE

Pour en savoir plus sur les pods, les déploiements et les services, consultez Commencer à découvrir Kubernetes ou les ressources disponibles à la fin de cette page.

Serveur

Commencez par examiner le fichier manifeste de l'server "Hello World" :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloserver
  template:
    metadata:
      labels:
        app: helloserver
    spec:
      containers:
      - image: gcr.io/google-samples/istio/helloserver:v0.0.1
        imagePullPolicy: Always
        name: main
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

Ce fichier manifeste contient les champs suivants:

  • 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 champ image correspond au nom de l'image à extraire d'Artifact Registry. À l'étape suivante, vous allez remplacer cette valeur par la nouvelle image que vous venez de créer.

Le service hellosvc est défini comme suit:

apiVersion: v1
kind: Service
metadata:
  name: hellosvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: helloserver
  type: LoadBalancer
  • 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 commande EXPOSE 8080 de Dockerfile n'expose pas de ports. Exposez le port 8080 afin d'atteindre le conteneur server en dehors du cluster. Dans ce cas, hellosvc.default.cluster.local:80 (nom abrégé : hellosvc ) correspond au port 8080 de l'adresse IP du pod helloserver).
  • 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 la spécification de pod du déploiement loadgen comporte un champ appelé 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.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: loadgenerator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: loadgenerator
  template:
    metadata:
      labels:
        app: loadgenerator
    spec:
      containers:
      - env:
        - name: SERVER_ADDR
          value: http://hellosvc:80/
        - name: REQUESTS_PER_SECOND
          value: '10'
        image: gcr.io/google-samples/istio/loadgen:v0.0.1
        imagePullPolicy: Always
        name: main
        resources:
          limits:
            cpu: 500m
            memory: 512Mi
          requests:
            cpu: 300m
            memory: 256Mi
      restartPolicy: Always
      terminationGracePeriodSeconds: 5

Étant donné que loadgen n'accepte pas les requêtes entrantes, le champ type est défini sur ClusterIP. Ce type de service fournit une adresse IP stable que les entités du cluster peuvent utiliser, mais qui n'est pas exposée aux clients externes.

apiVersion: v1
kind: Service
metadata:
  name: loadgensvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: loadgenerator
  type: ClusterIP

Déployer les conteneurs sur GKE

Pour déployer les conteneurs, vous appliquez les fichiers manifestes qui spécifient l'état souhaité à l'aide de kubectl.

Déployer server

  1. Accédez au répertoire où se trouve l'exemple server :

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Ouvrez server.yaml dans l'éditeur Cloud Shell (ou dans l'éditeur de texte de votre choix).

  3. Remplacez le nom du champ image par le nom de votre image Docker.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
    

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud .

    • Si vous utilisez l'éditeur Cloud Shell, le fichier est automatiquement enregistré. Revenez à la fenêtre de terminal en cliquant sur Ouvrir le terminal.
    • Si vous utilisez un éditeur de texte dans Cloud Shell, enregistrez et fermez server.yaml.
  4. Déployez le fichier manifeste sur Kubernetes:

    kubectl apply -f server.yaml
    

    Le résultat ressemble à ce qui suit :

    deployment.apps/helloserver created
    service/hellosvc created
    

Déployer loadgen

  1. Accédez au répertoire où se trouve loadgen.

    cd ../loadgen
    
  2. Ouvrez loadgen.yaml dans un éditeur de texte, comme précédemment.

  3. Remplacez à nouveau le nom du champ image par le nom de votre image Docker.

    image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
    

    Remplacez PROJECT_ID par l'ID de votre projet Google Cloud .

    • Si vous utilisez l'éditeur Cloud Shell, le fichier est automatiquement enregistré. Revenez à la fenêtre de terminal en cliquant sur Ouvrir le terminal.
    • Si vous utilisez un éditeur de texte dans Cloud Shell, enregistrez et fermez loadgen.yaml.
  4. Déployez le fichier manifeste sur votre cluster:

    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érifier votre déploiement

Après avoir déployé vos fichiers manifestes sur le cluster, vérifiez que vos conteneurs ont bien été déployés:

  1. Vérifiez l'état des pods de votre cluster:

    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
    
  2. Récupérez les journaux de l'application à partir du pod loadgen. Remplacez POD_ID par l'identifiant du pod du générateur de charge de la sortie précédente.

    kubectl logs POD_ID
    
  3. Récupérez les adresses IP externes de hellosvc :

    kubectl get service hellosvc
    

    Le résultat ressemble à ce qui suit :

    NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
    hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
    
  4. Envoyez une requête à hellosvc. Remplacez EXTERNAL_IP par l'adresse IP externe de votre hellosvc.

    curl http://EXTERNAL_IP
    

    Un message "Hello World!" doit s'afficher sur le serveur.

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 supprimez les ressources individuelles.

Si vous ne souhaitez pas supprimer l'intégralité du projet:

  • Supprimez le cluster GKE. La suppression du cluster supprime toutes les ressources qui le constituent, telles que les instances Compute Engine, les disques et les ressources réseau.

     gcloud container clusters delete container-intro
    
  • Supprimez le dépôt Artifact Registry :

     gcloud artifacts repositories delete container-intro --location=us-central1
    

Étape suivante