Pic-a-daily: lab 5 - Pulizia dopo l'eliminazione dell'immagine

1. Panoramica

In questo lab di codice creerai un nuovo servizio Cloud Run, il garbage collector di immagini, che verrà attivato da Eventarc, un nuovo servizio per la ricezione di eventi in Cloud Run. Quando un'immagine viene eliminata dal bucket di immagini, il servizio riceve un evento da Eventarc. Quindi, elimina l'immagine dal bucket delle miniature e la rimuove anche dalla raccolta di immagini Firestore.

d93345bfc235f81e.png

Cosa imparerai a fare

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc

2. Configurazione e requisiti

Configurazione dell'ambiente da seguire in modo autonomo

  1. Accedi alla console Google Cloud e crea un nuovo progetto o riutilizzane uno esistente. Se non hai ancora un account Gmail o Google Workspace, devi crearne uno.

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

  • Il Nome progetto è il nome visualizzato dei partecipanti del progetto. Si tratta di una stringa di caratteri non utilizzata dalle API di Google e può essere aggiornata in qualsiasi momento.
  • L'ID progetto deve essere univoco in tutti i progetti Google Cloud ed è immutabile (non può essere modificato dopo essere stato impostato). La console Cloud genera automaticamente una stringa univoca. di solito non ti importa cosa sia. Nella maggior parte dei codelab, devi fare riferimento all'ID progetto (che solitamente è identificato come PROJECT_ID), quindi, se non ti piace, generane un altro a caso oppure puoi fare un tentativo personalizzato e controllare se è disponibile. Poi c'è "congelato" dopo la creazione del progetto.
  • C'è un terzo valore, il numero di progetto, utilizzato da alcune API. Scopri di più su tutti e tre questi valori nella documentazione.
  1. Successivamente, dovrai abilitare la fatturazione nella console Cloud per utilizzare le risorse/le API Cloud. Eseguire questo codelab non dovrebbe costare molto. Per arrestare le risorse in modo da non incorrere in fatturazione oltre questo tutorial, segui eventuali "pulizie" istruzioni riportate alla fine del codelab. I nuovi utenti di Google Cloud sono idonei al programma prova senza costi di 300$.

Avvia Cloud Shell

Anche se Google Cloud può essere utilizzato da remoto dal tuo laptop, in questo codelab utilizzerai Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.

Dalla console di Google Cloud, fai clic sull'icona di Cloud Shell nella barra degli strumenti in alto a destra:

bce75f34b2c53987.png

Dovrebbe richiedere solo qualche istante per eseguire il provisioning e connettersi all'ambiente. Al termine, dovresti vedere una schermata simile al seguente:

f6ef2b5f13479f3a.png

Questa macchina virtuale viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita su Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Tutto il lavoro in questo lab può essere svolto semplicemente con un browser.

3. Introduzione a Eventarc

Eventarc semplifica la connessione dei servizi Cloud Run agli eventi provenienti da una varietà di origini. Si occupa dell'importazione, della distribuzione, della sicurezza, dell'autorizzazione e della gestione degli errori degli eventi.

776ed63706ca9683.png

Puoi ricavare eventi da origini Google Cloud e pubblicazione di applicazioni personalizzate in Cloud Pub/Sub e consegnarli ai sink di Google Cloud Run.

Gli eventi provenienti da un'ampia gamma di origini Google Cloud vengono forniti tramite Cloud Audit Logs. La latenza e la disponibilità della distribuzione degli eventi da queste origini sono legate a quelle di Cloud Audit Logs. Ogni volta che viene attivato un evento da un'origine Google Cloud, viene creata una voce di Cloud Audit Log corrispondente.

La pubblicazione di applicazioni personalizzate in Cloud Pub/Sub può pubblicare messaggi in un argomento Pub/Sub specificato in qualsiasi formato.

I trigger di eventi sono il meccanismo di filtro per specificare quali eventi inviare a un determinato sink.

Tutti gli eventi vengono pubblicati nel formato CloudEvents v1.0 per l'interoperabilità tra servizi.

4. Prima di iniziare

Abilita API

Per attivare il servizio Cloud Run è necessario il servizio Eventarc. Assicurati che sia abilitata:

gcloud services enable eventarc.googleapis.com

L'operazione dovrebbe essere completata correttamente:

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

Configura account di servizio

Nei trigger verrà utilizzato l'account di servizio predefinito di Compute. Concedi il ruolo eventarc.eventReceiver all'account di servizio Compute predefinito:

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

Concedi il ruolo pubsub.publisher all'account di servizio Cloud Storage. È necessario per il trigger di Cloud Storage 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

Se hai abilitato l'account di servizio Pub/Sub entro l'8 aprile 2021, concedi il ruolo iam.serviceAccountTokenCreator all'account di servizio 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 il codice

Clona il codice, se non l'hai già fatto nel codelab precedente:

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

Quindi puoi andare alla directory contenente il servizio:

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

Per il servizio avrai il seguente layout di file:

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

La cartella contiene tre file:

  • index.js contiene il codice Node.js
  • package.json definisce le dipendenze della libreria

6. Esplora il codice

Dipendenze

Il file package.json definisce le dipendenze di libreria necessarie:

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

Dipendiamo dalla libreria di Cloud Storage per eliminare le immagini all'interno di Cloud Storage. Dichiariamo una dipendenza da Cloud Firestore, per eliminare anche i metadati delle immagini archiviati in precedenza. Inoltre, per leggere gli eventi CloudEvents inviati da Eventarc, ci affidiamo all'SDK CloudEvents e alle librerie di Eventi Google. Express è un framework web JavaScript / Nodo. Bluebird viene utilizzato per gestire le promesse.

index.js

Diamo un'occhiata più da vicino al nostro codice 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');

Sono necessarie le varie dipendenze necessarie per l'esecuzione del nostro programma: Express è il framework web Node che utilizzeremo, Bluebird è una libreria per la gestione delle promesse relative a JavaScript, Storage e Firestore sono utili per lavorare rispettivamente con Google Cloud Storage (i nostri bucket di immagini) e con il datastore Cloud Firestore. Inoltre, richiediamo a CloudEvent di leggere il CloudEvent inviato da Eventarc StoreObjectData dalla libreria di eventi Google per leggere il corpo dell'evento Cloud Storage di 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);
    }
});

Qui sopra abbiamo la struttura del gestore dei nodi: la nostra app risponde alle richieste HTTP POST. Legge l'evento CloudEvent dalla richiesta HTTP e gestiamo una parte degli errori nel caso in cui qualcosa vada storto. Diamo ora un'occhiata a cosa c'è all'interno di questa struttura.

Il passaggio successivo consiste nel recuperare e analizzare il corpo di CloudEvent e recuperare il nome dell'oggetto:

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

const objectName = storageObjectData.name;

Una volta conosciuto il nome dell'immagine, possiamo eliminarlo dal bucket delle miniature:

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}.`);
}

Come ultimo passaggio, elimina anche i metadati dell'immagine dalla raccolta 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}'.`);

Ora è il momento di far sì che lo script del nostro nodo ascolti le richieste in arrivo. Verifica inoltre che siano impostate le variabili di ambiente richieste:

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

7. Esegui test in locale

Testa il codice in locale per assicurarti che funzioni prima del deployment nel cloud.

All'interno della cartella garbage-collector/nodejs, installa le dipendenze npm e avvia il server:

export BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT

npm install; npm start

Se tutto è andato a buon fine, il server dovrebbe essere avviato sulla porta 8080:

Started service on port 8080

Usa CTRL-C per uscire.

8. Crea ed esegui il deployment su Cloud Run

Prima di eseguire il deployment in Cloud Run, imposta la regione di Cloud Run su una delle regioni e della piattaforma supportate su managed:

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

Puoi verificare che la configurazione sia impostata:

gcloud config list

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

Anziché creare e pubblicare manualmente l'immagine container con Cloud Build, puoi fare affidamento su Cloud Run per creare l'immagine container al posto tuo utilizzando Google Cloud Buildpacks.

Esegui questo comando per creare l'immagine container utilizzando Google Cloud Buildpack, quindi esegui il deployment dell'immagine container in Cloud Run:

SERVICE_NAME=garbage-collector-service

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

Nota il flag –-source. Questo flag segnala a Cloud Run l'utilizzo di Google Cloud Buildpacks per creare l'immagine container senza Dockerfile.. Il flag --no-allow-unauthenticated rende il servizio Cloud Run un servizio interno che verrà attivato solo da account di servizio specifici. Successivamente, creerai un trigger con l'account di servizio Compute predefinito con il ruolo run.invoker per chiamare i servizi Cloud Run interni.

9. Crea un trigger

In Eventarc, un trigger definisce quale servizio deve ricevere il tipo di eventi. In questo caso, vuoi che il servizio riceva gli eventi quando un file viene eliminato in un bucket.

Imposta la località del trigger nella stessa regione del bucket delle immagini caricate:

gcloud config set eventarc/location eu

Crea un trigger AuditLog per filtrare gli eventi storage.objects.delete e invialo al servizio 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

Puoi verificare che il trigger sia stato creato con questo comando:

gcloud eventarc triggers list

10. Prova il servizio

Per verificare se il servizio funziona, vai al bucket uploaded-pictures ed elimina una delle immagini. Nei log del servizio dovresti vedere che ha eliminato l'immagine pertinente nel bucket thumbnails e anche il relativo documento dalla raccolta Firestore pictures.

519abf90e7ea4d12.png

11. Libera spazio (facoltativo)

Se non intendi continuare con gli altri lab della serie, puoi eseguire la pulizia delle risorse per risparmiare sui costi ed essere nel complesso un buon cittadino del cloud. Puoi eseguire la pulizia delle risorse singolarmente come descritto di seguito.

Elimina il servizio:

gcloud run services delete $SERVICE_NAME -q

Elimina il trigger Eventarc:

gcloud eventarc triggers delete trigger-$SERVICE_NAME -q

In alternativa, puoi eliminare l'intero progetto:

gcloud projects delete $GOOGLE_CLOUD_PROJECT

12. Complimenti!

Complimenti! Hai creato un servizio Cloud Run, il garbage collector di immagini, che viene attivato da Eventarc, un nuovo servizio per la ricezione di eventi in Cloud Run. Quando un'immagine viene eliminata dal bucket di immagini, il servizio riceve un evento da Eventarc. Quindi, elimina l'immagine dal bucket delle miniature e la rimuove anche dalla raccolta di immagini Firestore.

Argomenti trattati

  • Cloud Run
  • Cloud Storage
  • Cloud Firestore
  • Eventarc