Tutorial sobre la línea de comandos gcloud dentro de un servicio de Cloud Run

En este tutorial, crearás un inventario de servicios de Cloud Run con la CLI de Google Cloud dentro de un servicio de Cloud Run. Puedes aplicar lo que aprendas en este tutorial a tus secuencias de comandos de operaciones de Cloud o crear una prueba de concepto antes de usar bibliotecas de cliente para crear un servicio más sólido.

Puedes usar la CLI de gcloud como cualquier secuencia de comandos de shell dentro de un servicio web, como se muestra en la guía de inicio rápido de Shell. En Cloud Run, ambas herramientas funcionan con servicios Google Cloud autenticándose automáticamente con la identidad de servicio de Cloud Run. La CLI de gcloud tiene acceso a todos los permisos que se hayan concedido a la identidad de servicio.

La CLI de gcloud es capaz de recopilar información y gestionar recursos en Google Cloud , por lo que el reto de usarla en un servicio web es minimizar el riesgo de que un llamante haga un uso inadecuado de estas funciones. Si no se aplican controles de seguridad, se podría poner en riesgo otros servicios o recursos que se ejecuten en el mismo proyecto al permitir actividades maliciosas accidentales o intencionadas. Estos son algunos ejemplos de estos riesgos:

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

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

Crear secuencias de comandos con la herramienta de línea de comandos dentro de un servicio de Cloud Run es similar a usar la línea de comandos de forma local. La principal diferencia son las restricciones adicionales que debes añadir en torno a la lógica de la secuencia de comandos principal.

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.

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:

    git clone https://github.com/GoogleCloudPlatform/cloud-run-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:

    cd cloud-run-samples/gcloud-report/

Revisar el código

En esta sección se incluye información sobre el código de muestra que has obtenido.

Generar un informe y subirlo a Cloud Storage

Este script de shell genera un informe de los servicios de Cloud Run del proyecto y la región actuales, y sube el resultado a Cloud Storage. Muestra los servicios cuyo nombre contiene el argumento de cadena search proporcionado.

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

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}"

Este script se puede ejecutar de forma segura como servicio porque las invocaciones repetidas del mismo actualizan el informe sin que se produzcan más cambios costosos. Otras secuencias de comandos que usan la CLI de gcloud pueden ser más costosas si se invocan repetidamente, como crear recursos de Cloud o realizar tareas costosas. Los scripts idempotentes, que dan el mismo resultado en invocaciones repetidas, son más seguros para ejecutarse como servicio.

Invocar la secuencia de comandos en una solicitud HTTP

Este código de Go configura un servicio web que ejecuta una secuencia de comandos shell para generar un informe. Como la consulta de búsqueda es una entrada del usuario, el código la valida para asegurarse de que solo contiene letras, números o guiones, y así evitar que se introduzcan comandos maliciosos. Este conjunto de caracteres es lo suficientemente limitado como para evitar ataques de inyección de comandos.

El servicio web transfiere el parámetro de búsqueda como argumento a la secuencia de comandos 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

Definir el entorno del contenedor

El archivo Dockerfile define cómo se configura el entorno del servicio. Es similar al archivo Dockerfile de la guía de inicio rápido de helloworld-shell, salvo que la imagen de contenedor final se basa en la imagen de la gcloud CLI de Google Cloud. De esta forma, tu servicio puede usar gcloud sin tener que seguir pasos de instalación y configuración personalizados para la CLI de Google Cloud.


# 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"]

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 de Artifact Registry.

Configurar el segmento de Cloud Storage

Crea un segmento de Cloud Storage para subir informes:

gcloud storage buckets create gs://REPORT_ARCHIVE_BUCKET

Sustituye REPORT_ARCHIVE_BUCKET por un nombre de segmento único de forma global.

Configurar la identidad del servicio

Para limitar los privilegios que tiene el servicio en otras infraestructuras, crea una identidad de servicio y personaliza los permisos de gestión de identidades y accesos específicos necesarios para hacer el trabajo.

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

  1. Crea una cuenta de servicio:

    gcloud iam service-accounts create gcloud-report-identity

  2. Concede a la cuenta de servicio permiso 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. Concede a la cuenta de servicio permiso para leer y escribir en el segmento 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 de servicio personalizada impide que el servicio acceda a otros recursos. Google Cloud

Enviar el servicio

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

  • Crear una imagen de contenedor con Cloud Build
  • Subir la imagen de contenedor a Artifact Registry
  • Desplegando 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:

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

    Sustituye:

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

    gcloud-report es el nombre de tu servicio.

    Si la operación se realiza correctamente, se mostrará un mensaje de ÉXITO con el ID, la hora de creación y el nombre de la imagen. La imagen se almacena en Artifact Registry y se puede reutilizar si es necesario.

  2. Ejecuta el siguiente comando para desplegar 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

    Sustituye:

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

    gcloud-report forma parte del nombre del contenedor y del nombre del servicio. La imagen de contenedor se desplegará en el servicio y la región (Cloud Run) que hayas configurado anteriormente en Configurar gcloud.

    La marca --no-allow-unauthenticated restringe el acceso público al servicio. Si mantienes el servicio privado, puedes usar la autenticación integrada de Cloud Run para bloquear las solicitudes no autorizadas. Para obtener más información sobre la autenticación basada en la gestión de identidades y accesos (IAM), consulta Gestionar el acceso con IAM.

    Espera a que se complete la implementación. Este proceso puede tardar aproximadamente medio minuto. Si la acción se realiza correctamente, la línea de comandos mostrará la URL del servicio.

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

Consulta Gestionar el acceso con la gestión de identidades y accesos para saber cómo conceder acceso a los usuarios para invocar este servicio. Google Cloud Los editores y propietarios de proyectos tienen este acceso automáticamente.

Generar un informe

Para generar un informe de 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

    Sustituye SERVICE_URL por la URL que proporciona Cloud Run después de completar el despliegue.

    Si has creado un proyecto y has seguido este tutorial, el resultado será similar al siguiente:

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

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

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

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

    Esta consulta devolverá un resultado similar al siguiente:

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

    gcloud storage cp gs://REPORT_FILE_NAME .

    El . del comando hace referencia al directorio de trabajo actual.

    Sustituye REPORT_FILE_NAME por el nombre del objeto de Cloud Storage que se ha mostrado en el paso anterior.

Abre el archivo para ver el informe. Debería tener este aspecto:

Captura de pantalla de la lista de servicios de Cloud Run del proyecto con columnas de cuatro atributos de servicio.
Las cuatro columnas se extraen de la descripción del servicio. como el nombre del servicio, la URL asignada en la primera implementación, el creador inicial del servicio y los límites de CPU y memoria del servicio.

Mejorar la solidez de cara al futuro

Si tienes previsto seguir desarrollando este servicio, te recomendamos que lo reescribas en un lenguaje de programación más sólido y que uses la API Admin de Cloud Run y la biblioteca de cliente de Cloud Storage.

Puedes examinar las llamadas a la API que se están haciendo (y ver algunos detalles de autenticación) añadiendo --log-http a los comandos de la CLI de gcloud.

Automatizar esta operación

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