Línea de comandos de gcloud dentro de un instructivo de servicio de Cloud Run


En este instructivo, crearás un inventario de los servicios de Cloud Run mediante Google Cloud CLI dentro de un servicio de Cloud Run. Puedes aplicar lo que aprendes en este instructivo a las secuencias de comandos de operaciones de Cloud existentes o crear una prueba de concepto antes de usar las bibliotecas cliente para compilar un servicio más sólido.

Usa gcloud CLI como cualquier secuencia de comandos de shell dentro de un servicio web, por ejemplo, como se muestra en la guía de inicio rápido de Shell. En Cloud Run, ambas herramientas funcionan con los servicios de Google Cloud mediante la autenticación automática con la identidad del servicio de Cloud Run. Cualquier permiso otorgado a la identidad del servicio está disponible para la CLI de gcloud.

Las capacidades de la CLI de gcloud de recopilar información y administrar recursos en Google Cloud son tan amplias que el desafío de usarla dentro de un servicio web es minimizar el riesgo de que un emisor use de forma inadecuada estas capacidades. Sin los controles de seguridad, podrías generar riesgos para otros servicios o recursos que se ejecutan en el mismo proyecto, ya que permite actividad maliciosa accidental o intencional. Algunos ejemplos de riesgos son los siguientes:

  • Habilitar el descubrimiento de direcciones IP de máquinas virtuales privadas
  • Habilitar el acceso a los datos privados desde una base de datos en el mismo proyecto
  • Habilitar la eliminación de otros servicios en ejecución

En varios pasos de este instructivo, se muestra cómo imponer controles para minimizar los riesgos, como especificar el comando gcloud que se ejecutará en el código, en lugar de dejarlo abierto como una entrada del usuario.

Las secuencias de comandos con la herramienta de línea de comandos dentro de un servicio de Cloud Run son similares a usar la línea de comandos de manera local. La principal diferencia son las restricciones adicionales que debes agregar en torno a la lógica de la secuencia de comandos principal.

Objetivos

  • Escribir y compilar un contenedor personalizado con un Dockerfile
  • Escribir, compilar e implementar un servicio de Cloud Run
  • Usa gcloud CLI de forma segura en un servicio web
  • Genera un informe de los servicios de Cloud Run y guárdalo en Cloud Storage

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Antes de comenzar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. Enable the Artifact Registry, Cloud Build, Cloud Run, and Cloud Storage APIs.

    Enable the APIs

  7. Instala e inicializa la CLI de gcloud

Roles obligatorios

Si quieres obtener los permisos que necesitas para completar el instructivo, pídele a tu administrador que te otorgue los siguientes roles de IAM en tu proyecto:

Para obtener más información sobre cómo otorgar roles, consulta Administra el acceso a proyectos, carpetas y organizaciones.

También puedes obtener los permisos necesarios mediante roles personalizados o cualquier otro rol predefinido.

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. Configura gcloud en la región que elegiste:

    gcloud config set run/region REGION

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

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

Sujetas 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 (India)
  • australia-southeast1 (Sídney)
  • australia-southeast2 (Melbourne)
  • europe-central2 (Varsovia, Polonia)
  • europe-west10 (Berlín) ícono de hoja Bajo nivel de CO2
  • europe-west12 (Turín)
  • europe-west2 (Londres, Reino Unido) ícono de hoja Bajo nivel de CO2
  • europe-west3 (Fráncfort, Alemania) ícono de hoja Bajo nivel de CO2
  • europe-west6 (Zúrich, Suiza) ícono de hoja Bajo nivel de CO2
  • me-central1 (Doha)
  • me-central2 (Dammam)
  • northamerica-northeast1 (Montreal) ícono de hoja Bajo nivel de CO2
  • northamerica-northeast2 (Toronto) ícono de hoja Bajo nivel de CO2
  • southamerica-east1 (São Paulo, Brasil) ícono de hoja Bajo nivel de CO2
  • southamerica-west1 (Santiago, Chile) ícono de hoja Bajo nivel de CO2
  • us-west2 (Los Ángeles)
  • us-west3 (Salt Lake City)
  • us-west4 (Las Vegas)

Si ya creaste un servicio de Cloud Run, puedes ver la región en el panel de Cloud Run en la consola de Google 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:

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples.git

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

  2. Ve al directorio que contiene el código de muestra de Cloud Run:

    cd cloud-run-samples/gcloud-report/

Revisa el código

En esta sección, se incluye información sobre la muestra de código que recuperaste.

Genera un informe y súbelo a Cloud Storage

Esta secuencia de comandos de shell genera un informe de los servicios de Cloud Run en el proyecto y la región actuales, y sube el resultado a Cloud Storage. Enumera los servicios cuyo nombre contiene el argumento search de string proporcionado.

La secuencia de comandos usa el comando gcloud run services list, las opciones de formato avanzadas de gcloud y el modo de copia de transferencia de transmisión de gcloud.

set -eo pipefail

# Check for required environment variables.
requireEnv() {
  test "${!1}" || (echo "gcloud-report: '$1' not found" >&2 && exit 1)
}
requireEnv GCLOUD_REPORT_BUCKET

# Prepare formatting: Default search term to include all services.
search=${1:-'.'}
limits='spec.template.spec.containers.resources.limits.flatten("", "", " ")'
format='table[box, title="Cloud Run Services"](name,status.url,metadata.annotations.[serving.knative.dev/creator],'${limits}')'

# Create a specific object name that will not be overridden in the future.
obj="gs://${GCLOUD_REPORT_BUCKET}/report-${search}-$(date +%s).txt"

# Write a report containing the service name, service URL, service account or user that
# deployed it, and any explicitly configured service "limits" such as CPU or Memory.
gcloud run services list \
  --format "${format}" \
  --filter "metadata.name~${search}" | gsutil -q cp -J - "${obj}"

# /dev/stderr is sent to Cloud Logging.
echo "gcloud-report: wrote to ${obj}" >&2
echo "Wrote report to ${obj}"

Esta secuencia de comandos es segura para ejecutarse como un servicio porque las invocaciones repetidas actualizan el informe sin más deserción costosa. Otras secuencias de comandos que usan la CLI de gcloud pueden ser más costosas cuando se invocan de manera repetida, como crear recursos nuevos de Cloud o realizar tareas costosas. Las secuencias de comandos idempotentes, que producen el mismo resultado en invocaciones repetidas, son más seguras de ejecutar como servicio.

Invoca la secuencia de comandos en la solicitud HTTP

Este código de Go configura un servicio web que ejecuta una secuencia de comandos de shell para generar un informe. Dado que la búsqueda es una entrada del usuario, el código la valida para garantizar que solo contenga letras, números o guiones a fin de evitar comandos de entrada maliciosos. Este conjunto de caracteres es lo suficientemente pequeño como para evitar ataques de inyección de comandos.

El servicio web pasa el parámetro de búsqueda como un argumento a la secuencia de comandos de shell.


// Service gcloud-report is a Cloud Run shell-script-as-a-service.
package main

import (
	"log"
	"net/http"
	"os"
	"os/exec"
	"regexp"
)

func main() {
	http.HandleFunc("/", scriptHandler)

	// 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)
	}
}

func scriptHandler(w http.ResponseWriter, r *http.Request) {
	search := r.URL.Query().Get("search")
	re := regexp.MustCompile(`^[a-z]+[a-z0-9\-]*$`)
	if !re.MatchString(search) {
		log.Printf("invalid search criteria %q, using default", search)
		search = "."
	}

	cmd := exec.CommandContext(r.Context(), "/bin/bash", "script.sh", search)
	cmd.Stderr = os.Stderr
	out, err := cmd.Output()
	if err != nil {
		log.Printf("Command.Output: %v", err)
		http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
		return
	}
	w.Write(out)
}

Un archivo go.mod declara las dependencias de la aplicación en un módulo de Go:

module github.com/GoogleCloudPlatform/cloud-run-samples/gcloud-report

go 1.19

Define el entorno del contenedor

El Dockerfile define cómo se reúne el entorno para el servicio. Es similar al Dockerfile de la guía de inicio rápido de helloworld-shell, pero la imagen final del contenedor se basa en la imagen de Google Cloud CLI de gcloud. Esto permite que tu servicio use gcloud sin pasos de instalación y configuración personalizados para Google Cloud CLI.


# Use the official 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.20-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 invoke.go ./

# Build the binary.
RUN go build -mod=readonly -v -o server

# Use a gcloud image based on debian:buster-slim for a lean production container.
# https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds
FROM gcr.io/google.com/cloudsdktool/cloud-sdk:slim

WORKDIR /app

# Copy the binary to the production image from the builder stage.
COPY --from=builder /app/server /app/server
COPY *.sh /app/
RUN chmod +x /app/*.sh

# Run the web service on container startup.
CMD ["/app/server"]

Crea 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

Reemplaza lo siguiente:

  • REPOSITORY por un nombre único para el repositorio.
  • REGION por la región de Google Cloud de Artifact Registry.

Configura el bucket de Cloud Storage

Crea un bucket de Cloud Storage para subir informes:

gcloud storage buckets create gs://REPORT_ARCHIVE_BUCKET

Reemplaza REPORT_ARCHIVE_BUCKET por un nombre de bucket único a nivel global.

Configura la identidad del servicio

Para limitar los privilegios que el servicio tiene por sobre otra infraestructura, crea una identidad de servicio y personaliza los permisos de IAM específicos necesarios para el trabajo.

En este caso, los privilegios necesarios son permiso para leer los servicios de Cloud Run y permiso para leer y escribir en el bucket de Cloud Storage.

  1. Crea una cuenta de servicio:

    gcloud iam service-accounts create gcloud-report-identity

  2. Otorga permiso a la cuenta de servicio para leer los servicios de Cloud Run:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role roles/run.viewer
  3. Otorga permiso a la cuenta de servicio para leer y escribir en el bucket de Cloud Storage:

    gcloud storage buckets add-iam-policy-binding gs://REPORT_ARCHIVE_BUCKET \
      --member=serviceAccount:gcloud-report-identity@PROJECT_ID.iam.gserviceaccount.com \
      --role=roles/storage.objectUser

El acceso limitado de esta identidad del servicio personalizado evita que el servicio acceda a otros recursos de Google Cloud.

Envía el servicio

El código de envío consta de tres pasos:

  • Compila una imagen de contenedor con Cloud Build
  • Carga la imagen del contenedor a Artifact Registry.
  • Implementa la imagen de contenedor en Cloud Run

Para enviar el código, haz lo siguiente:

  1. Compila el contenedor y publica en Artifact Registry:

    gcloud builds submit --tag REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report

    Reemplaza lo siguiente:

    • PROJECT_ID por el ID del proyecto de Google Cloud
    • REPOSITORY por el nombre del repositorio de Artifact Registry
    • REGION por la región de Google Cloud de Artifact Registry.

    gcloud-report es el nombre del servicio.

    Si la operación se completa de manera correcta, aparecerá un mensaje de SUCCESS con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y puede volver a usarse si es necesario.

  2. Ejecuta el comando siguiente para implementar tu servicio:

    gcloud run deploy gcloud-report \
       --image REGION-docker.pkg.dev/PROJECT_ID/REPOSITORY/gcloud-report \
       --update-env-vars GCLOUD_REPORT_BUCKET=REPORT_ARCHIVE_BUCKET \
       --service-account gcloud-report-identity \
       --no-allow-unauthenticated

    Reemplaza lo siguiente:

    • PROJECT_ID por el ID del proyecto de Google Cloud.
    • REPOSITORY por el nombre del repositorio de Artifact Registry
    • REGION por la región de Google Cloud del servicio.

    gcloud-report es parte del nombre del contenedor y el nombre del servicio. La imagen de contenedor se implementa en el servicio y la región (Cloud Run) que configuraste antes en Configura gcloud.

    La marca --no-allow-unauthenticated restringe el acceso no autenticado al servicio. Si mantienes el servicio privado, puedes confiar en la autenticación integrada de Cloud Run para bloquear las solicitudes no autorizadas. Para obtener más detalles sobre la autenticación basada en la Identity and Access Management (IAM), consulta Administra el acceso mediante la IAM.

    Espera hasta que se complete 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.

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

Consulta Cómo administrar el acceso mediante IAM para saber cómo otorgar acceso a los usuarios de Google Cloud a fin de invocar este servicio. Los editores y propietarios del proyecto tienen este acceso de forma automática.

Genera un informe

Para generar un informe de los servicios de Cloud Run, sigue estos pasos:

  1. Usa curl para enviar una solicitud autenticada:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL

    Reemplaza SERVICE_URL por la URL que proporciona Cloud Run después de completar la implementación.

    Si creaste un proyecto nuevo y seguiste este instructivo, el resultado será similar a lo siguiente:

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-.-DATE.txt

    El . en el nombre de archivo es el argumento de búsqueda predeterminado, como se menciona en el código fuente.

    Para usar la función de búsqueda, agrega un argumento search a la solicitud:

    curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" SERVICE_URL?search=gcloud

    Esta consulta mostrará un resultado similar al siguiente:

    Wrote report to gs://REPORT_ARCHIVE_BUCKET/report-gcloud-DATE.txt
  2. Recupera el archivo con gcloud CLI de forma local:

    gcloud storage cp gs://REPORT_FILE_NAME .

    El . en el comando significa el directorio de trabajo actual.

    Reemplaza REPORT_FILE_NAME por el resultado del nombre del objeto de Cloud Storage en el paso anterior.

Abre el archivo para ver el informe. Se verá de la siguiente manera:

Captura de pantalla de la lista de servicios de Cloud Run en el proyecto con columnas para cuatro atributos de servicio.
Las cuatro columnas se extraen de la descripción del servicio. Incluyen el Nombre del servicio, la URL asignada en la primera implementación, el Creador inicial del servicio y los Límites del servicio de CPU y memoria máximas.

Mejora la solidez para el futuro

Si planeas desarrollar este servicio de forma más detallada, considera volver a escribir en un lenguaje de programación más flexible y usar la API de Admin de Cloud Run y la biblioteca cliente de Cloud Storage.

Para examinar las llamadas que se realizan a la API (y ver algunos detalles de autenticación), puedes agregar --log-http a los comandos de gcloud CLI.

Automatiza esta operación

Ahora que el informe de los servicios de Cloud Run se puede activar con una solicitud HTTP, usa la automatización para generar informes cuando los necesites:

Limpia

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. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

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 la consola de Google Cloud.

  2. Quita la configuración de región predeterminada de gcloud que agregaste durante la configuración en el instructivo:

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

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

¿Qué sigue?