Pic-a-daily: Lab 5: Limpieza después de borrar la imagen

Pic-a-daily:
Lab 5:
Limpieza después de borrar la imagen

Acerca de este codelab

subjectÚltima actualización: oct 7, 2021
account_circleEscrito por Mete Atamel

1. Descripción general

En este codelab, crearás un nuevo servicio de Cloud Run, un recolector de elementos no utilizados de imagen, que se activará con Eventarc, un servicio nuevo para recibir eventos en Cloud Run. Cuando se borra una foto del bucket de imágenes, el servicio recibe un evento de Eventarc. Luego, borra la imagen del bucket de miniaturas y también la quita de la colección de fotos de Firestore.

d93345bfc235f81e.png

Qué aprenderás

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

2. Configuración y requisitos

Configuración del entorno de autoaprendizaje

  1. Accede a Google Cloud Console y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • El Nombre del proyecto es el nombre visible de los participantes de este proyecto. Es una string de caracteres que no se utiliza en las API de Google y se puede actualizar en cualquier momento.
  • El ID del proyecto debe ser único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). Cloud Console genera automáticamente una string única, que, por lo general, no importa cuál sea. En la mayoría de los codelabs, debes hacer referencia al ID del proyecto (suele ser PROJECT_ID). Por lo tanto, si no te gusta, genera otro aleatorio o prueba con uno propio y comprueba si está disponible. Después de crear el proyecto, este ID se “congela” y no se puede cambiar.
  • Además, hay un tercer valor, el Número de proyecto, que usan algunas API. Obtén más información sobre estos tres valores en la documentación.
  1. A continuación, deberás habilitar la facturación en Cloud Console para usar las API o los recursos de Cloud. Ejecutar este codelab no debería costar mucho, tal vez nada. Si quieres cerrar los recursos para no se te facture más allá de este instructivo, sigue las instrucciones de “limpieza” que se encuentran al final del codelab. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.

Inicia Cloud Shell

Si bien Google Cloud y Spanner se pueden operar de manera remota desde tu laptop, en este codelab usarás Google Cloud Shell, un entorno de línea de comandos que se ejecuta en la nube.

En GCP Console, haga clic en el ícono de Cloud Shell en la barra de herramientas superior derecha:

bce75f34b2c53987.png

El aprovisionamiento y la conexión al entorno deberían tomar solo unos minutos. Cuando termine el proceso, debería ver algo como lo siguiente:

f6ef2b5f13479f3a.png

Esta máquina virtual está cargada con todas las herramientas de desarrollo que necesitarás. Ofrece un directorio principal persistente de 5 GB y se ejecuta en Google Cloud, lo que permite mejorar considerablemente el rendimiento de la red y la autenticación. Puedes realizar todo tu trabajo en este lab usando simplemente un navegador.

3. Introducción a Eventarc

Eventarc facilita la conexión de los servicios de Cloud Run con eventos de una variedad de fuentes. Se encarga de la transferencia de eventos, la entrega, la seguridad, la autorización y el manejo de errores por ti.

827c38341467.png

Puedes extraer eventos de fuentes de Google Cloud y aplicaciones personalizadas que publican en Cloud Pub/Sub y entregarlos a receptores de Google Cloud Run.

Los eventos de una gran variedad de fuentes de Google Cloud se entregan a través de Registros de auditoría de Cloud. La latencia y la disponibilidad de la entrega de eventos de estas fuentes están vinculadas a las de los Registros de auditoría de Cloud. Cada vez que se activa un evento de una fuente de Google Cloud, se crea la entrada correspondiente de los Registros de auditoría de Cloud.

Las aplicaciones personalizadas que publican en Cloud Pub/Sub pueden publicar mensajes en un tema de Pub/Sub que especifiquen en cualquier formato.

Los activadores de eventos son el mecanismo de filtrado para especificar qué eventos entregar a qué receptor.

Todos los eventos se entregan en el formato CloudEvents v1.0 para la interoperabilidad entre servicios.

4. Antes de comenzar

Habilita las APIs

Necesitarás el servicio de Eventarc para activar el servicio de Cloud Run. Asegúrate de que esté habilitada:

gcloud services enable eventarc.googleapis.com

Deberías ver que la operación finaliza correctamente:

Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.

Configurar cuentas de servicio

La cuenta de servicio de procesamiento predeterminada se usará en los activadores. Otorga el rol eventarc.eventReceiver a la cuenta de servicio de procesamiento predeterminada:

PROJECT_NUMBER=$(gcloud projects describe $GOOGLE_CLOUD_PROJECT --format='value(projectNumber)')

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
    --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role roles/eventarc.eventReceiver

Otorga el rol pubsub.publisher a la cuenta de servicio de Cloud Storage. Esto es necesario para el activador de Cloud Storage de Eventarc:

SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER)

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member serviceAccount:$SERVICE_ACCOUNT \
    --role roles/pubsub.publisher

Si habilitaste la cuenta de servicio de Pub/Sub el 8 de abril de 2021 o antes de esa fecha, otorga el rol iam.serviceAccountTokenCreator a la cuenta de servicio de 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

5. Clona el código

Clona el código, si aún no lo hiciste en el codelab anterior:

git clone https://github.com/GoogleCloudPlatform/serverless-photosharing-workshop

Luego, puedes ir al directorio que contiene el servicio:

cd serverless-photosharing-workshop/services/garbage-collector/nodejs

Tendrás el siguiente diseño de archivo para el servicio:

services
 |
 ├── garbage-collector
      |
      ├── nodejs
           |
           ├── index.js
           ├── package.json

Dentro de la carpeta, tienes 3 archivos:

  • index.js contiene el código de Node.js.
  • package.json define las dependencias de la biblioteca.

6. Cómo explorar el código

Dependencias

El archivo package.json define las dependencias de biblioteca necesarias:

{
 
"name": "garbage_collector_service",
 
"version": "0.0.1",
 
"main": "index.js",
 
"scripts": {
   
"start": "node index.js"
 
},
 
"dependencies": {
   
"cloudevents": "^4.0.1",
   
"express": "^4.17.1",
   
"@google/events": "^3.1.0",
   
"@google-cloud/firestore": "^4.9.9",
   
"@google-cloud/storage": "^5.8.3"
 
}
}

Dependemos de la biblioteca de Cloud Storage para borrar imágenes en Cloud Storage. Declaramos una dependencia en Cloud Firestore para borrar también los metadatos de fotos que almacenamos anteriormente. Además, dependemos del SDK de CloudEvents y las bibliotecas de Eventos de Google para leer los CloudEvents que envía Eventarc. Express es un framework web de JavaScript / Node. Bluebird se usa para administrar promesas.

index.js

Analicemos con más detalle nuestro código index.js:

const express = require('express');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
const { HTTP } = require("cloudevents");
const {toStorageObjectData} = require('@google/events/cloud/storage/v1/StorageObjectData');

Exigimos las diversas dependencias necesarias para que nuestro programa se ejecute: Express es el framework web de Node que usaremos, Bluebird es una biblioteca para manejar promesas de JavaScript, Storage y Firestore se usan para trabajar respectivamente con Google Cloud Storage (nuestros buckets de imágenes) y el almacén de datos de Cloud Firestore. Además, es necesario que CloudEvent lea el CloudEvent que envió Eventarc StoreObjectData desde la biblioteca de Google Events para leer el cuerpo del evento de Cloud Storage del CloudEvent.

const app = express();
app
.use(express.json());

app
.post('/', async (req, res) => {
   
try {
       
const cloudEvent = HTTP.toEvent({ headers: req.headers, body: req.body });
        console
.log(cloudEvent);


       
/* ... */

   
} catch (err) {
        console
.log(`Error: ${err}`);
        res
.status(500).send(err);
   
}
});

Arriba, tenemos la estructura de nuestro controlador de Node: nuestra app responde a las solicitudes HTTP POST. Lee el CloudEvent de la solicitud HTTP y realizamos un poco de manejo de errores en caso de que algo salga mal. Ahora, veamos qué contiene esta estructura.

El siguiente paso es recuperar y analizar el cuerpo de CloudEvent y recuperar el nombre del objeto:

const storageObjectData = toStorageObjectData(cloudEvent.data);
console
.log(storageObjectData);

const objectName = storageObjectData.name;

Una vez que sabemos el nombre de la imagen, podemos borrarla del bucket de miniaturas:

try {
    await storage
.bucket(bucketThumbnails).file(objectName).delete();
    console
.log(`Deleted '${objectName}' from bucket '${bucketThumbnails}'.`);
}
catch(err) {
    console
.log(`Failed to delete '${objectName}' from bucket '${bucketThumbnails}': ${err}.`);
}

Como último paso, borra también los metadatos de las fotos de la colección de Firestore:

try {
   
const pictureStore = new Firestore().collection('pictures');
   
const docRef = pictureStore.doc(objectName);
    await docRef
.delete();

    console
.log(`Deleted '${objectName}' from Firestore collection 'pictures'`);
}
catch(err) {
    console
.log(`Failed to delete '${objectName}' from Firestore: ${err}.`);
}

res
.status(200).send(`Processed '${objectName}'.`);

Ahora, es momento de hacer que nuestra secuencia de comandos de Node escuche las solicitudes entrantes. Además, verifica que estén configuradas las variables de entorno necesarias:

app.listen(PORT, () => {
   
if (!bucketThumbnails) throw new Error("BUCKET_THUMBNAILS not set");
    console
.log(`Started service on port ${PORT}`);
});

7. Realiza pruebas locales

Prueba el código de forma local para asegurarte de que funciona antes de implementarlo en la nube.

En la carpeta garbage-collector/nodejs, instala las dependencias de npm y, luego, inicia el servidor:

export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT

npm install; npm start

Si todo salió bien, debería iniciar el servidor en el puerto 8080:

Started service on port 8080

Usa CTRL-C para salir.

8. Compila e implementa en Cloud Run

Antes de realizar implementaciones en Cloud Run, configura la región de Cloud Run en una de las regiones y la plataforma compatibles en managed:

REGION=europe-west1
gcloud config set run/region $REGION
gcloud config set run/platform managed

Puedes verificar que la configuración esté establecida:

gcloud config list

...
[run]
platform = managed
region = europe-west1

En lugar de compilar y publicar la imagen de contenedor con Cloud Build de forma manual, también puedes confiar en que Cloud Run compilará la imagen de contenedor por ti con Google Cloud Buildpacks.

Ejecuta el siguiente comando para compilar la imagen de contenedor con los Google Cloud Buildpacks y, luego, impleméntala en Cloud Run:

SERVICE_NAME=garbage-collector-service

gcloud run deploy $SERVICE_NAME \
    --source . \
    --no-allow-unauthenticated \
    --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS

Observa la marca –-source. Esto indica que Cloud Run use paquetes de Google Cloud Build para compilar la imagen de contenedor sin un Dockerfile.. La marca --no-allow-unauthenticated hace que el servicio de Cloud Run sea un servicio interno que solo se activará mediante cuentas de servicio específicas. Más adelante, crearás un activador con la cuenta de servicio de procesamiento predeterminada que tiene el rol run.invoker para llamar a los servicios internos de Cloud Run.

9. Crea un activador

En Eventarc, un activador define qué servicio debería obtener el tipo de eventos. En este caso, quieres que el servicio reciba eventos cuando se borre un archivo de un bucket.

Establece la ubicación del activador en la misma región que el bucket de imágenes subidas:

gcloud config set eventarc/location eu

Crea un activador AuditLog para filtrar los eventos storage.objects.delete y enviarlos al servicio de Cloud Run:

BUCKET_IMAGES=uploaded-pictures-$GOOGLE_CLOUD_PROJECT

gcloud eventarc triggers create trigger-$SERVICE_NAME \
  --destination-run-service=$SERVICE_NAME \
  --destination-run-region=$REGION \
  --event-filters="type=google.cloud.storage.object.v1.deleted" \
  --event-filters="bucket=$BUCKET_IMAGES" \
  --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

Puedes verificar que el activador se cree con este comando:

gcloud eventarc triggers list

10. Prueba el servicio

Para probar si funciona el servicio, ve al bucket uploaded-pictures y borra una de las fotos. En los registros del servicio, deberías ver que borró la foto relevante del bucket thumbnails y el documento de la colección pictures de Firestore.

519abf90e7ea4d12.png

11. Limpieza (opcional)

Si no pretendes continuar con los otros labs de la serie, puedes liberar recursos para ahorrar costos y ser un buen ciudadano de la nube en general. Puedes limpiar los recursos de forma individual de la siguiente manera.

Borra el servicio:

gcloud run services delete $SERVICE_NAME -q

Borrar el activador de Eventarc:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

También puedes borrar todo el proyecto:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. ¡Felicitaciones!

¡Felicitaciones! Creaste un servicio de Cloud Run, recolector de elementos no utilizados de imagen, que se activa mediante Eventarc, un servicio nuevo para recibir eventos en Cloud Run. Cuando se borra una foto del bucket de imágenes, el servicio recibe un evento de Eventarc. Luego, borra la imagen del bucket de miniaturas y también la quita de la colección de fotos de Firestore.

Temas abordados

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc