1. Introduzione
Panoramica
Cloud Run functions è l'offerta Functions as a Service di Google Cloud basata su Cloud Run ed Eventarc, che ti offre un controllo più avanzato su prestazioni e scalabilità, nonché un maggiore controllo sul runtime e sui trigger delle funzioni da oltre 90 origini evento.
Questo codelab ti guiderà nella creazione di funzioni Cloud Run che rispondono alle chiamate HTTP e vengono attivate da messaggi Pub/Sub e Cloud Audit Logs.
Questo codelab utilizza anche gli aggiornamenti automatici delle immagini di base per i deployment delle funzioni specificando un'immagine di base utilizzando il flag --base-image. Gli aggiornamenti automatici delle immagini di base per Cloud Run consentono a Google di applicare automaticamente patch di sicurezza ai componenti del sistema operativo e del runtime del linguaggio dell'immagine di base. Non devi ricompilare o ridistribuire il servizio per aggiornare l'immagine di base. Per ulteriori informazioni, consulta la sezione Aggiornamenti automatici delle immagini di base.
Se preferisci non utilizzare gli aggiornamenti automatici dell'immagine di base, puoi rimuovere il flag --base-image dagli esempi mostrati in questo codelab.
Obiettivi didattici
- Panoramica di Cloud Run Functions e su come utilizzare gli aggiornamenti automatici delle immagini di base.
- Come scrivere una funzione che risponde alle chiamate HTTP.
- Come scrivere una funzione che risponde ai messaggi Pub/Sub.
- Come scrivere una funzione che risponde agli eventi Cloud Storage.
- Come suddividere il traffico tra due revisioni.
- Come eliminare gli avvii a freddo con le istanze minime.
2. Configurazione e requisiti
Creare una cartella principale
Crea una cartella principale per tutti gli esempi.
mkdir crf-codelab cd crf-codelab
Imposta le variabili di ambiente
Imposta le variabili di ambiente che verranno utilizzate in questo codelab.
gcloud config set project <YOUR-PROJECT-ID> REGION=<YOUR_REGION> PROJECT_ID=$(gcloud config get-value project)
Abilita API
Attiva tutti i servizi necessari:
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ eventarc.googleapis.com \ run.googleapis.com \ logging.googleapis.com \ pubsub.googleapis.com
3. Funzione HTTP
Per la prima funzione, creiamo una funzione Node.js autenticata che risponde alle richieste HTTP. Utilizziamo anche un timeout di 10 minuti per mostrare come una funzione può avere più tempo per rispondere alle richieste HTTP.
Crea
Crea una cartella per l'app e vai alla cartella:
mkdir hello-http cd hello-http
Crea un file index.js che risponde alle richieste HTTP:
const functions = require('@google-cloud/functions-framework');
functions.http('helloWorld', (req, res) => {
res.status(200).send('HTTP with Node.js in Cloud Run functions!');
});
Crea un file package.json per specificare le dipendenze:
{
"name": "nodejs-run-functions-codelab",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"@google-cloud/functions-framework": "^2.0.0"
}
}
Esegui il deployment
Esegui il deployment della funzione:
gcloud run deploy nodejs-run-function \
--source . \
--function helloWorld \
--base-image nodejs22 \
--region $REGION \
--timeout 600 \
--no-allow-unauthenticated
Questo comando utilizza i buildpack per trasformare il codice sorgente della funzione in un'immagine container pronta per la produzione.
Tieni presente quanto segue:
- il flag
--sourceviene utilizzato per indicare a Cloud Run di creare la funzione in un servizio basato su container eseguibile - Il flag
--function(nuovo) viene utilizzato per impostare il punto di ingresso del nuovo servizio in modo che corrisponda alla firma della funzione che vuoi richiamare. - Il flag
--base-image(nuovo) specifica l'ambiente dell'immagine di base per la funzione, ad esempionodejs22,python312,go123,java21,dotnet8,ruby33ophp83. Per maggiori dettagli sulle immagini di base e sui pacchetti inclusi in ogni immagine, consulta Immagini di base dei runtime. - (Facoltativo) il flag
--timeoutconsente alla funzione di avere un timeout più lungo per rispondere alle richieste HTTP. In questo esempio, vengono utilizzati 600 secondi per dimostrare un tempo di risposta di 10 minuti. - (facoltativo)
--no-allow-unauthenticatedper impedire che la funzione possa essere richiamata pubblicamente
Test
Testa la funzione con i seguenti comandi:
# get the Service URL SERVICE_URL="$(gcloud run services describe nodejs-run-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
Dovresti visualizzare il messaggio HTTP with Node.js in Cloud Run functions! come risposta.
4. Funzione Pub/Sub
Per la seconda funzione, creiamo una funzione Python attivata da un messaggio Pub/Sub pubblicato in un argomento specifico.
Configurare i token di autenticazione Pub/Sub
Se hai attivato l'account di servizio Pub/Sub il giorno 8 aprile 2021 o in una data precedente, concedi il ruolo iam.serviceAccountTokenCreator all'account di servizio Pub/Sub:
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)') gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com \ --role roles/iam.serviceAccountTokenCreator
Crea
Crea un argomento Pub/Sub da utilizzare per l'esempio:
TOPIC=cloud-run-functions-pubsub-topic gcloud pubsub topics create $TOPIC
Crea una cartella per l'app e vai alla cartella:
mkdir ../hello-pubsub cd ../hello-pubsub
Crea un file main.py che registri un messaggio contenente l'ID CloudEvent:
import functions_framework
@functions_framework.cloud_event
def hello_pubsub(cloud_event):
print('Pub/Sub with Python in Cloud Run functions! Id: ' + cloud_event['id'])
Crea un file requirements.txt con i seguenti contenuti per specificare le dipendenze:
functions-framework==3.*
Esegui il deployment
Esegui il deployment della funzione:
gcloud run deploy python-pubsub-function \
--source . \
--function hello_pubsub \
--base-image python313 \
--region $REGION \
--no-allow-unauthenticated
Recupera il numero di progetto da utilizzare per l'identità del service account.
PROJECT_NUMBER=$(gcloud projects list --filter="project_id:$PROJECT_ID" --format='value(project_number)')
Crea il trigger
gcloud eventarc triggers create python-pubsub-function-trigger \
--location=$REGION \
--destination-run-service=python-pubsub-function \
--destination-run-region=$REGION \
--event-filters="type=google.cloud.pubsub.topic.v1.messagePublished" \
--transport-topic=projects/$PROJECT_ID/topics/$TOPIC \
--service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
Test
Testa la funzione inviando un messaggio all'argomento:
gcloud pubsub topics publish $TOPIC --message="Hello World"
Dovresti vedere CloudEvent ricevuto nei log:
gcloud run services logs read python-pubsub-function --region $REGION --limit=10
5. Funzione Cloud Storage
Per la funzione successiva, creiamo una funzione Node.js che risponde agli eventi di un bucket Cloud Storage.
Configura
Per utilizzare le funzioni di Cloud Storage, concedi il ruolo IAM pubsub.publisher all'account di servizio Cloud Storage:
SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p $PROJECT_NUMBER) gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$SERVICE_ACCOUNT \ --role roles/pubsub.publisher
Crea
Crea una cartella per l'app e vai alla cartella:
mkdir ../hello-storage cd ../hello-storage
Crea un file index.js che risponda semplicemente agli eventi Cloud Storage:
const functions = require('@google-cloud/functions-framework');
functions.cloudEvent('helloStorage', (cloudevent) => {
console.log('Cloud Storage event with Node.js in Cloud Run functions!');
console.log(cloudevent);
});
Crea un file package.json per specificare le dipendenze:
{
"name": "nodejs-crf-cloud-storage",
"version": "0.0.1",
"main": "index.js",
"dependencies": {
"@google-cloud/functions-framework": "^2.0.0"
}
}
Esegui il deployment
Innanzitutto, crea un bucket Cloud Storage (o utilizza un bucket esistente):
export BUCKET_NAME="gcf-storage-$PROJECT_ID" export BUCKET="gs://gcf-storage-$PROJECT_ID" gsutil mb -l $REGION $BUCKET
Esegui il deployment della funzione:
gcloud run deploy nodejs-crf-cloud-storage \ --source . \ --base-image nodejs22 \ --function helloStorage \ --region $REGION \ --no-allow-unauthenticated
Una volta eseguito il deployment della funzione, puoi visualizzarla nella sezione Cloud Run di Cloud Console.
Ora crea il trigger Eventarc.
BUCKET_REGION=$REGION gcloud eventarc triggers create nodejs-crf-cloud-storage-trigger \ --location=$BUCKET_REGION \ --destination-run-service=nodejs-crf-cloud-storage \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET_NAME" \ --service-account=$PROJECT_NUMBER-compute@developer.gserviceaccount.com
Test
Testa la funzione caricando un file nel bucket:
echo "Hello World" > random.txt gsutil cp random.txt $BUCKET/random.txt
Dovresti vedere CloudEvent ricevuto nei log:
gcloud run services logs read nodejs-crf-cloud-storage --region $REGION --limit=10
6. Cloud Audit Logs
Per la funzione successiva, creiamo una funzione Node.js che riceve un evento Cloud Audit Logs quando viene creata un'istanza VM di Compute Engine. Di conseguenza, aggiunge un'etichetta alla VM appena creata, specificando l'autore della VM.
Determinare le VM Compute Engine appena create
Compute Engine genera due audit log quando viene creata una VM.
Il primo viene emesso all'inizio della creazione della VM. Il secondo viene emesso dopo la creazione della VM.
Nei log di controllo, i campi dell'operazione sono diversi e contengono i valori first: true e last: true. Il secondo audit log contiene tutte le informazioni necessarie per etichettare un'istanza, pertanto utilizzeremo il flag last: true per rilevarlo nelle funzioni Cloud Run.
Configura
Per utilizzare le funzioni di Cloud Audit Logs, devi abilitare gli audit log per Eventarc. Devi anche utilizzare un service account con il ruolo eventarc.eventReceiver.
- Attiva i tipi di log Abilita log di controllo di Cloud Lettura amministratore, Lettura dati e Scrittura dati per l'API Compute Engine.
- Concedi al service account Compute Engine predefinito il ruolo IAM
eventarc.eventReceiver:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \ --role roles/eventarc.eventReceiver
Crea la funzione
Questo codelab utilizza Node.js, ma puoi trovare altri esempi all'indirizzo https://github.com/GoogleCloudPlatform/eventarc-samples
Creare un file package.json
{
"dependencies": {
"googleapis": "^84.0.0"
}
}
Creare un file node.js
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
const { google } = require("googleapis");
var compute = google.compute("v1");
exports.labelVmCreation = async (cloudevent) => {
const data = cloudevent.body;
// in case an event has >1 audit log
// make sure we respond to the last event
if (!data.operation || !data.operation.last) {
console.log("Operation is not last, skipping event");
return;
}
// projects/dogfood-gcf-saraford/zones/us-central1-a/instances/instance-1
var resourceName = data.protoPayload.resourceName;
var resourceParts = resourceName.split("/");
var project = resourceParts[1];
var zone = resourceParts[3];
var instanceName = resourceParts[5];
var username = data.protoPayload.authenticationInfo.principalEmail.split("@")[0];
console.log(`Setting label username: ${username} to instance ${instanceName} for zone ${zone}`);
var authClient = await google.auth.getClient({
scopes: ["https://www.googleapis.com/auth/cloud-platform"]
});
// per docs: When updating or adding labels in the API,
// you need to provide the latest labels fingerprint with your request,
// to prevent any conflicts with other requests.
var labelFingerprint = await getInstanceLabelFingerprint(authClient, project, zone, instanceName);
var responseStatus = await setVmLabel(
authClient,
labelFingerprint,
username,
project,
zone,
instanceName
);
// log results of setting VM label
console.log(JSON.stringify(responseStatus, null, 2));
};
async function getInstanceLabelFingerprint(authClient, project, zone, instanceName) {
var request = {
project: project,
zone: zone,
instance: instanceName,
auth: authClient
};
var response = await compute.instances.get(request);
var labelFingerprint = response.data.labelFingerprint;
return labelFingerprint;
}
async function setVmLabel(authClient, labelFingerprint, username, project, zone, instanceName) {
var request = {
project: project,
zone: zone,
instance: instanceName,
resource: {
labels: { "creator": username },
labelFingerprint: labelFingerprint
},
auth: authClient
};
var response = await compute.instances.setLabels(request);
return response.statusText;
}
Esegui il deployment
Esegui il deployment della funzione:
gcloud run deploy gce-vm-labeler \ --source . \ --function labelVmCreation \ --region $REGION \ --no-allow-unauthenticated
Ora crea il trigger. Nota come la funzione filtra gli audit log per gli inserimenti di Compute Engine con il flag --trigger-event-filters.
gcloud eventarc triggers create gce-vm-labeler-trigger \ --location=$REGION \ --destination-run-service=gce-vm-labeler \ --destination-run-region=$REGION \ --event-filters="type=google.cloud.audit.log.v1.written,serviceName=compute.googleapis.com,methodName=v1.compute.instances.insert" \ --service-account=$ROJECT_NUMBER-compute@developer.gserviceaccount.com
Test
Imposta le variabili di ambiente:
# if you're using europe-west1 as your region
ZONE=europe-west1-d
VM_NAME=codelab-crf-auditlog
Esegui questo comando per creare una VM:
gcloud compute instances create $VM_NAME --zone=$ZONE --machine-type=e2-medium --image-family=debian-11 --image-project=debian-cloud
Una volta completata la creazione della VM, dovresti visualizzare l'etichetta creator aggiunta alla VM nella console Google Cloud nella sezione Informazioni di base o utilizzando il seguente comando:
gcloud compute instances describe $VM_NAME --zone=$ZONE
Dovresti vedere l'etichetta nell'output, come nell'esempio seguente:
... labelFingerprint: ULU6pAy2C7s= labels: creator: atameldev ...
Esegui la pulizia
Assicurati di eliminare l'istanza VM. Non verrà più utilizzato in questo lab.
gcloud compute instances delete $VM_NAME --zone=$ZONE
7. Suddivisione del traffico
Le funzioni Cloud Run supportano più revisioni delle funzioni, dividendo il traffico tra diverse revisioni ed eseguendo il rollback della funzione a una versione precedente.
In questo passaggio, eseguirai il deployment di due revisioni di una funzione e poi dividerai il traffico tra loro al 50%.
Crea
Crea una cartella per l'app e vai alla cartella:
mkdir ../traffic-splitting cd ../traffic-splitting
Crea un file main.py con una funzione Python che legge una variabile di ambiente di colore e risponde con Hello World in quel colore di sfondo:
import os
color = os.environ.get('COLOR')
def hello_world(request):
return f'<body style="background-color:{color}"><h1>Hello World!</h1></body>'
Crea un file requirements.txt con i seguenti contenuti per specificare le dipendenze:
functions-framework==3.*
Esegui il deployment
Esegui il deployment della prima revisione della funzione con uno sfondo arancione:
COLOR=orange gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
A questo punto, se testi la funzione visualizzando il trigger HTTP (l'URI di output del comando di deployment precedente) nel browser, dovresti visualizzare Hello World con uno sfondo arancione:

Esegui il deployment della seconda revisione con uno sfondo giallo:
COLOR=yellow gcloud run deploy hello-world-colors \ --source . \ --base-image python313 \ --function hello_world \ --region $REGION \ --allow-unauthenticated \ --update-env-vars COLOR=$COLOR
Poiché si tratta dell'ultima revisione, se testi la funzione, dovresti visualizzare Hello World con uno sfondo giallo:

Dividi il traffico 50-50
Per dividere il traffico tra le revisioni arancione e gialla, devi trovare gli ID revisione dei servizi Cloud Run. Questo è il comando per visualizzare gli ID revisione:
gcloud run revisions list --service hello-world-colors \ --region $REGION --format 'value(REVISION)'
L'output dovrebbe essere simile al seguente:
hello-world-colors-00001-man hello-world-colors-00002-wok
Ora, dividi il traffico tra queste due revisioni come segue (aggiorna X-XXX in base ai nomi delle revisioni):
gcloud run services update-traffic hello-world-colors \ --region $REGION \ --to-revisions hello-world-colors-0000X-XXX=50,hello-world-colors-0000X-XXX=50
Test
Testa la funzione visitando il suo URL pubblico. Metà delle volte dovresti vedere la revisione arancione e l'altra metà la revisione gialla:

Per saperne di più, consulta Rollback, rilasci graduali e migrazione del traffico.
8. Numero minimo di istanze
Nelle funzioni Cloud Run, puoi specificare un numero minimo di istanze di funzione da mantenere in uso e pronte per gestire le richieste. Ciò è utile per limitare il numero di avvii a freddo.
In questo passaggio, eseguirai il deployment di una funzione con inizializzazione lenta. Osserverai il problema dell'avvio a freddo. Poi, esegui il deployment della funzione con il valore dell'istanza minima impostato su 1 per eliminare l'avvio a freddo.
Crea
Crea una cartella per l'app e vai al suo interno:
mkdir ../min-instances cd ../min-instances
Crea un file main.go. Questo servizio Go ha una funzione init che rimane inattiva per 10 secondi per simulare un'inizializzazione lunga. Ha anche una funzione HelloWorld che risponde alle chiamate HTTP:
package p
import (
"fmt"
"net/http"
"time"
)
func init() {
time.Sleep(10 * time.Second)
}
func HelloWorld(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Slow HTTP Go in Cloud Run functions!")
}
Esegui il deployment
Esegui il deployment della prima revisione della funzione con il valore predefinito di istanze minime pari a zero:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated
Testa la funzione con questo comando:
# get the Service URL SERVICE_URL="$(gcloud run services describe go-slow-function --region $REGION --format 'value(status.url)')" # invoke the service curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
Vedrai un ritardo di 10 secondi (avvio a freddo) alla prima chiamata e poi vedrai il messaggio. Le chiamate successive dovrebbero essere restituite immediatamente.
Imposta il numero minimo di istanze
Per eliminare l'avvio a freddo nella prima richiesta, esegui nuovamente il deployment della funzione con il flag --min-instances impostato su 1 come segue:
gcloud run deploy go-slow-function \ --source . \ --base-image go123 \ --function HelloWorld \ --region $REGION \ --no-allow-unauthenticated \ --min-instances 1
Test
Testa di nuovo la funzione:
curl -H "Authorization: bearer $(gcloud auth print-identity-token)" -X GET $SERVICE_URL
Non dovresti più vedere il ritardo di 10 secondi nella prima richiesta. Il problema dell'avvio a freddo per la prima chiamata (dopo molto tempo) non si verifica più, grazie alle istanze minime.
Per ulteriori informazioni, vedi Utilizzo delle istanze minime.
9. Complimenti!
Congratulazioni per aver completato il codelab.
Argomenti trattati
- Panoramica di Cloud Run Functions e su come utilizzare gli aggiornamenti automatici delle immagini di base.
- Come scrivere una funzione che risponde alle chiamate HTTP.
- Come scrivere una funzione che risponde ai messaggi Pub/Sub.
- Come scrivere una funzione che risponde agli eventi Cloud Storage.
- Come suddividere il traffico tra due revisioni.
- Come eliminare gli avvii a freddo con le istanze minime.