Guide de démarrage rapide : déployer une application dans une image de conteneur sur un cluster GKE


Cette page vous explique comment :

  1. Créer une application Hello World
  2. Empaqueter l'application dans une image de conteneur à l'aide de Cloud Build
  3. Créer un cluster dans Google Kubernetes Engine (GKE)
  4. Déployer l'image de conteneur sur votre cluster.

L'exemple est proposé dans plusieurs langages, mais vous pouvez en utiliser d'autres en plus de ceux présentés.


Pour obtenir des instructions détaillées sur cette tâche directement dans l'éditeur Cloud Shell, cliquez sur Visite guidée :

Visite guidée


Avant de commencer

  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Activer les API Artifact Registry, Cloud Build, and Google Kubernetes Engine.

    Activer les API

  5. Installez Google Cloud CLI.
  6. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  7. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  8. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  9. Activer les API Artifact Registry, Cloud Build, and Google Kubernetes Engine.

    Activer les API

  10. Installez Google Cloud CLI.
  11. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  12. kubectl permet de gérer Kubernetes, le système d'orchestration de clusters utilisé par GKE. Vous pouvez installer kubectl à l'aide de gcloud :
    gcloud components install kubectl

Écrire l'exemple d'application

Pour obtenir des instructions sur la création d'une application Hello World exécutée dans GKE, cliquez sur votre langage :

Go

  1. Créez un répertoire nommé helloworld-gke et modifiez les sous-répertoires comme suit :

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Créez un module nommé example.com/helloworld :

    go mod init example.com/helloworld
    
  3. Créez un fichier nommé helloworld.go et collez-y le code suivant :

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	http.HandleFunc("/", handler)
    
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    
    	log.Printf("Listening on localhost:%s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
    	log.Print("Hello world received a request.")
    	target := os.Getenv("TARGET")
    	if target == "" {
    		target = "World"
    	}
    	fmt.Fprintf(w, "Hello %s!\n", target)
    }
    

    Ce code crée un serveur Web qui écoute le port défini par la variable d'environnement PORT.

Votre application est terminée et prête à être empaquetée dans un conteneur Docker, puis importée dans Artifact Registry.

Node.js

  1. Créez un répertoire nommé helloworld-gke et accédez à ce répertoire :

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Créez un fichier package.json avec le contenu suivant :

    {
      "name": "gke-helloworld",
      "version": "1.0.0",
      "description": "GKE hello world sample in Node",
      "main": "index.js",
      "scripts": {
        "start": "node index.js"
      },
      "author": "",
      "license": "Apache-2.0",
      "dependencies": {
        "express": "^4.16.4"
      }
    }
    
  3. Dans le même répertoire, créez un fichier index.js, puis copiez les lignes suivantes dans ce fichier :

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      console.log('Hello world received a request.');
    
      const target = process.env.TARGET || 'World';
      res.send(`Hello ${target}!`);
    });
    
    const port = process.env.PORT || 8080;
    app.listen(port, () => {
      console.log('Hello world listening on port', port);
    });

    Ce code crée un serveur Web qui écoute le port défini par la variable d'environnement PORT.

Votre application est terminée et prête à être empaquetée dans un conteneur Docker, puis importée dans Artifact Registry.

Python

  1. Créez un répertoire nommé helloworld-gke et accédez à ce répertoire :

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Créez un fichier nommé app.py et collez le code suivant dans ce fichier :

    import os
    
    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    def hello_world():
        target = os.environ.get('TARGET', 'World')
        return 'Hello {}!\n'.format(target)
    
    if __name__ == "__main__":
        app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))

Java

Créez une application Spring Boot.

  1. Installez Java SE 8 ou une version ultérieure du JDK, et cURL. Java SE et cURL ne sont requis que pour créer le projet Web à l'étape suivante. Le fichier Docker, décrit ultérieurement, charge toutes les dépendances dans le conteneur.

  2. Depuis votre terminal, créez un projet Web vide :

    curl https://start.spring.io/starter.zip \
        -d dependencies=web \
        -d javaVersion=1.8 \
        -d type=maven-project \
        -d bootVersion=2.6.6 \
        -d name=helloworld \
        -d artifactId=helloworld \
        -d baseDir=helloworld-gke \
        -o helloworld-gke.zip
    unzip helloworld-gke.zip
    cd helloworld-gke
    

    Vous disposez maintenant d'un nouveau projet Spring Boot dans helloworld-gke.

  3. Dans le fichier src/main/java/com/example/helloworld/HelloworldApplication.java, mettez à jour la classe HelloworldApplication en ajoutant un champ @RestController pour gérer le mappage /.

    package com.example.helloworld;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @SpringBootApplication
    public class HelloworldApplication {
    
    	@Value("${TARGET:World}")
    	String target;
    
    	@RestController
    	class HelloworldController {
    		@GetMapping("/")
    		String hello() {
    			return "Hello " + target + "!";
    		}
    	}
    
    	public static void main(String[] args) {
    		SpringApplication.run(HelloworldApplication.class, args);
    	}
    }

    Ce code crée un serveur Web qui écoute le port défini par la variable d'environnement PORT.

Votre application est terminée et prête à être empaquetée dans un conteneur Docker, puis importée dans Artifact Registry.

C#

  1. Installez le SDK .NET. Le SDK .NET n'est requis que pour créer le projet Web à l'étape suivante. Le fichier Dockerfile, décrit ultérieurement, charge toutes les dépendances dans le conteneur.

  2. Depuis votre terminal, créez un projet Web vide :

    dotnet new web -o helloworld-gke
    
  3. Remplacez le répertoire par helloworld-gke.

    cd helloworld-gke
    
  4. Mettez à jour Program.cs pour écouter sur le port 8080 :

    var builder = WebApplication.CreateBuilder(args);
    
    // Google Cloud Run sets the PORT environment variable to tell this
    // process which port to listen to.
    var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
    var url = $"http://0.0.0.0:{port}";
    var target = Environment.GetEnvironmentVariable("TARGET") ?? "World";
    
    var app = builder.Build();
    
    app.MapGet("/", () => $"Hello {target}!");
    
    app.Run(url);

Votre application est terminée et prête à être empaquetée dans un conteneur Docker, puis importée dans Artifact Registry.

PHP

  1. Créez un répertoire nommé helloworld-gke et accédez à ce répertoire :

    mkdir helloworld-gke
    cd helloworld-gke
    
  2. Créez un fichier nommé index.php et collez le code suivant dans ce fichier :

    <?php
    $target = getenv('TARGET', true) ?: 'World';
    echo sprintf("Hello %s!", $target);
    ?>

Votre application est terminée et prête à être empaquetée dans un conteneur Docker, puis importée dans Artifact Registry.

Conteneuriser l'application à l'aide de Cloud Build

  1. Pour conteneuriser l'exemple d'application, créez un fichier nommé Dockerfile dans le même répertoire que les fichiers sources, puis copiez le contenu suivant :

    Go

    # Use the offical Go image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.22.0 as builder
    WORKDIR /app
    
    # Initialize a new Go module.
    RUN go mod init quickstart-go
    
    # Copy local code to the container image.
    COPY *.go ./
    
    # Build the command inside the container.
    RUN CGO_ENABLED=0 GOOS=linux go build -o /quickstart-go
    
    # Use a Docker multi-stage build to create a lean production image.
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM gcr.io/distroless/base-debian11
    
    # Change the working directory.
    WORKDIR /
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /quickstart-go /quickstart-go
    
    # Run the web service on container startup.
    USER nonroot:nonroot
    ENTRYPOINT ["/quickstart-go"]

    Node.js

    # Use the official lightweight Node.js 16 image.
    # https://hub.docker.com/_/node
    FROM node:21-slim
    
    # Create and change to the app directory.
    WORKDIR /usr/src/app
    
    # Copy application dependency manifests to the container image.
    # A wildcard is used to ensure both package.json AND package-lock.json are copied.
    # Copying this separately prevents re-running npm install on every code change.
    COPY package*.json ./
    
    # Install production dependencies.
    RUN npm install --omit=dev
    
    # Copy local code to the container image.
    COPY . ./
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]

    Ajoutez un autre fichier .dockerignore pour vous assurer que les fichiers locaux n'affectent pas le processus de création du conteneur :

    Dockerfile
    README.md
    node_modules
    npm-debug.log
    

    Python

    # Use the official lightweight Python image.
    # https://hub.docker.com/_/python
    FROM python:3.12-slim
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Install production dependencies.
    RUN pip install Flask gunicorn
    
    # Run the web service on container startup. Here we use the gunicorn
    # webserver, with one worker process and 8 threads.
    # For environments with multiple CPU cores, increase the number of workers
    # to be equal to the cores available.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app

    Ajoutez un fichier .dockerignore pour vous assurer que les fichiers locaux n'affectent pas le processus de création du conteneur :

    Dockerfile
    README.md
    *.pyc
    *.pyo
    *.pyd
    __pycache__
    

    Java

    # Use the official maven/Java 8 image to create a build artifact.
    # https://hub.docker.com/_/maven
    FROM maven:3.5-jdk-8-alpine as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY pom.xml ./
    COPY src ./src/
    
    # Build a release artifact.
    RUN mvn package -DskipTests
    
    # Use AdoptOpenJDK for base image.
    # It's important to use OpenJDK 8u191 or above that has container support enabled.
    # https://hub.docker.com/r/adoptopenjdk/openjdk8
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM adoptopenjdk/openjdk8:jdk8u202-b08-alpine-slim
    
    # Copy the jar to the production image from the builder stage.
    COPY --from=builder /app/target/helloworld-*.jar /helloworld.jar
    
    # Run the web service on container startup.
    CMD ["java","-Djava.security.egd=file:/dev/./urandom","-Dserver.port=${PORT}","-jar","/helloworld.jar"]

    C#

    # Use Microsoft's official lightweight .NET images.
    FROM mcr.microsoft.com/dotnet/sdk:6.0 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 . ./
    
    # Build a release artifact.
    RUN dotnet publish -c Release -o out
    
    # Run the web service on container startup in a lean production image.
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    WORKDIR /app
    COPY --from=build /app/out .
    
    # Start the .dll (will have the same name as your .csproj file)
    ENTRYPOINT ["dotnet", "helloworld-gke.dll"]

    Ajoutez un fichier .dockerignore pour vous assurer que les fichiers locaux n'affectent pas le processus de création du conteneur :

    Dockerfile
    README.md
    **/obj/
    **/bin/
    

    PHP

    # Use the official PHP 7.4 image.
    # https://hub.docker.com/_/php
    FROM php:8.2-apache
    
    # Copy local code to the container image.
    COPY index.php /var/www/html/
    
    # Use port 8080 in Apache configuration files.
    RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
    
    # Configure PHP for development.
    # Switch to the production php.ini for production operations.
    # RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
    # https://hub.docker.com/_/php#configuration
    RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

    Ajoutez un fichier .dockerignore pour vous assurer que les fichiers locaux n'affectent pas le processus de création du conteneur :

    Dockerfile
    README.md
    vendor
    
  2. Obtenez votre ID de projet Google Cloud :

    gcloud config get-value project
    
  3. Dans ce guide de démarrage rapide, vous allez stocker votre conteneur dans Artifact Registry et le déployer sur votre cluster à partir du registre. Exécutez la commande suivante pour créer un dépôt nommé hello-repo dans le même emplacement que votre cluster :

    gcloud artifacts repositories create hello-repo \
        --project=PROJECT_ID \
        --repository-format=docker \
        --location=us-central1 \
        --description="Docker repository"
    

    Remplacez les valeurs suivantes :

    • PROJECT_ID correspond à votre ID de projet Google Cloud.
  4. Créez votre image de conteneur à l'aide de Cloud Build. Ce processus est semblable à l'exécution de docker build et docker push, mais il est effectué sur Google Cloud.

    gcloud builds submit \
      --tag us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke .
    

    L'image est stockée dans Container Registry.

Créer un cluster GKE

Un cluster GKE est un ensemble géré de machines virtuelles Compute Engine fonctionnant comme un cluster GKE unique.

  1. Créez le cluster.

    gcloud container clusters create-auto helloworld-gke \
      --location us-central1
    
  2. Vérifiez que vous avez accès au cluster. La commande suivante répertorie les nœuds de votre cluster de conteneurs qui sont opérationnels et indique que vous avez accès au cluster.

    kubectl get nodes
    

    Si vous rencontrez des erreurs, consultez le guide de dépannage de Kubernetes.

Déployer sur GKE

Pour déployer votre application sur le cluster GKE que vous avez créé, vous avez besoin de deux objets Kubernetes.

  1. Un objet Deployment pour définir votre application
  2. Un service pour définir comment accéder à votre application

Déployer une application

L'application dispose d'une interface qui gère les requêtes Web. Vous définissez les ressources de cluster nécessaires à l'exécution de l'interface dans un nouveau fichier appelé deployment.yaml. Ces ressources sont décrites comme un déploiement. Vous utilisez les déploiements pour créer et mettre à jour un ensemble d'instances dupliquées (ReplicaSet) et ses pods associés.

  1. Créez le fichier deployment.yaml dans le même répertoire que vos autres fichiers et copiez le contenu suivant : Remplacez les valeurs suivantes dans votre fichier :

    • $GCLOUD_PROJECT correspond à votre ID de projet Google Cloud.
    • $LOCATION correspond à l'emplacement du dépôt, par exemple us-central1.
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloworld-gke
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: hello
      template:
        metadata:
          labels:
            app: hello
        spec:
          containers:
          - name: hello-app
            # Replace $LOCATION with your Artifact Registry location (e.g., us-west1).
            # Replace $GCLOUD_PROJECT with your project ID.
            image: $LOCATION-docker.pkg.dev/$GCLOUD_PROJECT/hello-repo/helloworld-gke:latest
            # This app listens on port 8080 for web traffic by default.
            ports:
            - containerPort: 8080
            env:
              - name: PORT
                value: "8080"
            resources:
              requests:
                memory: "1Gi"
                cpu: "500m"
                ephemeral-storage: "1Gi"
              limits:
                memory: "1Gi"
                cpu: "500m"
                ephemeral-storage: "1Gi"
  2. Déployez la ressource sur le cluster :

    kubectl apply -f deployment.yaml
    
  3. Suivez l'état du déploiement :

    kubectl get deployments
    

    Le déploiement est terminé lorsque tous les déploiements AVAILABLE affichent l'état READY.

    NAME              READY   UP-TO-DATE   AVAILABLE   AGE
    helloworld-gke    1/1     1            1           20s
    

    Si le déploiement rencontre une erreur, exécutez à nouveau kubectl apply -f deployment.yaml pour mettre à jour le déploiement en cas de modification.

  4. Une fois le déploiement terminé, les pods créés par le déploiement s'affichent :

    kubectl get pods
    

Déployer un service

Les services fournissent un point d'accès unique à un ensemble de pods. Bien qu'il soit possible d'accéder à un pod unique, les pods sont éphémères et ne peuvent être accessibles de manière fiable qu'à l'aide d'une adresse de service. Dans l'application Hello World, le service "hello" définit un équilibreur de charge pour accéder aux pods hello-app à partir d'une adresse IP unique. Ce service est défini dans le fichier service.yaml.

  1. Créez le fichier service.yaml dans le même répertoire que vos autres fichiers sources en incluant le contenu suivant :

    # The hello service provides a load-balancing proxy over the hello-app
    # pods. By specifying the type as a 'LoadBalancer', Kubernetes Engine will
    # create an external HTTP load balancer.
    apiVersion: v1
    kind: Service
    metadata:
      name: hello
    spec:
      type: LoadBalancer
      selector:
        app: hello
      ports:
      - port: 80
        targetPort: 8080

    Les pods sont définis séparément du service qui utilise les pods. Kubernetes utilise des libellés pour sélectionner les pods auxquels accède un service. Les libellés vous permettent d'utiliser un service unique pour interagir avec les pods de différents ensembles d'instances dupliquées. Vous pouvez également faire pointer plusieurs services vers un pod unique.

  2. Créez le service Hello World :

    kubectl apply -f service.yaml
    
  3. Recherchez l'adresse IP externe du service :

    kubectl get services
    

    L'allocation de l'adresse IP peut prendre jusqu'à 60 secondes. L'adresse IP externe est répertoriée sous la colonne EXTERNAL-IP du service hello.

    NAME         TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)        AGE
    hello        LoadBalancer   10.22.222.222   35.111.111.11   80:32341/TCP   1m
    kubernetes   ClusterIP      10.22.222.1     <none>          443/TCP        20m
    

Afficher une application déployée

Vous avez déployé toutes les ressources nécessaires à l'exécution de l'application Hello World sur GKE.

Utilisez l'adresse IP externe de l'étape précédente pour charger l'application dans votre navigateur Web et afficher votre application en cours d'exécution :

 http://EXTERNAL_IP

Vous pouvez également effectuer un appel curl à l'adresse IP externe du service :

curl EXTERNAL_IP

Le résultat suivant s'affiche :

Hello World!

Effectuer un nettoyage

Pour éviter que les ressources utilisées sur cette page soient facturées sur votre compte Google Cloud, procédez comme suit :

Les instances Compute Engine exécutées dans votre cluster vous sont facturées, ainsi que l'image de conteneur dans Container Registry.

Supprimer le projet

La suppression de votre projet Google Cloud arrête la facturation de toutes les ressources utilisées dans ce projet.

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer le cluster et le conteneur

Si vous souhaitez conserver le projet et ne supprimer que les ressources que vous avez utilisées dans ce tutoriel, supprimez le cluster et l'image.

Pour supprimer un cluster à l'aide de Google Cloud CLI, exécutez l'une des commandes suivantes, selon le mode que vous avez utilisé :

gcloud container clusters delete helloworld-gke \
    --location us-central1

Pour supprimer une image dans votre dépôt Artifact Registry, exécutez la commande suivante :

gcloud artifacts docker images delete \
    us-central1-docker.pkg.dev/PROJECT_ID/hello-repo/helloworld-gke

Étapes suivantes

Pour plus d'informations sur Kubernetes, consultez les ressources suivantes :

Pour plus d'informations sur le déploiement sur GKE, consultez les ressources suivantes :

Pour en savoir plus sur la création, le développement et l'exécution d'applications sur GKE directement à partir de votre IDE avec Cloud Code, consultez les ressources suivantes :