Tutoriel "Utiliser Cloud Pub/Sub avec Cloud Run"

Ce tutoriel explique comment écrire, déployer et appeler un service Cloud Run à partir d'un abonnement push Cloud Pub/Sub.

Vous pouvez utiliser ce tutoriel avec Cloud Run ou Cloud Run sur GKE.

Objectifs

  • Écrire, créer et déployer un service sur Cloud Run ou Cloud Run sur GKE.
  • Appeler le service en publiant un message dans un sujet Cloud Pub/Sub.

Coûts

Ce tutoriel utilise des composants facturables de Cloud Platform, dont :

Les nouveaux utilisateurs de Cloud Platform peuvent bénéficier d'un essai gratuit.

Avant de commencer

  1. Connectez-vous à votre compte Google.

    Si vous n'en possédez pas déjà un, vous devez en créer un.

  2. Dans la page de sélection du projet de la console GCP, sélectionnez ou créez un projet GCP.

    Accéder à la page de sélection du projet

  3. Assurez-vous que la facturation est activée pour votre projet Google Cloud Platform. Découvrez comment confirmer que la facturation est activée pour votre projet.

  4. Activez l'API Cloud Run
  5. Installez et initialisez le SDK Cloud.
  6. Installez le composant gcloud beta :
    gcloud components install beta
  7. Pour Cloud Run sur GKE, installez le composant gcloud kubectl :
    gcloud components install kubectl
  8. Mettez à jour les composants :
    gcloud components update
  9. Si vous utilisez Cloud Run sur GKE, créez un nouveau cluster en suivant les instructions de la section Configurer Cloud Run sur GKE.

Configurer les paramètres par défaut de gcloud

Pour configurer gcloud avec les valeurs par défaut pour votre service Cloud Run, procédez comme suit :

  1. Définissez le projet par défaut :

    gcloud config set project [PROJECT-ID]

    Remplacez [PROJECT-ID] par le nom du projet que vous avez créé pour ce tutoriel.

  2. Si vous utilisez Cloud Run, configurez gcloud pour la région choisie :

     gcloud config set run/region us-central1
    

    Remplacez us-central1 par la région Cloud Run disponible de votre choix.

  3. Si vous utilisez Cloud Run sur GKE, configurez gcloud pour votre cluster :

    gcloud config set run/cluster [CLUSTER-NAME]
    gcloud config set run/cluster_location us-central1-a

    Remplacez [CLUSTER-NAME] par le nom utilisé pour votre cluster et, le cas échéant, remplacez us-central1-a par l'emplacement de cluster disponible de votre choix.

Emplacements Cloud Run

Cloud Run est régional, ce qui signifie que l’infrastructure qui exécute vos services Cloud Run est située dans une région spécifique, et gérée par Google pour être disponible de manière redondante dans toutes les zones de cette région.

Lors de la sélection de la région dans laquelle exécuter vos services Cloud Run, vous devez tout d'abord considérer vos exigences en matière de latence, de disponibilité et de durabilité. D'une manière générale, vous pouvez sélectionner la région la plus proche de vos utilisateurs. Mais vous devez également tenir compte de l'emplacement des autres produits GCP utilisés par votre service Cloud Run. L'utilisation combinée de produits GCP sur plusieurs sites peut affecter la latence de votre service, ainsi que son coût.

Cloud Run est disponible dans les régions suivantes :

  • us-central1 (Iowa)

Si vous avez déjà créé un service Cloud Run, vous pouvez afficher la région dans le tableau de bord Cloud Run de la console GCP.

Créer un sujet Cloud Pub/Sub

L'exemple de service est déclenché par des messages publiés dans un sujet Cloud Pub/Sub. Vous devez donc créer un sujet dans Cloud Pub/Sub.

Pour créer un nouveau sujet Cloud Pub/Sub, utilisez la commande suivante :

gcloud pubsub topics create myRunTopic

Vous pouvez conserver le nom myRunTopic ou le remplacer par un nom de sujet unique dans votre projet GCP.

Récupérer l'exemple de code

Pour récupérer l’exemple de code à utiliser, procédez comme suit :

  1. Téléchargez l'exemple de code de service :

    Node.js

    Go

  2. Décompressez l'archive. Vous pouvez utiliser ces utilitaires de ligne de commande Linux et macOS standards :

    Tarball

    tar -xzvf [FILE].tar.gz

    Fichier ZIP

    unzip [FILE].zip

    [FILE] est le nom du fichier de l’archive téléchargée, sans l’extension de fichier.

Examiner le code

Le code de ce tutoriel comprend les éléments suivants :

  • Un serveur qui gère les requêtes HTTP entrantes.

    Node.js

    Pour que le service Node.js reste facile à tester, la configuration du serveur est distincte du démarrage du serveur.

    Le serveur Web Node.js est configuré dans app.js

    const express = require('express')
    const bodyParser = require('body-parser');
    const app = express()
    
    app.use(bodyParser.json())
    
    Le serveur Web est démarré dans index.js :
    const app = require('./app.js');
    const PORT = process.env.PORT || 8080;
    
    app.listen(PORT, () => console.log(`nodejs-pubsub-tutorial listening on port ${PORT}`))

    Go

    // Sample run-pubsub is a Cloud Run service which handles Pub/Sub messages.
    package main
    
    import (
    	"encoding/json"
    	"fmt"
    	"log"
    	"net/http"
    	"os"
    )
    
    func main() {
    	http.HandleFunc("/", HelloPubSub)
    	// Determine port for HTTP service.
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    		log.Printf("Defaulting to port %s", port)
    	}
    	// Start HTTP server.
    	log.Printf("Listening on port %s", port)
    	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    }
    

  • Une fonction Hello World qui gère le message Cloud Pub/Sub et enregistre un message d'accueil.

    Node.js

    app.post('/', (req, res) => {
    
      if (!req.body) {
        const msg = 'no Pub/Sub message received'
        console.error(`error: ${msg}`)
        res.status(400).send(`Bad Request: ${msg}`)
        return
      }
      if (!req.body.message) {
        const msg = 'invalid Pub/Sub message format'
        console.error(`error: ${msg}`)
        res.status(400).send(`Bad Request: ${msg}`)
        return
      }
    
      const pubSubMessage = req.body.message
      const name = pubSubMessage.data
        ? Buffer.from(pubSubMessage.data, 'base64').toString().trim()
        : 'World'
    
      console.log(`Hello ${name}!`)
      res.status(204).send()
    })
    

    Go

    // PubSubMessage is the payload of a Pub/Sub event. Please refer to the docs for
    // additional information regarding Pub/Sub events.
    type PubSubMessage struct {
    	Message struct {
    		Data []byte `json:"data,omitempty"`
    		ID   string `json:"id"`
    	} `json:"message"`
    	Subscription string `json:"subscription"`
    }
    
    // HelloPubSub consumes a Pub/Sub message.
    func HelloPubSub(w http.ResponseWriter, r *http.Request) {
    	// Parse the Pub/Sub message.
    	var m PubSubMessage
    
    	if err := json.NewDecoder(r.Body).Decode(&m); err != nil {
    		log.Printf("json.NewDecoder: %v", err)
    		http.Error(w, "Bad Request", http.StatusBadRequest)
    		return
    	}
    
    	name := string(m.Message.Data)
    	if name == "" {
    		name = "World"
    	}
    	log.Printf("Hello %s!", name)
    }
    

    Vous devez coder le service pour renvoyer un code de réponse HTTP précis. Les codes de réussite, tels que HTTP 200 ou 204, confirment le traitement complet du message Cloud Pub/Sub. Les codes d'erreur, tels que HTTP 400 ou 500, indiquent qu'une nouvelle tentative d'envoi sera effectuée, comme décrit dans le guide Recevoir des messages en mode push.

  • Un Dockerfile qui définit l'environnement d'exploitation du service. Le contenu du Dockerfile varie selon le langage.

    Node.js

    # Use the official Node.js 10 image.
    # https://hub.docker.com/_/node
    FROM node:10
    
    # 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 --only=production
    
    # Copy local code to the container image.
    COPY . .
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Go

    # Use the offical Golang image to create a build artifact.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang as builder
    
    # Copy local code to the container image.
    WORKDIR /app
    COPY . .
    
    # Build the outyet command inside the container.
    # (You may fetch or manage dependencies here,
    # either manually or with a tool like "godep".)
    RUN CGO_ENABLED=0 GOOS=linux go build -v -o hellopubsub
    
    # 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 alpine
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /app/hellopubsub .
    
    # Service must listen to $PORT environment variable.
    # This default value facilitates local development.
    ENV PORT 8080
    
    # Run the web service on container startup.
    CMD ["/hellopubsub"]
    

Pour savoir en détail comment authentifier l'origine des requêtes Cloud Pub/Sub, lisez la section ci-dessous Intégration à Cloud Pub/Sub.

Transmettre le code

La transmission du code se déroule en trois étapes : création d'une image de conteneur avec Cloud Build, importation de l'image de conteneur dans Container Registry, puis déploiement de l'image de conteneur dans Cloud Run ou Cloud Run sur GKE.

Pour transmettre votre code, procédez comme suit :

  1. Créez votre conteneur et publiez-le dans Container Registry.

    gcloud builds submit --tag gcr.io/[PROJECT-ID]/pubsub

    [PROJECT-ID] est votre ID de projet GCP, et pubsub est le nom que vous voulez donner à votre service.

    En cas de réussite, un message SUCCESS apparaît contenant l'ID, l'heure de création et le nom de l'image. Celle-ci est stockée dans Container Registry et peut être réutilisée au besoin.

  2. Exécutez la commande suivante pour déployer votre application :

    gcloud beta run deploy pubsub-tutorial --image gcr.io/[PROJECT-ID]/pubsub

    Remplacez [PROJECT-ID] par votre ID de projet GCP. pubsub est le nom du conteneur et pubsub-tutorial le nom du service. Notez que l'image du conteneur est déployée sur le service et la région (Cloud Run) ou sur le cluster (Cloud Run sur GKE) que vous avez précédemment configurés dans la section Configurer gcloud.

    Si vous déployez sur Cloud Run, répondez n, "non", à l'invite "Autoriser sans authentification". En gardant le service privé, le processus d'intégration automatique de Cloud Pub/Sub de Cloud Run assure l'authentification des requêtes. Cette configuration est présentée en détail dans la section Intégration à Cloud Pub/Sub ci-après. Pour en savoir plus sur l'authentification basée sur IAM, consultez la page Gérer l'accès.

    Patientez jusqu'à la fin du déploiement, soit environ 30 secondes. En cas de réussite, la ligne de commande affiche l'URL du service, laquelle permet de configurer un abonnement Cloud Pub/Sub.

  3. Si vous souhaitez déployer une mise à jour de code sur le service, répétez les opérations précédentes. Chaque déploiement sur un service crée une nouvelle révision et commence automatiquement à acheminer le trafic une fois prêt.

Intégration à Cloud Pub/Sub

Maintenant que nous avons déployé notre service Cloud Run, nous allons configurer Cloud Pub/Sub pour y transférer les messages.

Pour intégrer le service à Cloud Pub/Sub, procédez comme suit :

  1. Activez le projet pour créer des jetons d'authentification Cloud Pub/Sub :

    gcloud projects add-iam-policy-binding [PROJECT-ID] \
         --member=serviceAccount:service-[PROJECT-NUMBER]@gcp-sa-pubsub.iam.gserviceaccount.com \
         --role=roles/iam.serviceAccountTokenCreator

    Remplacer

    • [PROJECT-ID] par votre ID de projet GCP.
    • [PROJECT-NUMBER] par votre numéro de projet GCP.
  2. Créez ou sélectionnez un compte de service pour représenter l'identité de l'abonnement Cloud Pub/Sub.

    gcloud iam service-accounts create cloud-run-pubsub-invoker \
         --display-name "Cloud Run Pub/Sub Invoker"

    Vous pouvez utiliser l'identité cloud-run-pubsub-invoker ou la remplacer par un nom unique dans votre projet Google Cloud Platform.

  3. Pour Cloud Run, autorisez ce compte de service à appeler votre service pubsub-tutorial :

    gcloud beta run services add-iam-policy-binding pubsub-tutorial \
         --member=serviceAccount:cloud-run-pubsub-invoker@[PROJECT-ID].iam.gserviceaccount.com \
         --role=roles/run.invoker

    La diffusion des modifications IAM peut prendre plusieurs minutes. Entre-temps, des erreurs HTTP 403 peuvent apparaître dans les journaux du service.

  4. Créez un abonnement Cloud Pub/Sub avec le compte de service :

    gcloud beta pubsub subscriptions create myRunSubscription --topic myRunTopic \
       --push-endpoint=[SERVICE-URL]/ \
       --push-auth-service-account=cloud-run-pubsub-invoker@[PROJECT-ID].iam.gserviceaccount.com

    Remplacer

    • myRunTopic par le sujet que vous avez créé précédemment.
    • [SERVICE-URL] par l'URL HTTPS fournie lors du déploiement du service.
    • [PROJECT-ID] par votre ID de projet GCP.

    L'indicateur --push-account-service-account active la fonctionnalité push de Cloud Pub/Sub pour l'authentification et l'autorisation.

  5. Si vous avez déployé sur Cloud Run et que vous utilisez le domaine run.app par défaut, le domaine de votre service est automatiquement enregistré pour être utilisé avec les abonnements Cloud Pub/Sub dans le même projet. Si vous utilisez un domaine personnalisé, vous devez enregistrer la propriété du domaine. Pour sécuriser les transmissions push vers un service Cloud Run avec un domaine personnalisé, configurez plutôt votre abonnement de la façon suivante :

    gcloud beta pubsub subscriptions create myRunSubscription --topic myRunTopic \
       --push-endpoint=https://[CUSTOM-DOMAIN] \
       --push-auth-service-account=cloud-run-pubsub-invoker@[PROJECT-ID].iam.gserviceaccount.com \
       --push-auth-token-audience=[SERVICE-URL]/

    Remplacer

    • myRunTopic par le sujet que vous avez créé précédemment.
    • [CUSTOM-DOMAIN] par votre domaine personnalisé précédemment mappé.
    • [PROJECT-ID] par votre ID de projet GCP.
    • [SERVICE-URL] par l'URL HTTPS fournie lors du déploiement du service.
  6. Si vous déployez sur Cloud Run, toutes les requêtes Cloud Pub/Sub sont authentifiées avant d’atteindre votre service. Pour les cas d'utilisation avancée ou si vous déployez dans Cloud Run sur GKE, validez le jeton Web JSON envoyé avec la requête Cloud Pub/Sub pour votre service. Consultez la page Authentification et autorisation pour obtenir d'autres informations.

Votre service est maintenant entièrement intégré à Cloud Pub/Sub.

Essayez-le !

Pour tester la solution de bout en bout, procédez comme suit :

  1. Envoyez un message au sujet sur Cloud Pub/Sub :

    gcloud pubsub topics publish myRunTopic --message "Runner"

    Au lieu d'utiliser la ligne de commande comme décrit dans ce tutoriel, vous pouvez programmer la publication des messages. Reportez-vous à la page Publier des messages pour en savoir plus.

  2. Accédez aux journaux du service :

    1. Accédez à la console Google Cloud Platform.
    2. Cliquez sur le service pubsub-tutorial.
    3. Sélectionnez l'onglet Journaux.

      L'affichage des journaux peut nécessiter quelques instants. S'ils n'apparaissent pas immédiatement, patientez et vérifiez de nouveau.

  3. Recherchez le message "Hello Runner !"

Effectuer un nettoyage

Supprimer le projet

Le moyen le plus simple d'éviter la facturation consiste à supprimer le projet que vous avez créé pour le tutoriel.

Pour supprimer le projet :

  1. Dans la console GCP, 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 service Cloud Run

La suppression de services Cloud Run ne supprime pas les ressources stockées dans Cloud Storage. Si vous souhaitez les supprimer, faites-le séparément.

Pour supprimer le service que vous avez déployé dans ce tutoriel, procédez comme suit :

gcloud beta run services delete [SERVICE-NAME]

[SERVICE-NAME] est le nom du service que vous avez choisi.

Vous pouvez également supprimer les services Cloud Run ou Cloud Run sur GKE à partir de la console Google Cloud Platform.

Étapes suivantes