Instructivo de uso de Pub/Sub con Cloud Run

En este instructivo, se muestra cómo escribir un servicio de Cloud Run desde una suscripción de envío a Pub/Sub, cómo implementarlo y cómo llamarlo.

Puedes usar este instructivo con Cloud Run (completamente administrado) o Cloud Run for Anthos en Google Cloud.

Objetivos

  • Escribir, compilar y, también, implementar un servicio en Cloud Run o Cloud Run for Anthos en Google Cloud
  • Llamar al servicio mediante la publicación de un mensaje en un tema de Pub/Sub

Costos

En este instructivo, se usan componentes facturables de Google Cloud, que incluyen lo siguiente:

Usa la calculadora de precios para generar una estimación de los costos según el uso previsto.

Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Antes de comenzar

  1. Accede a tu Cuenta de Google.

    Si todavía no tienes una cuenta, regístrate para obtener una nueva.

  2. En la página de selección de proyectos de Cloud Console, selecciona o crea un proyecto de Cloud.

    Ir a la página Selector de proyectos

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud. Obtén información sobre cómo confirmar que tienes habilitada la facturación para tu proyecto.

  4. Habilita la API de Cloud Run
  5. Instala y, luego, inicializa el SDK de Cloud.
  6. Para Cloud Run for Anthos en Google Cloud, instala el componente gcloud kubectl:
    gcloud components install kubectl
  7. Actualiza los componentes:
    gcloud components update
  8. Si usas Cloud Run for Anthos en Google Cloud, crea un clúster nuevo según las instrucciones de Configura Cloud Run for Anthos en Google Cloud.

Configura los valores predeterminados de gcloud

A fin de configurar gcloud con los valores predeterminados para el servicio de Cloud Run, sigue estos pasos:

  1. Configura el proyecto predeterminado:

    gcloud config set project PROJECT_ID

    Reemplaza PROJECT_ID por el nombre del proyecto que creaste para este instructivo.

  2. Si usas Cloud Run (completamente administrado), configura gcloud para la región que elegiste:

    gcloud config set run/region REGION

    Reemplaza REGION por la región de Cloud Run compatible que prefieras.

  3. Si usas Cloud Run for Anthos en Google Cloud, configura gcloud para el clúster:

    gcloud config set run/cluster CLUSTER-NAME
    gcloud config set run/cluster_location REGION

    Reemplaza los siguientes elementos:

    • CLUSTER-NAME por el nombre que usaste para el clúster
    • REGION por la ubicación de clúster compatible que elijas

Ubicaciones de Cloud Run

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

El cumplimiento de los requisitos de latencia, disponibilidad o durabilidad es el factor principal para seleccionar la región en la que se ejecutan los servicios de Cloud Run. Por lo general, puedes seleccionar la región más cercana a los usuarios, pero debes considerar la ubicación de los otros productos de Google Cloud que usa el servicio de Cloud Run. Si usas productos de Google Cloud en varias ubicaciones, la latencia y el costo del servicio pueden verse afectados.

Cloud Run está disponible en las siguientes regiones:

Sujetas a los Precios del nivel 1

  • asia-east1 (Taiwán)
  • asia-northeast1 (Tokio)
  • asia-northeast2 (Osaka)
  • europe-north1 (Finlandia)
  • europe-west1 (Bélgica)
  • europe-west4 (Países Bajos)
  • us-central1 (Iowa)
  • us-east1 (Carolina del Sur)
  • us-east4 (Virginia del Norte)
  • us-west1 (Oregón)

Sujetas a los Precios del nivel 2

  • asia-east2 (Hong Kong)
  • asia-northeast3 (Seúl, Corea del Sur)
  • asia-southeast1 (Singapur)
  • asia-southeast2 (Yakarta)
  • asia-south1 (Bombay, India)
  • australia-southeast1 (Sídney)
  • europe-west2 (Londres, Reino Unido)
  • europe-west3 (Fráncfort, Alemania)
  • europe-west6 (Zúrich, Suiza)
  • northamerica-northeast1 (Montreal)
  • southamerica-east1 (São Paulo, Brasil)

Si ya creaste un servicio de Cloud Run, puedes ver la región en el panel de Cloud Run en Cloud Console.

Crea un tema de Pub/Sub

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

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

gcloud pubsub topics create myRunTopic

Puedes usar myRunTopic o reemplazar por un nombre de tema único dentro de tu proyecto de Cloud.

Recupera la muestra de código

A fin de recuperar la muestra de código para su uso, haz lo siguiente:

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

    Node.js

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

    Python

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

    Go

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

    De manera opcional, puedes descargar la muestra como un archivo ZIP y extraerla.

    Java

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

    De manera alternativa, puedes descargar la muestra como un archivo ZIP y extraerla.

  2. Ve al directorio que contiene el código de muestra 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/

Observa el código

El código de este instructivo consta de los siguientes elementos:

  • Un servidor que maneja las solicitudes entrantes

    Node.js

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

    El servidor web de Node.js está configurado en app.js.

    const express = require('express');
    const bodyParser = require('body-parser');
    const app = express();
    
    app.use(bodyParser.json());
    El servidor web se inicia en 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}`)
    );

    Python

    import base64
    import os
    
    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/ioutil"
    	"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);
      }
    }

  • 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():
        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

    
    // PubSubMessage is the payload of a Pub/Sub event.
    type PubSubMessage 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 PubSubMessage
    	body, err := ioutil.ReadAll(r.Body)
    	if err != nil {
    		log.Printf("ioutil.ReadAll: %v", err)
    		http.Error(w, "Bad Request", http.StatusBadRequest)
    		return
    	}
    	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 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 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);
      }
    }

    Debes codificar el servicio para mostrar un código de respuesta HTTP preciso. Los códigos de éxito, como HTTP 200204, confirman la recepción del procesamiento completo del mensaje de Pub/Sub. Los códigos de error, como HTTP 400500, indican que se volverá a intentar enviar el mensaje, como se describe en la Guía de recepción de mensajes mediante suscripciones de envío.

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

    Node.js

    
    # Use the official lightweight Node.js 10 image.
    # https://hub.docker.com/_/node
    FROM node:12-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 add a package-lock.json speed your build by switching to 'npm ci'.
    # RUN npm ci --only=production
    RUN npm install --production
    
    # 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.9
    
    # 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.
    CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
    

    Go

    
    # Use the offical golang image to create a binary.
    # This is based on Debian and sets the GOPATH to /go.
    # https://hub.docker.com/_/golang
    FROM golang:1.13-buster 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 -mod=readonly -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:buster-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 esta muestra, se usa Jib para compilar imágenes de Docker mediante herramientas de Java comunes. Jib optimiza las compilaciones de contenedores sin la necesidad de tener un Dockerfile o tener Docker instalado. Obtén más información sobre cómo compilar contenedores de Java con Jib.
    <plugin>
      <groupId>com.google.cloud.tools</groupId>
      <artifactId>jib-maven-plugin</artifactId>
      <version>2.6.0</version>
      <configuration>
        <to>
          <image>gcr.io/PROJECT_ID/pubsub</image>
        </to>
      </configuration>
    </plugin>
    

Para obtener detalles sobre cómo autenticar el origen de las solicitudes de Pub/Sub, lee la siguiente sección sobre Integración en Pub/Sub.

Envía el código

El código de envío consta de tres pasos: compilar una imagen de contenedor con Cloud Build, subir la imagen de contenedor a Container Registry y, luego, implementar la imagen de contenedor en Cloud Run o Cloud Run for Anthos en Google Cloud.

Para enviar el código, haz lo siguiente:

  1. Compila el contenedor y publica en Container Registry:

    Node.js

    gcloud builds submit --tag gcr.io/PROJECT_ID/pubsub

    En el que PROJECT_ID es el ID del proyecto de Cloud y pubsub es el nombre que deseas darle a tu servicio.

    Si la operación se completa de manera correcta, deberías ver un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y puede volver a usarse si así se desea.

    Python

    gcloud builds submit --tag gcr.io/PROJECT_ID/pubsub

    En el que PROJECT_ID es el ID del proyecto de Cloud y pubsub es el nombre que deseas darle a tu servicio.

    Si la operación se completa de manera correcta, deberías ver un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y puede volver a usarse si así se desea.

    Go

    gcloud builds submit --tag gcr.io/PROJECT_ID/pubsub

    En el que PROJECT_ID es el ID del proyecto de Cloud y pubsub es el nombre que deseas darle a tu servicio.

    Si la operación se completa de manera correcta, deberías ver un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Container Registry y puede volver a usarse si así se desea.

    Java

    mvn compile jib:build -Dimage=gcr.io/PROJECT_ID/pubsub

    En el que PROJECT_ID es el ID del proyecto de Cloud y pubsub es el nombre que deseas darle a tu servicio.

    Si se ejecuta de forma correcta, deberías ver un mensaje de COMPILACIÓN EXITOSA. La imagen se almacena en Container Registry y puede volver a usarse si así se desea.

  2. Ejecuta el comando siguiente para implementar tu app:

    gcloud run deploy pubsub-tutorial --image gcr.io/PROJECT_ID/pubsub

    Reemplaza PROJECT_ID por tu ID del proyecto de Cloud. pubsub es el nombre del contenedor y pubsub-tutorial es el nombre del servicio. Ten en cuenta que la imagen del contenedor se implementa en el servicio y la región (Cloud Run) o el clúster (Cloud Run for Anthos en Google Cloud) que configuraste antes en Configura gcloud.

    Si implementas en Cloud Run, responde n, “No”, a la solicitud “Permitir sin autenticación”. Si mantienes el servicio privado, puedes confiar en la integración automática de Pub/Sub de Cloud Run para autenticar las solicitudes. Consulta Integra en Pub/Sub para obtener más detalles sobre cómo se configura. Para obtener más detalles sobre la autenticación basada en la administración de identidades y accesos (IAM), consulta Administra el acceso mediante la IAM.

    Espera hasta que finalice la implementación; esto puede tomar alrededor de medio minuto. Si la operación se completa de forma correcta, la línea de comandos mostrará la URL de servicio. Esta URL se usa para configurar una suscripción a Pub/Sub.

  3. Si deseas implementar una actualización de código en el servicio, repite los pasos anteriores. Con cada implementación en un servicio se crea una revisión nueva y se comienza a entregar tráfico de manera automática cuando está lista.

Integra en Pub/Sub

Ahora que implementamos nuestro servicio de Cloud Run, configuraremos Pub/Sub para enviarle mensajes.

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

  1. Habilita Pub/Sub para crear 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

    Reemplaza

    • PROJECT_ID por tu ID del proyecto de Cloud
    • PROJECT-NUMBER por el número de tu proyecto de Cloud
  2. Crea o selecciona una cuenta de servicio para representar la identidad de suscripción a 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 reemplazar con un nombre único dentro de tu proyecto de Cloud.

  3. Crea una suscripción a Pub/Sub con la cuenta de servicio; para ello, consulta la pestaña correspondiente según si usas Cloud Run o Cloud Run for Anthos en Google Cloud.

    Cloud Run

    1. Usa este comando para permitir que la cuenta de servicio invoque el 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

      Es posible que los cambios de IAM tomen varios minutos en propagarse. Mientras tanto, puede que veas errores HTTP 403 en los registros del servicio.

    2. Usa este comando para crear una suscripción a  Pub/Sub con la cuenta de servicio:

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

      Reemplaza los siguientes elementos:

      La marca --push-auth-service-account activa las funciones de envío de Pub/Sub para la autenticación y la autorización.

      Tu dominio del servicio de Cloud Run se registra de manera automática para que se use con las suscripciones a Pub/Sub.

      Solo para Cloud Run, hay una verificación de autenticación integrada de que el token sea válido y una verificación de autorización de que la cuenta de servicio tenga permiso para invocar el servicio de Cloud Run.

    Cloud Run for Anthos

    1. Habilita HTTPS y TLS automáticos para tu clúster y agrega una asignación de dominio a tu servicio.

    2. Registra la propiedad del dominio de Pub/Sub.

    3. Agrega código para validar el token de autenticación adjunto a los mensajes de Pub/Sub. El código de muestra se proporciona en Autenticación y autorización por parte del extremo de envío.

      La autenticación debe garantizar que el token sea válido y esté asociado con la cuenta de servicio prevista. A diferencia de Cloud Run (completamente administrado), Cloud Run for Anthos en Google Cloud no tiene una verificación de autorización integrada de que el token sea válido o de que la cuenta de servicio tenga autorización para invocar el servicio de Cloud Run for Anthos en Google Cloud.

    4. Usa este comando para crear una suscripción a Pub/Sub con la cuenta de servicio:

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

      Reemplaza los siguientes elementos:

      • myRunTopic por el tema que creaste antes
      • SERVICE-URL por la URL de tu servicio personalizado. Especifica https como el protocolo.
      • PROJECT_ID por tu ID del proyecto de Cloud

      La marca --push-auth-service-account activa las funciones de envío de Pub/Sub para la autenticación y la autorización.

Tu servicio ahora está completamente integrado en Pub/Sub.

Haz una prueba

Para probar la solución de extremo a extremo, 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 manera programática en lugar de usar la línea de comandos como se muestra en este instructivo. Para obtener más información, consulta Publica mensajes.

  2. Navega a los registros de servicio:

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

      Los registros pueden tomar un tiempo en aparecer. Si no los ves de inmediato, vuelve a revisar en unos minutos.

  3. Busca el mensaje “Hello Runner!”.

Realiza una limpieza

Para revisar un caso práctico más detallado del uso de Cloud Run con Pub/Sub, omite la limpieza por ahora y continúa con el Instructivo de procesamiento de imágenes con Cloud Run.

Si creaste un proyecto nuevo para este instructivo, bórralo. Si usaste un proyecto existente y deseas conservarlo sin los cambios que se agregaron en este instructivo, borra los recursos creados para el instructivo.

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, sigue estos pasos:

  1. En Cloud Console, ve a la página Administrar recursos.

    Ir a la página Administrar recursos

  2. En la lista de proyectos, selecciona el proyecto que deseas borrar y haz clic en Borrar .
  3. En el cuadro de diálogo, escribe el ID del proyecto y haz clic en Cerrar para borrar el proyecto.

Borra los recursos del instructivo

  1. Usa este comando para borrar el servicio de Cloud Run que implementaste en este instructivo:

    gcloud run services delete SERVICE-NAME

    En el ejemplo anterior, SERVICE-NAME es el nombre del servicio que elegiste.

    También puedes borrar los servicios de Cloud Run desde Google Cloud Console.

  2. Quita las opciones de configuración predeterminadas de gcloud que agregaste durante la configuración del instructivo.

    Si usas Cloud Run (completamente administrado), quita la configuración de la región:

     gcloud config unset run/region
    

    Si usas Cloud Run for Anthos en Google Cloud, quita la configuración del clúster:

     gcloud config unset run/cluster run/cluster
     gcloud config unset run/cluster run/cluster_location
    
  3. Quita la configuración del proyecto:

     gcloud config unset project
    
  4. Borra otros recursos de Google Cloud que creaste en este instructivo:

Próximos pasos