Tutorial para usar Pub/Sub con Cloud Run

En este tutorial se muestra cómo escribir, desplegar y llamar a un servicio de Cloud Run desde una suscripción de inserción de Pub/Sub.

Configurar los valores predeterminados de gcloud

Para configurar gcloud con los valores predeterminados de tu servicio de Cloud Run, sigue estos pasos:

  1. Configura tu proyecto predeterminado:

    gcloud config set project PROJECT_ID

    Sustituye PROJECT_ID por el nombre del proyecto que has creado para este tutorial.

  2. Configura gcloud para la región que hayas elegido:

    gcloud config set run/region REGION

    Sustituye REGION por la región de Cloud Run compatible que quieras.

Ubicaciones de Cloud Run

Cloud Run es regional, lo que significa que la infraestructura que ejecuta tus servicios de Cloud Run se encuentra en una región específica y Google la gestiona para que esté disponible de forma redundante en todas las zonas de esa región.

Cumplir tus requisitos de latencia, disponibilidad o durabilidad son factores primordiales para seleccionar la región en la que se ejecutan tus servicios de Cloud Run. Por lo general, puedes seleccionar la región más cercana a tus usuarios, pero debes tener en cuenta la ubicación de los otros Google Cloudproductos que utiliza tu servicio de Cloud Run. Usar Google Cloud productos juntos en varias ubicaciones puede afectar a la latencia y al coste de tu servicio.

Cloud Run está disponible en las siguientes regiones:

Con sujeción a los precios del nivel 1

  • asia-east1 (Taiwán)
  • asia-northeast1 (Tokio)
  • asia-northeast2 (Osaka)
  • asia-south1 (Bombay, la India)
  • europe-north1 (Finlandia) icono de una hoja CO2 bajo
  • europe-north2 (Estocolmo) icono de una hoja CO2 bajo
  • europe-southwest1 (Madrid) icono de una hoja CO2 bajo
  • europe-west1 (Bélgica) icono de una hoja CO2 bajo
  • europe-west4 (Países Bajos) icono de una hoja CO2 bajo
  • europe-west8 (Milán)
  • europe-west9 (París) icono de una hoja CO2 bajo
  • me-west1 (Tel Aviv)
  • northamerica-south1 (México)
  • us-central1 (Iowa) icono de una hoja CO2 bajo
  • us-east1 (Carolina del Sur)
  • us-east4 (Norte de Virginia)
  • us-east5 (Columbus)
  • us-south1 (Dallas) icono de una hoja CO2 bajo
  • us-west1 (Oregón) icono de una hoja CO2 bajo

Con sujeción a los precios del nivel 2

  • africa-south1 (Johannesburgo)
  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seúl, Corea del Sur)
  • asia-southeast1 (Singapur)
  • asia-southeast2 (Yakarta)
  • asia-south2 (Delhi, la India)
  • australia-southeast1 (Sídney)
  • australia-southeast2 (Melbourne)
  • europe-central2 Varsovia (Polonia)
  • europe-west10 (Berlín)
  • europe-west12 (Turín)
  • europe-west2 (Londres, Reino Unido) icono de una hoja CO2 bajo
  • europe-west3 (Fráncfort, Alemania)
  • europe-west6 (Zúrich, Suiza) icono de una hoja Bajas emisiones de CO2
  • me-central1 (Doha)
  • me-central2 (Dammam)
  • northamerica-northeast1 (Montreal) icono de una hoja CO2 bajo
  • northamerica-northeast2 (Toronto) icono de una hoja CO2 bajo
  • southamerica-east1 (São Paulo, Brasil) icono de una hoja CO2 bajo
  • southamerica-west1 (Santiago, Chile) icono de una hoja CO2 bajo
  • us-west2 (Los Ángeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Si ya has creado un servicio de Cloud Run, puedes ver la región en el panel de control de Cloud Run de la Google Cloud consola.

Crear un repositorio estándar de Artifact Registry

Crea un repositorio estándar de Artifact Registry para almacenar tu imagen de contenedor:

gcloud artifacts repositories create REPOSITORY \
    --repository-format=docker \
    --location=REGION

Sustituye:

  • REPOSITORY con un nombre único para el repositorio.
  • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

Crear un tema de Pub/Sub

El servicio de ejemplo se activa mediante mensajes publicados en un tema de Pub/Sub, por lo que tendrás que crear un tema en Pub/Sub.

gcloud

Para crear un tema de Pub/Sub, usa el comando:

gcloud pubsub topics create myRunTopic

Puedes usar myRunTopic o sustituirlo por un nombre de tema único en tu proyecto Google Cloud .

Terraform

Para saber cómo aplicar o quitar una configuración de Terraform, consulta Comandos básicos de Terraform.

Para crear un tema de Pub/Sub, añade lo siguiente al archivo main.tf:

resource "google_pubsub_topic" "default" {
  name = "pubsub_topic"
}

Puedes usar un nombre de tema único en tu proyecto de Cloud.

Obtener el código de ejemplo

Para obtener el código de muestra que vas a usar, sigue estos pasos:

  1. Clona el repositorio de aplicaciones de muestra en la máquina local:

    Node.js

    git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

    También puedes descargar el ejemplo como un archivo ZIP y extraerlo.

    Python

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git

    También puedes descargar el ejemplo como un archivo ZIP y extraerlo.

    Go

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git

    También puedes descargar el ejemplo como un archivo ZIP y extraerlo.

    Java

    git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git

    También puedes descargar el ejemplo como un archivo ZIP y extraerlo.

    C#

    git clone https://github.com/GoogleCloudPlatform/dotnet-docs-samples.git

    También puedes descargar el ejemplo como un archivo ZIP y extraerlo.

  2. Cambia al directorio que contiene el código de ejemplo de Cloud Run:

    Node.js

    cd nodejs-docs-samples/run/pubsub/

    Python

    cd python-docs-samples/run/pubsub/

    Go

    cd golang-samples/run/pubsub/

    Java

    cd java-docs-samples/run/pubsub/

    C#

    cd dotnet-docs-samples/run/Run.Samples.Pubsub.MinimalApi/

Revisar el código

El código de este tutorial consta de lo siguiente:

  • Un servidor que gestiona las solicitudes entrantes.

    Node.js

    Para que el servicio Node.js sea fácil de probar, la configuración del servidor está separada del inicio del servidor.

    El servidor web Node.js se configura en app.js.

    const express = require('express');
    const app = express();
    
    // This middleware is available in Express v4.16.0 onwards
    app.use(express.json());

    El servidor web se inicia en index.js:

    const app = require('./app.js');
    const PORT = parseInt(parseInt(process.env.PORT)) || 8080;
    
    app.listen(PORT, () =>
      console.log(`nodejs-pubsub-tutorial listening on port ${PORT}`)
    );

    Python

    import base64
    
    from flask import Flask, request
    
    
    app = Flask(__name__)
    

    Go

    
    // Sample run-pubsub is a Cloud Run service which handles Pub/Sub messages.
    package main
    
    import (
    	"encoding/json"
    	"io"
    	"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)
    	if err := http.ListenAndServe(":"+port, nil); err != nil {
    		log.Fatal(err)
    	}
    }
    

    Java

    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class PubSubApplication {
      public static void main(String[] args) {
        SpringApplication.run(PubSubApplication.class, args);
      }
    }

    C#

    var builder = WebApplication.CreateBuilder(args);
    var app = builder.Build();
    
    var port = Environment.GetEnvironmentVariable("PORT");
    if (port != null)
    {
        app.Urls.Add($"http://0.0.0.0:{port}");
    }
    

  • Un controlador que procesa el mensaje de Pub/Sub y registra un saludo.

    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();
    });

    Python

    @app.route("/", methods=["POST"])
    def index():
        """Receive and parse Pub/Sub messages."""
        envelope = request.get_json()
        if not envelope:
            msg = "no Pub/Sub message received"
            print(f"error: {msg}")
            return f"Bad Request: {msg}", 400
    
        if not isinstance(envelope, dict) or "message" not in envelope:
            msg = "invalid Pub/Sub message format"
            print(f"error: {msg}")
            return f"Bad Request: {msg}", 400
    
        pubsub_message = envelope["message"]
    
        name = "World"
        if isinstance(pubsub_message, dict) and "data" in pubsub_message:
            name = base64.b64decode(pubsub_message["data"]).decode("utf-8").strip()
    
        print(f"Hello {name}!")
    
        return ("", 204)
    
    

    Go

    
    // WrappedMessage is the payload of a Pub/Sub event.
    //
    // For more information about receiving messages from a Pub/Sub event
    // see: https://cloud.google.com/pubsub/docs/push#receive_push
    type WrappedMessage struct {
    	Message struct {
    		Data []byte `json:"data,omitempty"`
    		ID   string `json:"id"`
    	} `json:"message"`
    	Subscription string `json:"subscription"`
    }
    
    // HelloPubSub receives and processes a Pub/Sub push message.
    func HelloPubSub(w http.ResponseWriter, r *http.Request) {
    	var m WrappedMessage
    	body, err := io.ReadAll(r.Body)
    	defer r.Body.Close()
    	if err != nil {
    		log.Printf("io.ReadAll: %v", err)
    		http.Error(w, "Bad Request", http.StatusBadRequest)
    		return
    	}
    	// byte slice unmarshalling handles base64 decoding.
    	if err := json.Unmarshal(body, &m); err != nil {
    		log.Printf("json.Unmarshal: %v", err)
    		http.Error(w, "Bad Request", http.StatusBadRequest)
    		return
    	}
    
    	name := string(m.Message.Data)
    	if name == "" {
    		name = "World"
    	}
    	log.Printf("Hello %s!", name)
    }
    

    Java

    import com.example.cloudrun.Body;
    import java.util.Base64;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    
    // PubsubController consumes a Pub/Sub message.
    @RestController
    public class PubSubController {
      @RequestMapping(value = "/", method = RequestMethod.POST)
      public ResponseEntity<String> receiveMessage(@RequestBody Body body) {
        // Get PubSub message from request body.
        Body.Message message = body.getMessage();
        if (message == null) {
          String msg = "Bad Request: invalid Pub/Sub message format";
          System.out.println(msg);
          return new ResponseEntity<>(msg, HttpStatus.BAD_REQUEST);
        }
    
        String data = message.getData();
        String target =
            !StringUtils.isEmpty(data) ? new String(Base64.getDecoder().decode(data)) : "World";
        String msg = "Hello " + target + "!";
    
        System.out.println(msg);
        return new ResponseEntity<>(msg, HttpStatus.OK);
      }
    }

    C#

    app.MapPost("/", (Envelope envelope) =>
    {
        if (envelope?.Message?.Data == null)
        {
            app.Logger.LogWarning("Bad Request: Invalid Pub/Sub message format.");
            return Results.BadRequest();
        }
    
        var data = Convert.FromBase64String(envelope.Message.Data);
        var target = System.Text.Encoding.UTF8.GetString(data);
    
        app.Logger.LogInformation($"Hello {target}!");
    
        return Results.NoContent();
    });
    

    Debes codificar el servicio para que devuelva un código de respuesta HTTP preciso. Los códigos de éxito, como HTTP 200 o 204, confirman que el mensaje de Pub/Sub se ha procesado por completo. Los códigos de error, como 400 o 500 de HTTP, indican que se volverá a intentar enviar el mensaje, tal como se describe en la guía para recibir mensajes mediante Push.

  • Un Dockerfile que define el entorno operativo del servicio. El contenido de Dockerfile varía según el idioma.

    Node.js

    
    # Use the official lightweight Node.js image.
    # https://hub.docker.com/_/node
    FROM node:20-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 dependencies.
    # if you need a deterministic and repeatable build create a
    # package-lock.json file and use npm ci:
    # RUN npm ci --omit=dev
    # if you need to include development dependencies during development
    # of your application, use:
    # RUN npm install --dev
    
    RUN npm install --omit=dev
    
    # Copy local code to the container image.
    COPY . .
    
    # Run the web service on container startup.
    CMD [ "npm", "start" ]
    

    Python

    
    # Use the official Python image.
    # https://hub.docker.com/_/python
    FROM python:3.11
    
    # Allow statements and log messages to immediately appear in the Cloud Run logs
    ENV PYTHONUNBUFFERED True
    
    # Copy application dependency manifests to the container image.
    # Copying this separately prevents re-running pip install on every code change.
    COPY requirements.txt ./
    
    # Install production dependencies.
    RUN pip install -r requirements.txt
    
    # Copy local code to the container image.
    ENV APP_HOME /app
    WORKDIR $APP_HOME
    COPY . ./
    
    # Run the web service on container startup.
    # Use 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.
    # Timeout is set to 0 to disable the timeouts of the workers to allow Cloud Run to handle instance scaling.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
    

    Go

    
    # Use the official Go image to create a binary.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.24-bookworm as builder
    
    # Create and change to the app directory.
    WORKDIR /app
    
    # Retrieve application dependencies.
    # This allows the container build to reuse cached dependencies.
    # Expecting to copy go.mod and if present go.sum.
    COPY go.* ./
    RUN go mod download
    
    # Copy local code to the container image.
    COPY . ./
    
    # Build the binary.
    RUN go build -v -o server
    
    # Use the official Debian slim image for a lean production container.
    # https://hub.docker.com/_/debian
    # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
    FROM debian:bookworm-slim
    RUN set -x && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
        ca-certificates && \
        rm -rf /var/lib/apt/lists/*
    
    # Copy the binary to the production image from the builder stage.
    COPY --from=builder /app/server /server
    
    # Run the web service on container startup.
    CMD ["/server"]
    

    Java

    En este ejemplo se usa Jib para crear imágenes de Docker con herramientas comunes de Java. Jib optimiza las compilaciones de contenedores sin necesidad de usar un Dockerfile ni de tener Docker instalado. Más información sobre cómo crear contenedores Java con Jib

    <plugin>
      <groupId>com.google.cloud.tools</groupId>
      <artifactId>jib-maven-plugin</artifactId>
      <version>3.4.0</version>
      <configuration>
        <to>
          <image>gcr.io/PROJECT_ID/pubsub</image>
        </to>
      </configuration>
    </plugin>
    

    C#

    # Build in SDK base image
    FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
    WORKDIR /app
    
    COPY *.csproj ./
    RUN dotnet restore
    
    COPY . ./
    RUN dotnet publish -r linux-x64 --no-self-contained -p:PublishReadyToRun=true -c Release -o out
    
    # Copy to runtime image
    FROM mcr.microsoft.com/dotnet/aspnet:6.0
    WORKDIR /app
    COPY --from=build-env /app/out .
    
    # Port passed in by Cloud Run via environment variable PORT.  Default 8080.
    ENV PORT=8080
    
    ENTRYPOINT ["dotnet", "Run.Samples.Pubsub.MinimalApi.dll"]

Para obtener información sobre cómo autenticar el origen de las solicitudes de Pub/Sub, consulta Integrar con Pub/Sub.

Lanzar el código

El envío de código consta de tres pasos: crear una imagen de contenedor con Cloud Build, subir la imagen de contenedor a Artifact Registry y desplegar la imagen de contenedor en Cloud Run.

Para enviar tu código, sigue estos pasos:

  1. Crea el contenedor y publícalo en Artifact Registry:

    Node.js

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
    Reemplazar:
    • PROJECT_ID por el ID de tu proyecto. Google Cloud
    • REPOSITORY con el nombre del repositorio de Artifact Registry.
    • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

    pubsub es el nombre de la imagen.

    Si la operación se realiza correctamente, verás un mensaje de ÉXITO que contiene el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y se puede volver a usar si es necesario.

    Python

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
    Reemplazar:
    • PROJECT_ID por el ID de tu proyecto. Google Cloud
    • REPOSITORY con el nombre del repositorio de Artifact Registry.
    • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

    pubsub es el nombre de la imagen.

    Si la operación se realiza correctamente, verás un mensaje de ÉXITO que contiene el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y se puede volver a usar si es necesario.

    Go

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
    Reemplazar:
    • PROJECT_ID por el ID de tu proyecto. Google Cloud
    • REPOSITORY con el nombre del repositorio de Artifact Registry.
    • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

    pubsub es el nombre de la imagen.

    Si la operación se realiza correctamente, verás un mensaje de ÉXITO que contiene el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y se puede volver a usar si es necesario.

    Java

    • Usa el asistente de credenciales de la CLI de gcloud para autorizar a Docker a enviar contenido a tu Artifact Registry.
      gcloud auth configure-docker
    • Usa el complemento Jib Maven para compilar y enviar el contenedor a Artifact Registry.
      mvn compile jib:build -D image=REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
      Reemplazar:
      • PROJECT_ID por el ID de tu proyecto. Google Cloud
      • REPOSITORY con el nombre del repositorio de Artifact Registry.
      • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

      pubsub es el nombre de la imagen.

      Si todo va bien, debería aparecer el mensaje BUILD SUCCESS. La imagen se almacena en Artifact Registry y se puede volver a usar si es necesario.

    C#

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
    Reemplazar:
    • PROJECT_ID por el ID de tu proyecto. Google Cloud
    • REPOSITORY con el nombre del repositorio de Artifact Registry.
    • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

    pubsub es el nombre de la imagen.

    Si la operación se realiza correctamente, verás un mensaje de ÉXITO que contiene el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y se puede volver a usar si es necesario.

  2. Despliega tu aplicación:

    Línea de comandos

    1. Ejecuta el siguiente comando para implementar tu aplicación:

      gcloud run deploy pubsub-tutorial --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub  --no-allow-unauthenticated
      Reemplazar:
      • PROJECT_ID por el ID de tu proyecto. Google Cloud
      • REPOSITORY con el nombre del repositorio de Artifact Registry.
      • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

      pubsub es el nombre de la imagen y pubsub-tutorial es el nombre del servicio. Verás que la imagen del contenedor se ha desplegado en el servicio y la región que configuraste anteriormente en Configurar gcloud.

      La marca --no-allow-unauthenticated restringe el acceso no autenticado al servicio. Si mantienes el servicio privado, puedes confiar en la integración automática de Pub/Sub de Cloud Run para autenticar las solicitudes. Consulta Integrar con Pub/Sub para obtener más información sobre cómo se configura. Para obtener más información sobre la autenticación basada en la gestión de identidades y accesos, consulta Gestionar el acceso con la gestión de identidades y accesos.

      Espera a que se complete el despliegue, que puede tardar aproximadamente medio minuto. Si la acción se realiza correctamente, la línea de comandos mostrará la URL del servicio. Esta URL se usa para configurar una suscripción de Pub/Sub.

    2. Si quieres implementar una actualización de código en el servicio, repite los pasos anteriores. Cada despliegue en un servicio crea una revisión y empieza a servir tráfico automáticamente cuando está listo.

    Terraform

    Para crear un servicio de Cloud Run, añade lo siguiente al archivo .tf que ya tengas.

    resource "google_project_service" "cloudrun_api" {
       service            = "run.googleapis.com"
       disable_on_destroy = false
    }
    
    resource "google_cloud_run_v2_service" "default" {
       name     = "pubsub-tutorial"
       location = "REGION"
    
       template {
          containers {
             image = "IMAGE_URL"
         }
       }
       depends_on = [google_project_service.cloudrun_api]
    }
             
    Reemplazar:
    • IMAGE_URL con la URL de la imagen: REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/pubsub
    • REGION con la Google Cloud región que se va a usar en el repositorio de Artifact Registry.

Integrar con Pub/Sub

Para integrar el servicio con Pub/Sub, sigue estos pasos:

gcloud

  1. Crea o selecciona una cuenta de servicio que represente la identidad de la suscripción de Pub/Sub.

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

    Puedes usar cloud-run-pubsub-invoker o sustituirlo por un nombre único en tu proyecto. Google Cloud

  2. Crea una suscripción de Pub/Sub con la cuenta de servicio:

    1. Da permiso a la cuenta de servicio invocadora para invocar tu servicio pubsub-tutorial:

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

      Los cambios de IAM pueden tardar varios minutos en propagarse. Mientras tanto, es posible que veas errores HTTP 403 en los registros de servicio.

    2. Permite que Pub/Sub cree tokens de autenticación en tu proyecto:

      gcloud projects add-iam-policy-binding PROJECT_ID \
         --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \
         --role=roles/iam.serviceAccountTokenCreator

      Sustituye:

      • PROJECT_ID por el ID de tu proyecto. Google Cloud
      • PROJECT_NUMBER con el número de tu proyecto Google Cloud .

      El ID y el número de proyecto se indican en el panel Información del proyecto de la Google Cloud consola de tu proyecto.

    3. Crea una suscripción de Pub/Sub con la cuenta de servicio:

      gcloud pubsub subscriptions create myRunSubscription --topic myRunTopic \
      --ack-deadline=600 \
      --push-endpoint=SERVICE-URL/ \
      --push-auth-service-account=cloud-run-pubsub-invoker@PROJECT_ID.iam.gserviceaccount.com

      Sustituye:

      La marca --push-auth-service-account activa la función de inserción de Pub/Sub para la autenticación y la autorización.

      El dominio de tu servicio de Cloud Run se registra automáticamente para usarlo con suscripciones de Pub/Sub.

      En Cloud Run, solo se realiza una comprobación de autenticación integrada para verificar que el token sea válido y una comprobación de autorización para comprobar que la cuenta de servicio tiene permiso para invocar el servicio de Cloud Run.

Tu servicio ahora está totalmente integrado con Pub/Sub.

Terraform

  1. Crea o selecciona una cuenta de servicio que represente la identidad de la suscripción de Pub/Sub.

    resource "google_service_account" "sa" {
      account_id   = "cloud-run-pubsub-invoker"
      display_name = "Cloud Run Pub/Sub Invoker"
    }
  2. Crea una suscripción de Pub/Sub con la cuenta de servicio:

    1. Da permiso a la cuenta de servicio invocadora para invocar tu servicio pubsub-tutorial:

      resource "google_cloud_run_service_iam_binding" "binding" {
        location = google_cloud_run_v2_service.default.location
        service  = google_cloud_run_v2_service.default.name
        role     = "roles/run.invoker"
        members  = ["serviceAccount:${google_service_account.sa.email}"]
      }
    2. Permite que Pub/Sub cree tokens de autenticación en tu proyecto:

      resource "google_project_service_identity" "pubsub_agent" {
        provider = google-beta
        project  = data.google_project.project.project_id
        service  = "pubsub.googleapis.com"
      }
      
      resource "google_project_iam_binding" "project_token_creator" {
        project = data.google_project.project.project_id
        role    = "roles/iam.serviceAccountTokenCreator"
        members = ["serviceAccount:${google_project_service_identity.pubsub_agent.email}"]
      }
    3. Crea una suscripción de Pub/Sub con la cuenta de servicio:

      resource "google_pubsub_subscription" "subscription" {
        name  = "pubsub_subscription"
        topic = google_pubsub_topic.default.name
        push_config {
          push_endpoint = google_cloud_run_v2_service.default.uri
          oidc_token {
            service_account_email = google_service_account.sa.email
          }
          attributes = {
            x-goog-version = "v1"
          }
        }
        depends_on = [google_cloud_run_v2_service.default]
      }

Tu servicio ahora está totalmente integrado con Pub/Sub.

Pruébalo

Para probar la solución integral, sigue estos pasos:

  1. Envía un mensaje de Pub/Sub al tema:

    gcloud pubsub topics publish myRunTopic --message "Runner"

    También puedes publicar mensajes de forma programática en lugar de usar la línea de comandos, como se muestra en este tutorial. Para obtener más información, consulta Publicar mensajes.

  2. Ve a los registros del servicio:

    1. Ve a la Google Cloud consola.
    2. Haz clic en el servicio pubsub-tutorial.
    3. Selecciona la pestaña Registros.

      Puede que los registros tarden unos instantes en aparecer. Si no los ves inmediatamente, vuelve a comprobarlo al cabo de unos instantes.

  3. Busca el mensaje "Hello Runner!".