1. Panoramica
In questo lab di codice creerai un nuovo servizio Cloud Run, il servizio di collage, che verrà attivato da Cloud Scheduler a intervalli regolari. Il servizio recupera le immagini più recenti caricate e crea un collage di queste immagini: trova l'elenco delle immagini recenti in Cloud Firestore e scarica i file delle immagini effettive da Cloud Storage.
Cosa imparerai a fare
- Cloud Run
- Cloud Scheduler
- Cloud Storage
- Cloud Firestore
2. Configurazione e requisiti
Configurazione dell'ambiente da seguire in modo autonomo
- 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.
- 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.
- 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:
Dovrebbe richiedere solo qualche istante per eseguire il provisioning e connettersi all'ambiente. Al termine, dovresti vedere una schermata simile al seguente:
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. Abilita API
Avrai bisogno di Cloud Scheduler per attivare il servizio Cloud Run a intervalli regolari. Assicurati che sia abilitata:
gcloud services enable cloudscheduler.googleapis.com
L'operazione dovrebbe essere completata correttamente:
Operation "operations/acf.5c5ef4f6-f734-455d-b2f0-ee70b5a17322" finished successfully.
4. 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/collage/nodejs
Per il servizio avrai il seguente layout di file:
services | ├── collage | ├── nodejs | ├── Dockerfile ├── index.js ├── package.json
La cartella contiene tre file:
index.js
contiene il codice Node.jspackage.json
definisce le dipendenze della libreriaDockerfile
definisce l'immagine container
5. Esplora il codice
Dipendenze
Il file package.json
definisce le dipendenze di libreria necessarie:
{
"name": "collage_service",
"version": "0.0.1",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"bluebird": "^3.7.2",
"express": "^4.17.1",
"imagemagick": "^0.1.3",
"@google-cloud/firestore": "^4.9.9",
"@google-cloud/storage": "^5.8.3"
}
}
Dipendiamo dalla libreria di Cloud Storage per leggere e salvare i file immagine all'interno di Cloud Storage. Dichiariamo una dipendenza su Cloud Firestore per recuperare i metadati delle immagini archiviati in precedenza. Express è un framework web JavaScript / Nodo. Bluebird viene utilizzato per gestire le promesse, mentre imagemagick è una libreria per la manipolazione di immagini.
Dockerfile
Dockerfile
definisce l'immagine container per l'applicazione:
FROM node:14-slim
# installing Imagemagick
RUN set -ex; \
apt-get -y update; \
apt-get -y install imagemagick; \
rm -rf /var/lib/apt/lists/*
WORKDIR /picadaily/services/collage
COPY package*.json ./
RUN npm install --production
COPY . .
CMD [ "npm", "start" ]
Stiamo usando un'immagine base Node 14 chiara. Stiamo installando la libreria Imagemagick. Quindi installiamo i moduli di Gestione dei partner di rete necessari per il nostro codice ed eseguiamo il codice nodo con npm start.
index.js
Diamo un'occhiata più da vicino al nostro codice index.js
:
const express = require('express');
const imageMagick = require('imagemagick');
const Promise = require("bluebird");
const path = require('path');
const {Storage} = require('@google-cloud/storage');
const Firestore = require('@google-cloud/firestore');
Abbiamo bisogno delle varie dipendenze necessarie per l'esecuzione del nostro programma: Express è il framework web Node che utilizzeremo, ImageMagick la libreria per la manipolazione delle immagini, Bluebird è una libreria per la gestione delle promesse di JavaScript, Path viene utilizzato per gestire i percorsi di file e directory e quindi Storage e Firestore sono utilizzati per lavorare rispettivamente con Google Cloud Storage (i nostri bucket di immagini) e con il datastore Cloud Firestore.
const app = express();
app.get('/', async (req, res) => {
try {
console.log('Collage request');
/* ... */
} catch (err) {
console.log(`Error: creating the collage: ${err}`);
console.error(err);
res.status(500).send(err);
}
});
Qui sopra abbiamo la struttura del gestore dei nodi: la nostra app risponde alle richieste HTTP GET. Stiamo elaborando anche un po' di gestione degli errori nel caso in cui qualcosa vada storto. Diamo ora un'occhiata a cosa c'è all'interno di questa struttura.
const thumbnailFiles = [];
const pictureStore = new Firestore().collection('pictures');
const snapshot = await pictureStore
.where('thumbnail', '==', true)
.orderBy('created', 'desc')
.limit(4).get();
if (snapshot.empty) {
console.log('Empty collection, no collage to make');
res.status(204).send("No collage created.");
} else {
/* ... */
}
Il nostro servizio di collage necessita di almeno quattro immagini (le cui miniature sono state generate), quindi assicurati di caricare prima quattro immagini.
Recuperiamo le 4 immagini più recenti caricate dai nostri utenti dai metadati archiviati in Cloud Firerstore. Verifichiamo se la raccolta risultante è vuota o meno, quindi procediamo nel ramo altro del nostro codice.
Raccogliamo l'elenco dei nomi di file:
snapshot.forEach(doc => {
thumbnailFiles.push(doc.id);
});
console.log(`Picture file names: ${JSON.stringify(thumbnailFiles)}`);
Scarichiamo ognuno di questi file dal bucket delle miniature, il cui nome deriva da una variabile di ambiente che abbiamo impostato al momento del deployment:
const thumbBucket = storage.bucket(process.env.BUCKET_THUMBNAILS);
await Promise.all(thumbnailFiles.map(async fileName => {
const filePath = path.resolve('/tmp', fileName);
await thumbBucket.file(fileName).download({
destination: filePath
});
}));
console.log('Downloaded all thumbnails');
Una volta caricate le miniature più recenti, utilizzeremo la libreria ImageMagick per creare una griglia 4x4 con le miniature. Utilizziamo la libreria Bluebird e la sua implementazione Promise per trasformare il codice basato su callback in un codice semplice da async
/ await
, quindi aspettiamo la promessa che sta creando il collage di immagini:
const collagePath = path.resolve('/tmp', 'collage.png');
const thumbnailPaths = thumbnailFiles.map(f => path.resolve('/tmp', f));
const convert = Promise.promisify(im.convert);
await convert([
'(', ...thumbnailPaths.slice(0, 2), '+append', ')',
'(', ...thumbnailPaths.slice(2), '+append', ')',
'-size', '400x400', 'xc:none', '-background', 'none', '-append',
collagePath]);
console.log("Created local collage picture");
Poiché l'immagine del collage è stata salvata sul disco localmente nella cartella temporanea, dobbiamo caricarla in Cloud Storage e quindi restituire una risposta positiva (codice di stato 2xx):
await thumbBucket.upload(collagePath);
console.log("Uploaded collage to Cloud Storage bucket ${process.env.BUCKET_THUMBNAILS}");
res.status(204).send("Collage created.");
Ora è il momento di fare in modo che il nostro script del nodo ascolti le richieste in arrivo:
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Started collage service on port ${PORT}`);
});
Alla fine del nostro file sorgente, abbiamo le istruzioni per fare in modo che Express avvii la nostra applicazione web sulla porta predefinita 8080.
6. Esegui test in locale
Testa il codice in locale per assicurarti che funzioni prima di eseguirne il deployment nel cloud.
All'interno della cartella collage/nodejs
, installa le dipendenze npm e avvia il server:
npm install; npm start
Se tutto è andato a buon fine, il server dovrebbe essere avviato sulla porta 8080:
Started collage service on port 8080
Usa CTRL-C
per uscire.
7. 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
:
gcloud config set run/region europe-west1 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:
BUCKET_THUMBNAILS=thumbnails-$GOOGLE_CLOUD_PROJECT SERVICE_NAME=collage-service gcloud run deploy $SERVICE_NAME \ --source . \ --no-allow-unauthenticated \ --update-env-vars BUCKET_THUMBNAILS=$BUCKET_THUMBNAILS
Nota il flag –-source
. Questo è il deployment basato sull'origine in Cloud Run. Se nella directory del codice sorgente è presente un Dockerfile
, il codice sorgente caricato viene creato utilizzando questo Dockerfile
. Se nella directory del codice sorgente non è presente alcun Dockerfile
, i buildpacks di Google Cloud rilevano automaticamente il linguaggio in uso e recupera le dipendenze del codice per creare un'immagine container pronta per la produzione, utilizzando un'immagine base sicura gestita da Google. Questo flag segnala Cloud Run per utilizzare Google Cloud Buildpacks per creare l'immagine container definita in Dockerfile
.
Tieni inoltre presente che il deployment basato sull'origine utilizza Artifact Registry per archiviare i container creati. Artifact Registry è una versione moderna di Google Container Registry. L'interfaccia a riga di comando ti chiederà di abilitare l'API, se non è già abilitata nel progetto, e creerà un repository con il nome cloud-run-source-deploy
nella regione in cui stai eseguendo il deployment.
Il flag --no-allow-unauthenticated
rende il servizio Cloud Run un servizio interno che viene attivato solo da account di servizio specifici.
8. Configura Cloud Scheduler
Ora che il servizio Cloud Run è pronto ed è stato eseguito il deployment, è il momento di creare la pianificazione regolare, per richiamare il servizio ogni minuto.
Crea un account di servizio:
SERVICE_ACCOUNT=collage-scheduler-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name "Collage Scheduler Service Account"
Concedi all'account di servizio l'autorizzazione per richiamare il servizio Cloud Run:
gcloud run services add-iam-policy-binding $SERVICE_NAME \ --member=serviceAccount:$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --role=roles/run.invoker
Crea un job Cloud Scheduler da eseguire ogni minuto:
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --format 'value(status.url)') gcloud scheduler jobs create http $SERVICE_NAME-job --schedule "* * * * *" \ --http-method=GET \ --location=europe-west1 \ --uri=$SERVICE_URL \ --oidc-service-account-email=$SERVICE_ACCOUNT@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com \ --oidc-token-audience=$SERVICE_URL
Puoi andare alla sezione Cloud Scheduler in Cloud Console per verificare che sia configurato e che punti all'URL del servizio Cloud Run:
9. Prova il servizio
Per verificare se la configurazione funziona, cerca l'immagine del collage nel bucket thumbnails
(denominata collage.png
). Puoi anche controllare i log del servizio:
10. 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 job Cloud Scheduler:
gcloud scheduler jobs delete $SERVICE_NAME-job -q
In alternativa, puoi eliminare l'intero progetto:
gcloud projects delete $GOOGLE_CLOUD_PROJECT
11. Complimenti!
Complimenti! Hai creato un servizio pianificato: grazie a Cloud Scheduler, che esegue il push di un messaggio ogni minuto su un argomento Pub/Sub, il servizio di collage Cloud Run viene richiamato ed è in grado di aggiungere immagini per creare l'immagine risultante.
Argomenti trattati
- Cloud Run
- Cloud Scheduler
- Cloud Storage
- Cloud Firestore