Sviluppa la produzione in tre semplici passaggi con Cloud Run

1. Introduzione

Perché è così difficile gestire le applicazioni?

Uno dei motivi principali è che gli sviluppatori spesso devono svolgere anche il ruolo di amministratori di sistema part-time. Considera questo elenco (parziale) di problemi per sviluppare, eseguire il deployment e gestire un'applicazione web moderna di livello di produzione :

4d018476b4a73b47.png

Non so tu, ma queste sono tutte cose di cui non voglio preoccuparmi. Quello su cui voglio concentrarmi è la logica della mia applicazione:

6dfd143d20e5548b.png

In breve, questo è lo scopo di Cloud Run: darti la possibilità di concentrarti sulla tua app e lasciare a qualcun altro, ovvero Google, tutta l'amministrazione e la manutenzione. Google ha investito milioni di ore per perfezionare le proprie competenze in questo campo.

Oltre alle sfide amministrative menzionate sopra, devi anche affrontare:

  • Dipendenze: l'ambiente in cui viene eseguita l'app deve, ove possibile, corrispondere esattamente all'ambiente in cui è stata testata. Ciò può comprendere diverse dimensioni, tra cui sistema operativo, librerie di supporto, interprete o compilatore di linguaggio, configurazione hardware e molti altri fattori.
  • Distribuzione: il passaggio da un'incarnazione locale di un'app a una condivisa su internet spesso richiede un cambio di ambiente di runtime, un salto quantico in termini di complessità e una curva di apprendimento ripida.

Cloud Run si occupa di questi e molti altri problemi per te. Ma invece di fidarti della mia parola, creiamo insieme un'app e vediamo quanto è facile passare da un ambiente di sviluppo locale a un'app cloud di livello di produzione in pochi semplici passaggi.

Attività previste

  • Creerai una semplice app web e verificherai che funzioni come previsto nel tuo ambiente di sviluppo.
  • Poi passerai a una versione containerizzata della stessa app. Durante il percorso, scoprirai cosa significa containerizzazione e perché è così utile.
  • Infine, eseguirai il deployment della tua app sul cloud e vedrai quanto è facile gestire il servizio Cloud Run utilizzando la riga di comando e la console Google Cloud.

Cosa imparerai…

  • Come creare una semplice app server web in Python
  • Come inserire la tua app in un container Docker che viene eseguito ovunque
  • Come eseguire il deployment della tua app sul cloud in modo che chiunque possa provare la tua nuova creazione
  • Come semplificare ulteriormente i passaggi precedenti utilizzando Buildpack
  • Come utilizzare lo strumento a riga di comando Google Cloud e la UI web di Cloud Console

Cosa ti serve…

  • Un browser web
  • Un Account Google

Questo lab è rivolto a sviluppatori di tutti i livelli, inclusi i principianti. Anche se utilizzerai Python, non è necessario avere familiarità con la programmazione in Python per capire cosa sta succedendo, perché spiegheremo tutto il codice che utilizzerai.

2. Configurazione

5110b5081a1e1c49.png

Questa sezione descrive tutto ciò che devi fare per iniziare questo lab.

Configurazione dell'ambiente autonomo

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

96a9c957bc475304.png

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

Ricorda l'ID progetto, un nome univoco tra tutti i progetti Google Cloud (il nome sopra è già stato utilizzato e non funzionerà per te, mi dispiace). In questo codelab verrà chiamato PROJECT_ID.

  1. Successivamente, dovrai abilitare la fatturazione in Cloud Console per utilizzare le risorse Google Cloud.

L'esecuzione di questo codelab non dovrebbe costare molto, se non nulla. Assicurati di seguire le istruzioni riportate nella sezione "Pulizia", che ti consiglia come arrestare le risorse in modo da non incorrere in addebiti oltre questo tutorial. I nuovi utenti di Google Cloud possono beneficiare del programma prova senza costi di 300$.

Avvia Cloud Shell

In questo lab lavorerai in una sessione di Cloud Shell, un interprete di comandi ospitato da una macchina virtuale in esecuzione nel cloud di Google. Potresti eseguire facilmente questa sezione in locale sul tuo computer, ma l'utilizzo di Cloud Shell offre a chiunque l'accesso a un'esperienza riproducibile in un ambiente coerente. Dopo il lab, puoi riprovare questa sezione sul tuo computer.

704a7b7491bd157.png

Attiva Cloud Shell

  1. Nella console Cloud, fai clic su Attiva Cloud Shell 4292cbf4971c9786.png.

bce75f34b2c53987.png

Se non hai mai avviato Cloud Shell, viene visualizzata una schermata intermedia (sotto la piega) che ne descrive le funzionalità. In questo caso, fai clic su Continua e non comparirà più. Ecco come si presenta la schermata intermedia:

70f315d7b402b476.png

Bastano pochi istanti per eseguire il provisioning e connettersi a Cloud Shell.

fbe3a0674c982259.png

Questa macchina virtuale è caricata con tutti gli strumenti per sviluppatori di cui hai bisogno. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni e l'autenticazione della rete. Gran parte del lavoro per questo codelab, se non tutto, può essere svolto semplicemente con un browser o con Chromebook.

Una volta eseguita la connessione a Cloud Shell, dovresti vedere che il tuo account è già autenticato e il progetto è già impostato sul tuo ID progetto.

  1. Esegui questo comando in Cloud Shell per verificare che l'account sia autenticato:
gcloud auth list

Output comando

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Esegui questo comando in Cloud Shell per verificare che il comando gcloud conosca il tuo progetto:
gcloud config list project

Output comando

[core]
project = <PROJECT_ID>

In caso contrario, puoi impostarlo con questo comando:

gcloud config set project <PROJECT_ID>

Output comando

Updated property [core/project].

Imposta alcune variabili di ambiente nel terminale che semplificheranno i passaggi successivi:

export PROJ=$GOOGLE_CLOUD_PROJECT 
export APP=hello 
export PORT=8080
export REGION="us-central1"
export TAG="gcr.io/$PROJ/$APP"

Abilita le API

Nei passaggi successivi vedrai dove (e perché) sono necessari questi servizi, ma per il momento esegui questo comando per concedere al tuo progetto l'accesso ai servizi Cloud Build, Container Registry e Cloud Run:

gcloud services enable cloudbuild.googleapis.com         \
                       containerregistry.googleapis.com  \
                       run.googleapis.com          

Dovrebbe essere visualizzato un messaggio di operazione riuscita simile a questo:

Operation "operations/acf.cc11852d-40af-47ad-9d59-477a12847c9e" finished successfully.

3. Crea un'app web semplice

eef530b56b8e93a3.png

Inizia facendo clic sul pulsante Open Editor nella parte superiore del riquadro di Cloud Shell. Ha questo aspetto:

9b81c8a37a6bcdd8.png

Ti troverai quindi in un ambiente IDE simile a Visual Studio Code, in cui potrai creare progetti, modificare il codice sorgente, eseguire i tuoi programmi e così via. Se lo schermo è troppo piccolo, puoi espandere o ridurre la linea di divisione tra la console e la finestra di modifica/terminale trascinando la barra orizzontale tra le due regioni, evidenziata qui:

8dea35450851af53.png

Puoi passare dall'editor al terminale e viceversa facendo clic sui pulsanti Open Editor e Open Terminal, rispettivamente. Ora prova a passare da un ambiente all'altro.

Successivamente, crea una cartella in cui archiviare il tuo lavoro per questo lab selezionando File -> Nuova cartella, inserisci hello e fai clic su OK. Tutti i file che crei in questo lab e tutto il lavoro che svolgi in Cloud Shell verranno eseguiti in questa cartella.

Ora crea un file requirements.txt. Indica a Python le librerie da cui dipende la tua app. Per questa semplice app web, utilizzerai un modulo Python molto diffuso per la creazione di server web chiamato Flask e un framework per server web chiamato gunicorn. Nella finestra dell'editor di Cloud, fai clic sul menu File->Nuovo file per creare un nuovo file. Quando ti viene chiesto il nome del nuovo file, inserisci requirements.txt e premi il pulsante OK. Assicurati che il nuovo file finisca nella cartella del progetto hello.

Inserisci le seguenti righe nel nuovo file per specificare che la tua app dipende dal pacchetto Python Flask e dal server web gunicorn.

Flask
gunicorn

Non devi salvare esplicitamente questo file perché Cloud Editor salva automaticamente le modifiche.

Versione 1: Hello world!

Utilizzando la stessa tecnica, crea un altro nuovo file denominato main.py. Questo sarà il file di origine Python principale (e unico) della tua app. Anche in questo caso, assicurati che il nuovo file finisca nella cartella del progetto hello.

Inserisci il seguente codice in questo file:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
@app.route("/", methods=["GET"])
def say_hello():
    html = "<h1>Hello world!</h1>"
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Torna al terminale e passa alla cartella del progetto con questo comando:

cd hello

Esegui questo comando per installare le dipendenze del progetto:

pip3 install -r requirements.txt

Ora avvia l'app eseguendo questo comando nel terminale:

python3 main.py

A questo punto, la tua app è in esecuzione sulla macchina virtuale dedicata alla sessione di Cloud Shell. Cloud Shell include un meccanismo proxy che ti consente di accedere ai server web (come quello appena avviato) in esecuzione sulla tua macchina virtuale da qualsiasi punto di internet.

Fai clic sul pulsante web preview e poi sulla voce di menu Preview on Port 8080 come segue:

fe45e0192080efd6.png

Si aprirà una scheda del browser web con l'app in esecuzione, che dovrebbe avere un aspetto simile a questo:

b1f06501509aefb9.png

Versione 2: mirroring del percorso dell'URL

Torna a Cloud Editor (tramite il pulsante Open Editor) e aggiungi il supporto per l'echo di un suffisso URL facoltativo aggiornando il file main.py come segue:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from environment.

# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])     # ← NEW
def say_hello(name="world"):               # ← MODIFIED
    html = f"<h1>Hello {name}!</h1>"       # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Torna al terminale (tramite il pulsante Open Terminal) e inserisci control-C (tieni premuto il tasto Ctrl mentre premi "C") per arrestare l'app in esecuzione e riavviarla inserendo:

python3 main.py

Fai di nuovo clic sul pulsante web preview e poi sulla voce di menu Preview on Port 8080 per aprire una scheda del browser web con l'app in esecuzione. Dovresti visualizzare di nuovo il messaggio "Hello world!", ma ora sostituisci il testo dell'URL dopo la barra con una stringa a tua scelta (ad es. /your-name) e verifica di visualizzare un risultato simile a questo:

93b87996f88fa370.png

Versione 3: colori casuali

Ora aggiungi il supporto per i colori di sfondo casuali tornando a Cloud Editor (tramite il pulsante Open Editor) e aggiornando il file main.py come segue:

from flask import Flask
import os
import random

app = Flask(__name__)  # Create a Flask object.
PORT = os.environ.get("PORT")  # Get PORT setting from the environment.

# This function decides whether foreground text should be
# displayed in black or white, to maximize fg/bg contrast.
def set_text_color(rgb):                      # ← NEW
    sum = round(                              # ← NEW
        (int(rgb[0]) * 0.299)                 # ← NEW
        + (int(rgb[1]) * 0.587)               # ← NEW
        + (int(rgb[2]) * 0.114)               # ← NEW
    )                                         # ← NEW
    return "black" if sum > 186 else "white"  # ← NEW


# The app.route decorator routes any GET requests sent to the root path
# to this function, which responds with a "Hello world!" HTML document.
# If something is specified as the URL path (after the '/'), say_hello()
# responds with "Hello X", where X is the string at the end of the URL.
# To verify each new invocation of these requests, the HTML document
# includes CSS styling to produce a randomly colored background.
@app.route("/", methods=["GET"])
@app.route("/<name>", methods=["GET"])
def say_hello(name="world"):
    bg = random.sample(range(1, 255), 3)                       # ← NEW
    hex = (int(bg[0]) * 256) + (int(bg[1]) * 16) + int(bg[2])  # ← NEW
    fg_color = set_text_color(bg)                              # ← NEW
    bg_color = f"#{hex:06x}"                                   # ← NEW
    style = f"color:{fg_color}; background-color:{bg_color}"   # ← NEW
    html = f'<h1 style="{style}">Hello {name}!</h1>'           # ← MODIFIED
    return html


# This code ensures that your Flask app is started and listens for
# incoming connections on the local interface and port 8080.
if __name__ == "__main__":
    app.run(host="0.0.0.0", port=PORT)

Torna al terminale (tramite il pulsante Open Terminal) e inserisci control-C (tieni premuto il tasto Ctrl mentre premi "C") per arrestare l'app in esecuzione e riavviarla inserendo:

python3 main.py

Fai di nuovo clic sul pulsante web preview e poi sulla voce di menu Preview on Port 8080 per aprire una scheda del browser web con l'app in esecuzione. Dovresti visualizzare il testo generato, con il suffisso specificato o la stringa predefinita "Hello world!", visualizzato davanti a uno sfondo colorato in modo casuale, come questo:

baf8d028f15ea7f4.png

Ricarica la pagina alcune volte per vedere che il colore di sfondo casuale cambia ogni volta che visiti l'app.

A questo punto, la tua app è pronta. Congratulazioni. Nel passaggio successivo, imparerai a pacchettizzare la tua app in un container e perché è utile farlo.

4. Containerizza la tua app

17cc234ec3325a8a.png

Che cos'è un container?

I container in generale e Docker in particolare ci consentono di creare una scatola modulare in cui eseguire un'applicazione con tutte le sue dipendenze raggruppate. Il risultato è un'immagine container. In questa sezione creerai un'immagine container, che utilizzerai per incapsulare l'applicazione e tutte le relative dipendenze.

A proposito di dipendenze, in un passaggio precedente, quando eseguivi l'app in un ambiente di sviluppo, dovevi eseguire pip3 install -r requirements.txt e assicurarti che il file requirements.txt contenesse tutte le librerie dipendenti e le versioni corrispondenti. Con i container, installi questi requisiti quando generi l'immagine container, quindi non è necessario che il consumatore del container si preoccupi di installare nulla.

Questa immagine container costituirà il blocco di base per il deployment dell'applicazione su Cloud Run. Poiché i container possono essere utilizzati su quasi tutti i server virtuali o reali, questo ci consente di eseguire il deployment dell'applicazione ovunque tu voglia e di spostarla da un fornitore di servizi a un altro o da on-premise al cloud.

I container contribuiscono a rendere le tue applicazioni:

  • riproducibili: i container sono autonomi e completi
  • portabili: i container sono blocchi di costruzione intersettoriali, che consentono la portabilità delle applicazioni tra provider e ambienti cloud

In breve, i container offrono la possibilità di "scrivere una volta ed eseguire ovunque". Un'eccezione a questa regola è che il contenitore generato è vincolato all'esecuzione sul tipo di processore su cui è stato creato, ma esistono modi per generare versioni del contenitore anche per altre configurazioni hardware.

Basta chiacchiere, creiamo un contenitore. Utilizzerai una tecnologia specifica per creare un container chiamato Docker.

Nell'editor di Cloud, crea un nuovo file denominato Dockerfile. Questo file è un progetto per la costruzione dell'immagine. Indica a Docker l'ambiente operativo e il codice sorgente, come installare le dipendenze, creare l'app ed eseguire il codice.

# Use an official lightweight Python image.
FROM python:3.9-slim

# Copy local code to the container image.
WORKDIR /app
COPY main.py .
COPY requirements.txt .

# Install dependencies into this container so there's no need to 
# install anything at container run time.
RUN pip install -r requirements.txt

# Service must listen to $PORT environment variable.
# This default value facilitates local development.
ENV PORT 8080

# Run the web service on container startup. Here you use the gunicorn
# server, with one worker process and 8 threads. For environments 
# with multiple CPU cores, increase the number of workers to match 
# the number of cores available.
CMD exec gunicorn --bind 0.0.0.0:$PORT --workers 1 --threads 8 --timeout 0 main:app

In Cloud Terminal, crea l'immagine container utilizzando Cloud Build eseguendo questo comando:

gcloud builds submit --tag $TAG

Una volta eseguito il push in Artifact Registry, vedrai un messaggio SUCCESS contenente il nome dell'immagine, che dovrebbe essere simile a questo: gcr.io/<project-id>/hello. L'immagine è ora archiviata in Google Container Registry e può essere riutilizzata quando e dove vuoi.

Puoi elencare tutte le immagini container associate al tuo progetto corrente usando questo comando:

gcloud container images list

Ora esegui e testa l'applicazione in locale da Cloud Shell utilizzando questi comandi docker:

docker run -p $PORT:$PORT -e PORT=$PORT $TAG

L'opzione -p $PORT:$PORT indica a Docker di mappare la porta esterna $PORT (impostata su 8080 sopra) nell'ambiente host allo stesso numero di porta all'interno del container in esecuzione. In questo modo la vita è più facile perché il codice del server che scrivi e il numero di porta esterno a cui ti connetti quando testi l'app saranno gli stessi (8080), ma potresti anche utilizzare l'opzione -p per mappare qualsiasi porta esterna arbitraria sull'host a qualsiasi porta interna desiderata all'interno del container.

L'opzione -e PORT=$PORT indica a Docker di rendere disponibile la variabile di ambiente $PORT (impostata su 8080 sopra) alla tua app in esecuzione all'interno del container.

Ora puoi testare l'app puntando un browser web al codice Python in esecuzione all'interno del contenitore. Nella finestra Cloud Shell, fai clic sull'icona "Anteprima web" e seleziona "Anteprima sulla porta 8080", come hai fatto nel passaggio precedente.

Il risultato dovrebbe essere familiare: dovresti vedere il testo generato davanti a uno sfondo colorato in modo casuale, proprio come quando hai eseguito l'app direttamente nel terminale Cloud Shell. Ricarica la pagina alcune volte per vedere che il colore di sfondo casuale cambia ogni volta che visiti l'app.

Complimenti! Ora hai eseguito una versione containerizzata della tua app. Nella sezione successiva, senza toccare una riga di codice, trasformerai l'immagine container in un'app web di qualità di produzione.

5. Al cloud…

1b0665d94750ded6.gif

Ora che hai containerizzato l'app, vorrai condividere questa meraviglia con il resto del mondo, quindi è il momento di eseguirne il deployment nel cloud. Ma vorresti fare molto di più che condividerlo. Vuoi assicurarti che:

  • funziona in modo affidabile: ottieni la tolleranza automatica agli errori in caso di arresto anomalo di un computer che esegue la tua app
  • scala automaticamente: la tua app sarà in grado di gestire livelli di traffico elevati e ridurrà automaticamente il suo footprint quando non viene utilizzata
  • riduce al minimo i costi, in quanto non ti addebita le risorse che non utilizzi. Ti vengono addebitate solo le risorse consumate durante la risposta al traffico.
  • è accessibile tramite un nome di dominio personalizzato: hai accesso a una soluzione con un clic per assegnare un nome di dominio personalizzato al tuo servizio
  • offre un tempo di risposta eccellente: gli avvii a freddo sono ragionevolmente reattivi, ma puoi perfezionarli specificando una configurazione di istanza minima.
  • supporta la crittografia end-to-end utilizzando la sicurezza web SSL/TLS standard. Quando implementi un servizio, ottieni la crittografia web standard e i certificati richiesti corrispondenti, senza costi e automaticamente.

Se esegui il deployment dell'app in Google Cloud Run, ottieni tutto quanto sopra e altro ancora.

Esegui il deployment dell'app in Cloud Run

Innanzitutto, modifichiamo l'app in modo che tu possa distinguere la nuova revisione da quella precedente. Modifica il file main.py in modo che il messaggio predefinito cambi da "Hello world!" a "Hello from Cloud Run!". In altre parole, modifica questa riga in main.py da:

def say_hello(name="world"):

a questo:

def say_hello(name="from Cloud Run"):

Cloud Run è regionale, il che significa che l'infrastruttura che esegue i tuoi servizi Cloud Run si trova in una regione specifica ed è gestita da Google per essere disponibile in modo ridondante in tutte le zone all'interno di quella regione. Nella sezione "Configurazione" sopra, hai definito una regione predefinita tramite la variabile di ambiente REGION.

Ricrea l'immagine container ed esegui il deployment dell'applicazione containerizzata su Cloud Run con questo comando:

gcloud builds submit --tag $TAG
gcloud run deploy "$APP"   \
  --image "$TAG"           \
  --platform "managed"     \
  --region "$REGION"       \
  --allow-unauthenticated
  • Puoi anche definire una regione predefinita con gcloud config set run/region $REGION.
  • L'opzione --allow-unauthenticated rende il servizio disponibile pubblicamente. Per evitare richieste non autenticate, utilizza --no-allow-unauthenticated.

L'immagine specificata qui è l'immagine Docker che hai creato nell'ultimo passaggio. Grazie al servizio Cloud Build, che ha archiviato l'immagine risultante in Google Container Registry, il servizio Cloud Run può trovarla ed eseguirne il deployment per te.

Attendi qualche istante fino al completamento del deployment. Se l'operazione riesce, la riga di comando visualizza l'URL del servizio:

Deploying container to Cloud Run service [hello] in project [PROJECT_ID...
✓ Deploying new service... Done.                                   
  ✓ Creating Revision... Revision deployment finished. Waiting for health check...
  ✓ Routing traffic...
  ✓ Setting IAM Policy...
Done.
Service [hello] revision [hello-...] has been deployed and is serving 100 percent of traffic.
Service URL: https://hello-....a.run.app

Puoi anche recuperare l'URL del servizio con questo comando:

gcloud run services describe hello  \
  --platform managed                \
  --region $REGION                  \
  --format "value(status.url)"

Dovresti visualizzare un risultato simile a questo:

https://hello-....a.run.app

Questo link è un URL dedicato, con sicurezza TLS, per il tuo servizio Cloud Run. Questo link è permanente (a condizione che tu non disattivi il servizio) e utilizzabile ovunque su internet. Non utilizza il meccanismo proxy di Cloud Shell menzionato in precedenza, che dipendeva da una macchina virtuale temporanea.

Fai clic su Service URL evidenziato per aprire una scheda del browser web con l'app in esecuzione. Il risultato dovrebbe mostrare il messaggio "Hello from Cloud Run!" (Ciao da Cloud Run!) su uno sfondo colorato in modo casuale.

Complimenti! La tua app è ora in esecuzione nella cloud di Google. Senza doverci pensare, la tua app è disponibile pubblicamente, con crittografia TLS (HTTPS) e scalabilità automatica a livelli di traffico sbalorditivi.

Ma penso che questo processo potrebbe essere ancora più semplice…

6. Creare automaticamente il container

Tutto questo è molto interessante, ma cosa succede se non voglio nemmeno pensare a Dockerfile e container? Cosa succede se, come la maggior parte degli sviluppatori, voglio solo concentrarmi sulla scrittura del codice dell'applicazione e lasciare che qualcun altro si occupi del relativo contenitore? Beh, sei fortunato perché Cloud Run supporta uno standard open source chiamato Buildpacks, che esiste proprio per questo motivo: automatizzare il processo di produzione di un container da una raccolta di file di origine.

Tieni presente che in alcuni casi uno sviluppatore potrebbe preferire utilizzare un Dockerfile esplicito, ad esempio se vuole un elevato grado di personalizzazione nella creazione del container. Tuttavia, per casi comuni come questo esercizio, i buildpack funzionano bene ed evitano la necessità di creare manualmente un Dockerfile. Modifichiamo il codice per utilizzare i buildpack.

Innanzitutto, modifichiamo l'app in modo che tu possa distinguere la nuova revisione da quella precedente. Modifica il file main.py in modo che il messaggio predefinito cambi da "Hello from Cloud Run!" a "Hello from Cloud Run with Buildpacks!". In altre parole, modifica questa riga in main.py da:

def say_hello(name="from Cloud Run"):

a questo:

def say_hello(name="from Cloud Run with Buildpacks"):

Ora sfruttiamo i buildpack creando un nuovo file denominato Procfile. Crea il file in Cloud Editor e inserisci questa riga di testo:

web: python3 main.py

Questo indica al sistema buildback come eseguire l'app nel container generato automaticamente. Con questa istruzione, non hai più bisogno di un Dockerfile. Per verificarlo, elimina il Dockerfile ed esegui questo comando nel terminale Cloud Shell:

gcloud beta run deploy "$APP"  \
    --source .                 \
    --platform "managed"       \
    --region "$REGION"         \
    --allow-unauthenticated

Questo comando è simile a quello eseguito per il deployment dell'app nell'ultimo passaggio, ma questa volta hai sostituito l'opzione --image con l'opzione --source .. In questo modo, il comando gcloud sa che vuoi utilizzare i buildpack per creare l'immagine container in base ai file sorgente trovati nella directory corrente (dot in --source . è l'abbreviazione della directory corrente). Poiché il servizio gestisce implicitamente l'immagine container, non devi specificare un'immagine in questo comando gcloud.

Verifica ancora una volta che il deployment funzioni facendo clic su Service URL evidenziato per aprire una scheda del browser web con l'app in esecuzione e assicurati che il servizio visualizzi "Hello from Cloud Run with Buildpacks!" (Ciao da Cloud Run con Buildpacks!) davanti a uno sfondo colorato in modo casuale.

Tieni presente che, utilizzando i buildpack per produrre il tuo Dockerfile, hai ridotto i tre semplici passaggi a due:

  1. Crea un'app nell'ambiente di sviluppo.
  2. Esegui il deployment del codice identico nel cloud con un solo comando.

7. Devo utilizzare la riga di comando?

No! Come per quasi tutti i servizi Google Cloud, esistono tre modi per interagire con Cloud Run:

  • Lo strumento a riga di comando gcloud, che hai appena visto.
  • Un'interfaccia utente web avanzata, tramite la console Cloud, che supporta uno stile di interazione intuitivo di tipo point-and-click.
  • A livello di programmazione, utilizzando le librerie client di Google disponibili per molti linguaggi popolari, tra cui Java, C#, Python, Go, Javascript, Ruby, C/C++ e altri.

Eseguiamo il deployment di un'istanza aggiuntiva dell'app Cloud Run utilizzando la UI della console. Vai alla pagina di destinazione del servizio Cloud Run tramite il menu in alto a sinistra:

e2b4983b38c81796.png

Dovresti quindi visualizzare un riepilogo dei tuoi servizi Cloud Run, come questo:

b335e7bf0a3af845.png

Fai clic sul link "Crea servizio" per avviare la procedura di deployment:

51f61a8ddc7a4c0b.png

Inserisci "hello-again" come nome del servizio, accetta la piattaforma di deployment e la regione predefinite e fai clic su "Avanti".

8a17baa45336c4c9.png

Inserisci questo URL per l'immagine container: gcr.io/cloudrun/hello, che è un container creato da Google a scopo di test, e fai clic sul menu a discesa "Impostazioni avanzate" per visualizzare alcune delle numerose impostazioni di configurazione disponibili. Per citarne solo alcuni che puoi personalizzare:

  • numero di porta e punto di ingresso del container (che sostituirà il punto di ingresso specificato durante la creazione del container)
  • hardware: memoria e numero di CPU
  • scalabilità: istanze minime e massime
  • variabili di ambiente
  • Altri: impostazione del timeout della richiesta, numero massimo di richieste per container, HTTP/2

Fai clic sul pulsante "Avanti" per avanzare nella finestra di dialogo. La finestra di dialogo successiva ti consente di specificare come viene attivato il servizio. Per "In entrata", seleziona "Consenti tutto il traffico" e per "Autenticazione", seleziona "Consenti traffico non autenticato".

e78281d1cff3418.png

Queste sono le impostazioni più liberali, in quanto consentono a chiunque di accedere alla tua app Cloud Run, da qualsiasi punto di internet pubblico, senza specificare le credenziali di autenticazione. Potresti preferire impostazioni più restrittive per la tua app, ma per questo esercizio di apprendimento semplificheremo le cose.

Ora fai clic sul pulsante Create per creare il servizio Cloud Run. Dopo alcuni secondi, dovresti vedere il nuovo servizio nell'elenco riepilogativo dei servizi Cloud Run. La riga di riepilogo fornisce l'ultimo deployment (data/ora e autore) insieme ad alcune impostazioni di configurazione chiave. Fai clic sul link del nome del servizio per visualizzare in dettaglio il nuovo servizio.

Per verificare il servizio, fai clic sull'URL mostrato nella parte superiore della pagina di riepilogo, come evidenziato nell'esempio riportato di seguito:

6c35cf0636dddc51.png

Il risultato dovrebbe essere simile a questo:

3ba6ab4fe0da1f84.png

Ora che hai eseguito il deployment di un nuovo servizio Cloud Run, seleziona la scheda REVISIONS per visualizzare alcuni modi per gestire più deployment.

2351ee7ec4a356f0.png

Per eseguire il deployment di nuove revisioni direttamente dalla console, puoi fare clic sul pulsante EDIT & DEPLOY NEW REVISION, come evidenziato nello screenshot di esempio riportato di seguito:

a599fa88d00d6776.png

Fai clic su questo pulsante ora per creare una nuova revisione. Accanto all'URL del container, fai clic sul pulsante SELECT, come mostrato di seguito:

5fd1b1f8e1f11d40.png

Nella finestra di dialogo visualizzata, individua la semplice app web che hai eseguito il deployment da Cloud Build utilizzando Buildpack in precedenza e fai clic su Seleziona. Assicurati di scegliere l'immagine container in

gcr.io/<project>/cloud-run-source-deploy

cartella , in questo modo:

8a756c6157face3a.png

Una volta selezionato, scorri verso il basso e fai clic sul pulsante DEPLOY. Ora hai eseguito il deployment di una nuova revisione della tua app. Per verificare, visita di nuovo l'URL del servizio e verifica di visualizzare l'app web colorata "Hello from Cloud Run with Buildpacks!".

Come puoi vedere, la scheda Revisioni fornisce un riepilogo di ogni revisione di cui hai eseguito il deployment e ora dovresti vedere due revisioni per questo servizio. Puoi selezionare una revisione specifica facendo clic sul pulsante di opzione a sinistra del nome della revisione, che mostrerà un riepilogo dei dettagli della revisione sul lato destro dello schermo. Se selezioni questi pulsanti, puoi vedere che le due revisioni derivano da due immagini container diverse.

Il pulsante MANAGE TRAFFIC consente di modificare la distribuzione delle richieste in entrata inviate a una determinata revisione. Questa possibilità di perfezionare la quantità di traffico inviata a una determinata revisione consente diversi casi d'uso preziosi:

  • Testare una nuova versione dell'app con una piccola parte del traffico in entrata
  • ripristinare il traffico da una release problematica a una revisione precedente
  • Test A/B

Trova il pulsante MANAGE TRAFFIC qui:

519d3c22ae028287.png

Configura una suddivisione del traffico 50/50 tra le due revisioni specificando una suddivisione del traffico 50/50 come segue:

8c37d4f115d9ded4.png

Ora fai clic sul pulsante SALVA e verifica la suddivisione 50/50 visitando ripetutamente l'URL del servizio e controlla che, in media, metà delle richieste vengano gestite dalla revisione attuale ("Hello from Cloud Run with Buildpacks!") e metà dalla revisione precedente ("It's running!").

Altre schede della pagina Dettagli del servizio offrono la possibilità di monitorare prestazioni, traffico e log, che forniscono informazioni preziose sul funzionamento del servizio. Puoi anche perfezionare l'accesso al tuo servizio tramite la scheda "Autorizzazioni". Esplora le schede di questa pagina per farti un'idea delle funzionalità disponibili.

Interfaccia programmatica

Come indicato in precedenza, hai anche la possibilità di creare, eseguire il deployment e gestire i tuoi servizi Cloud Run in modo programmatico. Per le attività manuali, questa opzione è più avanzata della riga di comando o della console web, ma è sicuramente la soluzione ideale per automatizzare i servizi Cloud Run. Hai la possibilità di utilizzare le librerie client di Google in diversi linguaggi di programmazione comuni.

8. Testare l'app

198ada162d1f0bf1.png

In questo passaggio finale, eseguirai un test di carico artificiale per stressare la tua app e osservare come viene scalata in base alla domanda in entrata. Utilizzerai uno strumento chiamato hey, preinstallato in Cloud Shell, che ci consente di eseguire test di carico e presentare i risultati.

Esegui il test

Nel terminale Cloud Shell, esegui questo comando per eseguire un test di carico:

hey -q 1000 -c 200 -z 30s https://hello-...run.app

Gli argomenti del comando vengono interpretati come segue:

  • -q 1000: prova a gestire il carico a circa 1000 richieste al secondo
  • -c 200 - allocate 200 parallel workers
  • -z 30s - run the load test for 30 seconds
  • assicurati di utilizzare l'URL del servizio come ultimo argomento in questa riga di comando

I risultati del test dovrebbero essere simili a questi:

 Summary:
 Total:        30.2767 secs
 Slowest:      3.3633 secs
 Fastest:      0.1071 secs
 Average:      0.1828 secs
 Requests/sec: 1087.2387
 Total data:   3028456 bytes
 Size/request: 92 bytes

Response time histogram:
 0.107 [1]     |
 0.433 [31346] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
 0.758 [1472]  |■■
 1.084 [82]    |
 1.410 [4]     |
...

Latency distribution:
...
 50% in 0.1528 secs
 75% in 0.1949 secs
 90% in 0.2442 secs
 95% in 0.4052 secs
 99% in 0.7062 secs

Details (average, fastest, slowest):
...
 req write:    0.0000 secs, 0.0000 secs, 0.0232 secs
 resp wait:    0.1824 secs, 0.1070 secs, 3.2953 secs
 resp read:    0.0000 secs, 0.0000 secs, 0.0010 secs
Status code distribution:
 [200] 32918 responses

Questo riepilogo ci fornisce diverse informazioni interessanti:

  • Sono state inviate 32.918 richieste a circa 1000 al secondo per 30 secondi.
  • Non sono stati rilevati errori (solo risposte HTTP 200).
  • La latenza media era di 180 ms.
  • La latenza minima è stata di 107 ms, il caso peggiore è stato di 3,3 s
  • La latenza del 90° percentile era di 244 ms.

Se controlli la scheda METRICS nella console Cloud Run, puoi vedere il lato server della storia del rendimento:

e635c6831c468dd3.png

9. Pulizia

Sebbene non siano previsti addebiti per Cloud Run quando il servizio non è in uso, ti potrebbero comunque essere addebitati i costi di archiviazione dell'immagine container creata.

Puoi eliminare il tuo progetto GCP per evitare addebiti, interrompendo così la fatturazione per tutte le risorse utilizzate all'interno di quel progetto, o semplicemente eliminare l'immagine del container utilizzando questo comando:

gcloud container images delete $TAG

Per eliminare i servizi Cloud Run, utilizza questi comandi:

gcloud run services delete hello --platform managed --region $REGION --quiet
gcloud run services delete hello-again --platform managed --region $REGION --quiet

10. Ce l'hai fatta!

9a31f4fdbbf1ddcb.png

Congratulazioni. Hai creato ed eseguito il deployment di un'app Cloud Run di produzione. Durante il percorso, hai imparato a conoscere i container e a crearne uno. Hai visto quanto è facile eseguire il deployment dell'app con Cloud Run, utilizzando sia lo strumento a riga di comando gcloud sia la console Cloud. Ora sai come condividere le tue brillanti creazioni con il mondo intero.

Voglio lasciarti con una domanda importante:

Una volta che l'app funziona nel tuo ambiente di sviluppo, quante righe di codice hai dovuto modificare per eseguirne il deployment nel cloud, con tutti gli attributi di livello di produzione offerti da Cloud Run?

La risposta, ovviamente, è zero. :)

Codelab da provare...

Altre fantastiche funzionalità da esplorare…

Documenti di riferimento…

11. Invito all'azione

Logo Google Cloud

Se questo codelab ti è piaciuto e probabilmente trascorrerai più tempo a lavorare con Google Cloud, ti consigliamo di aderire a Google Cloud Innovators oggi stesso.

logo del badge come membro generico di Innovators

Google Cloud Innovators è senza costi e include:

  • Discussioni dal vivo, sessioni di domande e risposte e roadmap per conoscere le ultime novità direttamente dai Googler
  • le ultime notizie di Google Cloud direttamente nella tua posta in arrivo
  • Badge digitale e sfondo per videoconferenze
  • 500 crediti per lab e corsi su Skills Boost

Fai clic qui per registrarti.