1. Introduzione
Ultimo aggiornamento: 01-11-2024
Come faccio a modernizzare una vecchia applicazione PHP su Google Cloud?
(📽️ guarda un video introduttivo di 7 minuti a questo codelab)
È comune avere applicazioni legacy on-premise che devono essere modernizzate. Ciò significa renderli scalabili, sicuri e di possibile implementazione in ambienti diversi.
In questo workshop imparerai a:
- Esegui il containerizzazione dell'applicazione PHP.
- Passa a un servizio di database gestito ( Cloud SQL).
- Esegui il deployment in Cloud Run (è un'alternativa a zero operazioni a GKE/Kubernetes).
- Proteggi l'applicazione con Identity and Access Management (IAM) e Secret Manager.
- Definisci una pipeline CI/CD tramite Cloud Build. Cloud Build può essere collegato al tuo repository Git ospitato su provider Git popolari come GitHub o GitLab ed essere attivato, ad esempio, a ogni push al main.
- Ospita le immagini dell'applicazione su Cloud Storage. Questo viene ottenuto tramite il montaggio e non è necessario alcun codice per modificare l'app.
- Introduci la funzionalità di IA generativa tramite Gemini, orchestrata tramite Cloud Functions (serverless).
- Acquisisci familiarità con gli SLOs e gestisci la tua app appena aggiornata.
Seguendo questi passaggi, puoi modernizzare gradualmente la tua applicazione PHP, migliorandone la scalabilità, la sicurezza e la flessibilità di deployment. Inoltre, il passaggio a Google Cloud ti consente di sfruttare la sua potente infrastruttura e i suoi servizi per garantire il corretto funzionamento della tua applicazione in un ambiente cloud-native.
Riteniamo che ciò che imparerai seguendo questi semplici passaggi possa essere applicato alla tua applicazione e alla tua organizzazione con linguaggi/stack e casi d'uso diversi.
Informazioni sull'app
L'applicazione ( codice, in licenza MIT) che eseguirai il fork è un'applicazione PHP 5.7 di base con autenticazione MySQL. L'idea principale dell'app è fornire una piattaforma in cui gli utenti possono caricare foto e gli amministratori hanno la possibilità di taggare le immagini inappropriate. L'applicazione ha due tabelle:
- Utenti. Viene precompilato con gli amministratori. I nuovi utenti possono registrarsi.
- Immagini. Include alcune immagini di esempio. Gli utenti che hanno eseguito l'accesso possono caricare nuove foto. Aggiungeremo un po' di magia.
Il tuo obiettivo
Vogliamo modernizzare la vecchia applicazione per averla in Google Cloud. Sfrutteremo i suoi strumenti e servizi per migliorare la scalabilità, aumentare la sicurezza, automatizzare la gestione dell'infrastruttura e integrare funzionalità avanzate come l'elaborazione delle immagini, il monitoraggio e lo stoccaggio dei dati utilizzando servizi come Cloud SQL, Cloud Run, Cloud Build, Secret Manager e altri ancora.
Ma soprattutto, vogliamo farlo passo passo per consentirti di apprendere il processo di pensiero alla base di ogni passaggio e, in genere, ogni passaggio sblocca nuove possibilità per quelli successivi (ad esempio, moduli 2 -> 3 e 6 -> 7).
Non sei ancora convinto? Guarda questo video di 7 minuti su YouTube.
Che cosa ti serve
- Un computer con un browser connesso a internet.
- Alcuni crediti Google Cloud. Chiedi a un appassionato di Google della tua zona ;)
- Il comando
gcloud
funziona. - Lavori localmente? Scaricalo qui. Ti servirà anche un buon editor (ad es. vscode o intellij).
- Vuoi fare tutto "sul cloud"? Puoi utilizzare Cloud Shell.
- Utente GitHub. Ti serve per creare un ramo del codice originale 🧑🏻💻 gdgpescara/app-mod-workshop con il tuo repository Git. Questo è necessario per avere una tua pipeline CI/CD (commit automatico -> compilazione -> deployment)
Esempi di soluzioni sono disponibili qui:
- Il repository dell'autore: https://github.com/Friends-of-Ricc/app-mod-workshop
- Il repo del laboratorio originale,nelle cartelle
.solutions/
, per capitolo.
Questo laboratorio può essere utilizzato dal tuo computer locale o anche completamente su un browser.
2. Configurazione del credito e fork
Utilizza il credito Google Cloud e configura il tuo ambiente Google Cloud [facoltativo]
Per partecipare a questo seminario, devi disporre di un account di fatturazione con un po' di credito. Se hai già la tua fatturazione, puoi saltare questo passaggio.
Crea un nuovo account Google Gmail (*) da collegare al tuo credito Google Cloud. Chiedi all'insegnante il link per utilizzare il credito Google Cloud o utilizza i crediti qui: bit.ly/PHP-Amarcord-credits .
Accedi con l'account appena creato e segui le istruzioni.
(
) Perché ho bisogno di un account Gmail nuovo di zecca?*
Abbiamo notato che alcune persone non riescono a completare il codelab perché il loro account (in particolare le email di lavoro o degli studenti) ha avuto un contatto precedente con Google Cloud e norme dell'organizzazione che ne limitano la possibilità di farlo. Ti consigliamo di creare un nuovo account Gmail o di utilizzare un account Gmail esistente (gmail.com) senza precedenti esposizioni a Google Cloud.
Fai clic sul pulsante per utilizzare il credito.
Compila il seguente modulo con il tuo nome e cognome e accetta i Termini e condizioni.
Potresti dover attendere alcuni secondi prima che l'account di fatturazione venga visualizzato qui: https://console.cloud.google.com/billing
Al termine, apri la console Google Cloud e crea un nuovo progetto facendo clic sul selettore di progetti nel menu a discesa in alto a sinistra in cui è visualizzato "Nessuna organizzazione". Vedi di seguito
Crea un nuovo progetto se non ne hai uno, come mostrato nello screenshot di seguito. Nell'angolo in alto a destra è presente l'opzione "NUOVO PROGETTO".
Assicurati di collegare il nuovo progetto all'account di fatturazione della prova Google Cloud come segue.
È tutto pronto per utilizzare la piattaforma Google Cloud. Se sei un principiante o vuoi semplicemente fare tutto in un ambiente cloud, puoi accedere a Cloud Shell e al relativo editor tramite il seguente pulsante nell'angolo in alto a sinistra, come mostrato di seguito.
Assicurati che il nuovo progetto sia selezionato in alto a sinistra:
Non selezionato (non valido):
Selezionato (buono):
Esegui il fork dell'app da GitHub
- Vai all'app demo: https://github.com/gdgpescara/app-mod-workshop
- Fai clic su 🍴 Forchetta.
- Se non hai un account GitHub, devi crearne uno nuovo.
- Modifica i contenuti come preferisci.
- Clona il codice dell'app utilizzando
git clone
https://github.com/
YOUR-GITHUB-USER/YOUR-REPO-NAME
- Apri la cartella del progetto clonato con il tuo editor preferito. Se scegli Cloud Shell, puoi farlo facendo clic su "Apri editor", come mostrato di seguito.
Con Google Cloud Shell Editor hai tutto ciò che ti serve, come mostrato nella figura seguente
Per farlo, fai clic su "Apri cartella" e seleziona la cartella, probabilmente app-mod-workshop
nella tua home directory.
3. Modulo 1: crea un'istanza SQL
Crea l'istanza Google Cloud SQL
La nostra app PHP si connetterà a un database MySQL e, pertanto, dobbiamo replicarlo in Google Cloud per una migrazione senza problemi. Cloud SQL è la soluzione perfetta perché ti consente di eseguire un database MySQL completamente gestito nel cloud. Ecco i passaggi da seguire:
- Vai alla pagina Cloud SQL: https://console.cloud.google.com/sql/instances
- Fai clic su "Crea istanza"
- Abilita l'API (se necessario). L'operazione potrebbe richiedere alcuni secondi.
- Scegli MySQL.
- (stiamo cercando di offrirti la versione più economica, in modo che duri più a lungo):
- Versione: Enterprise
- Preset: sviluppo (abbiamo provato la sandbox, ma non ha funzionato)
- Versione MySQL: 5.7 (wow, un tuffo nel passato!)
- ID istanza: scegli
appmod-phpapp
(se lo modifichi, ricordati di modificare di conseguenza anche gli script e le soluzioni futuri). - Password: qualsiasi, ma annota CLOUDSQL_INSTANCE_PASSWORD
- Regione: mantieni la stessa selezionata per il resto dell'app (ad es. Milano =
europe-west8
) - avail zonale: zona singola (risparmiamo per la demo)
Fai clic sul pulsante Crea istanza per eseguire il deployment del database Cloud SQL. ⌛ L'operazione richiede circa 10 minuti⌛. Nel frattempo, continua a leggere la documentazione. Puoi anche iniziare a risolvere il modulo successivo ("Esegui il containerizzazione dell'app PHP") perché non ha dipendenze da questo modulo nella prima parte (fino a quando non correggi la connessione al database).
Nota: Il costo di questa istanza dovrebbe aggirarsi sui 7 $ al giorno. Assicurati di spegnerlo dopo il workshop.
Crea il database e l'utente image_catalog in Cloud SQL
Il progetto dell'app è dotato di una cartella db/
contenente due file SQL:
- 01_schema.sql : contiene il codice SQL per creare due tabelle contenenti i dati di Utenti e Immagini.
- 02_seed.sql: contiene il codice SQL per eseguire il seeding dei dati nelle tabelle create in precedenza.
Questi file verranno utilizzati in un secondo momento, dopo la creazione del database image_catalog
. Per farlo, segui questi passaggi:
- Apri l'istanza e fai clic sulla scheda Database:
- Fai clic su "Crea database".
- Chiamalo
image_catalog
(come nella configurazione dell'app PHP).
Poi creiamo l'utente del database. In questo modo possiamo autenticarci nel database image_catalog.
- Ora fai clic sulla scheda Utenti.
- Fai clic su "Aggiungi account utente".
- Utente: creiamone uno:
- Nome utente:
appmod-phpapp-user
- Password: scegli una password che puoi ricordare o fai clic su "Genera"
- Mantieni l'opzione "Consenti qualsiasi host (%)".
- Fai clic su AGGIUNGI.
Apri il DB agli IP noti.
Tieni presente che tutti i database in Cloud SQL sono "isolati" per impostazione predefinita. Devi configurare esplicitamente una rete da cui essere accessibile.
- Fai clic sull'istanza
- Apri il menu "Connessioni"
- Fai clic sulla scheda "Networking".
- Fai clic nella sezione "Reti autorizzate". Ora aggiungi una rete (ovvero una subnet).
- Per il momento, scegliamo un'impostazione rapida, ma NON SICURA, per consentire il funzionamento dell'app. Potresti volerla limitare in un secondo momento agli IP attendibili:
- Nome: "Tutti nel mondo - NON SICURO".
- Rete: "
0.0.0.0/0"
(nota: questa è la parte NON SICURA) - Fai clic su FINE.
- Fai clic su Salva.
Il risultato dovrebbe essere simile a questo:
Nota: Questa soluzione è un buon compromesso per completare il workshop in O(ore). Tuttavia, consulta la documentazione SECURITY per proteggere la tua soluzione per la produzione.
È il momento di testare la connessione al database.
Vediamo se l'utente image_catalog
che abbiamo creato in precedenza funziona.
Accedi a "Cloud SQL Studio" all'interno dell'istanza e inserisci il database, l'utente e la password da autenticare come mostrato di seguito:
Ora puoi aprire l'editor SQL e passare alla sezione successiva.
Importa il database dal codice di base
Utilizza l'editor SQL per importare le tabelle image_catalog
con i relativi dati. Copia il codice SQL dai file nel repository ( 01_schema.sql e 02_seed.sql) ed eseguili uno dopo l'altro in ordine sequenziale.
Dopodiché dovresti visualizzare due tabelle in image_catalog, ovvero users e images, come mostrato di seguito:
Puoi testarlo eseguendo il seguente comando nell'editor: select * from images;
Inoltre, assicurati di annotare l'indirizzo IP pubblico dell'istanza Cloud SQL, ti servirà in seguito. Per ottenere l'IP, vai alla pagina principale dell'istanza Cloud SQL nella pagina Panoramica. (Panoramica > Connettiti a questa istanza > Indirizzo IP pubblico).
4. Modulo 2: containerizza l'app PHP
Vogliamo creare questa app per il cloud.
Ciò significa impacchettare il codice in una sorta di file ZIP contenente tutte le informazioni per eseguirlo nel cloud.
Esistono diversi modi per impacchettarlo:
- Docker. Molto popolare, ma piuttosto complesso da configurare correttamente.
- Buildpack. Meno popolare, ma tende a "indovinare automaticamente" cosa costruire e cosa eseguire. Spesso funzionano.
Nel contesto di questo workshop, presupponiamo che tu utilizzi Docker.
Se hai scelto di utilizzare Cloud Shell, è il momento di riaprirlo (fai clic in alto a destra nella console Cloud).
Dovresti visualizzare una comoda shell nella parte inferiore della pagina, dove dovresti aver eseguito il fork del codice nel passaggio di configurazione.
Docker
Se vuoi avere il controllo, questa è la soluzione giusta per te. Questo è utile quando devi configurare librerie specifiche e iniettare determinati comportamenti non evidenti (un chmod nei caricamenti, un file eseguibile non standard nella tua app e così via).
Poiché vogliamo eseguire il deployment della nostra applicazione containerizzata in Cloud Run, consulta la seguente documentazione. Come esegui il backport da PHP 8 a PHP 5.7? Forse puoi utilizzare Gemini. In alternativa, puoi utilizzare questa versione precotta:
La versione più recente di Dockerfile
è disponibile qui.
Per testare la nostra applicazione localmente, dobbiamo modificare il file config.php in modo che la nostra app PHP si connetta al database MYSQL disponibile su Google CloudSQL. In base a quanto hai configurato in precedenza, compila gli spazi vuoti:
<?php
// Database configuration
$db_host = '____________';
$db_name = '____________';
$db_user = '____________';
$db_pass = '____________';
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
DB_HOST
è l'indirizzo IP pubblico di Cloud SQL, che puoi trovare nella console SQL:
DB_NAME
non deve essere modificato:image_catalog
DB_USER
deve essereappmod-phpapp-user
DB_PASS
è un'opzione che hai scelto. Impostalo tra virgolette singole ed esegui l'escape, se necessario.
Inoltre, non esitare a tradurre le poche parti in italiano 🇮🇹 in inglese con l'aiuto di Gemini.
Bene, ora che hai Dockerfile
e hai configurato la tua app PHP per connetterti al tuo DB, proviamo.
Installa Docker se non lo hai ancora fatto ( link). Non è necessario se utilizzi Cloud Shell (non è fantastico?).
Ora prova a creare ed eseguire l'app PHP containerizzata con i comandi di compilazione ed esecuzione di Docker appropriati.
# Build command - don't forget the final . This works if Dockerfile is inside the code folder:
$ docker build -t my-php-app-docker .
# Local Run command: most likely ports will be 8080:8080
$ docker run -it -p <CONTAINER_PORT>:<LOCAL_MACHINE_PORT> my-php-app-docker
Se tutto funziona, dovresti riuscire a vedere la seguente pagina web quando sei connesso all'host locale. Ora che l'app è in esecuzione sulla porta 8080, fai clic sull'icona "Anteprima web" (un browser con un occhio) e poi su Anteprima sulla porta 8080 (o "Cambia porta" per qualsiasi altra porta).
Testare il risultato nel browser
Ora la tua applicazione dovrebbe avere il seguente aspetto:
Se accedi con Amministratore/admin123, dovresti visualizzare un messaggio del tipo:
Ottimo! A parte il testo in italiano, funziona. 🎉🎉🎉
Se la dockerizzazione è corretta, ma le credenziali del database sono errate, potresti visualizzare un messaggio simile al seguente:
Riprova, ci sei quasi.
Salvataggio in Artifact Registry [facoltativo]
A questo punto, dovresti avere un'applicazione PHP containerizzata funzionante pronta per essere dispiaggiata nel cloud. A questo punto, abbiamo bisogno di uno spazio nel cloud per archiviare l'immagine Docker e renderla accessibile per il deployment nei servizi Google Cloud come Cloud Run. Questa soluzione di archiviazione si chiama Artifact Registry, un servizio Google Cloud completamente gestito progettato per l'archiviazione degli elementi dell'applicazione, tra cui immagini container Docker, pacchetti Maven, moduli npm e altro ancora.
Creiamo un repository in Google Cloud Artifact Registry utilizzando il pulsante appropriato.
Scegli un nome valido, il formato e la regione adatti per l'archiviazione degli elementi.
Torna al tag dell'ambiente di sviluppo locale ed esegui il push dell'immagine del contenitore dell'app nel repository Artifact Registry appena creato. Per farlo, completa i seguenti comandi.
- docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
- docker push TARGET_IMAGE[:TAG]
Il risultato dovrebbe essere simile allo screenshot seguente.
Ottimo 🎉🎉🎉, puoi passare al livello successivo. Prima di questo, ti consigliamo di dedicare 2 minuti al caricamento/all'accesso/all'uscita e di familiarizzare con gli endpoint dell'app.Ti serviranno più tardi.
Possibili errori
Se ricevi errori di contenimento, prova a utilizzare Gemini per spiegare e correggere l'errore, fornendo:
- Il tuo Dockerfile attuale
- L'errore ricevuto
- [se necessario] il codice PHP in esecuzione.
Autorizzazioni di caricamento. Prova anche l'endpoint /upload.php
e carica una foto. Potresti visualizzare l'errore riportato di seguito. In questo caso, devi apportare alcune modifiche al chmod/chown
nel Dockerfile
.
Avviso: move_uploaded_file(uploads/image (3).png): failed to open stream: Permission denied in /var/www/html/upload.php on line 11
PDOException "could not find driver" (o "Errore di connessione: could not find driver"). Assicurati che il tuo Dockerfile contenga le librerie PDO appropriate per mysql (pdo_mysql
) per connetterti al database. Lasciati ispirare dalle soluzioni disponibili qui.
Impossibile inoltrare la richiesta a un backend. Impossibile connettersi a un server sulla porta 8080. Ciò significa che probabilmente stai esponendo la porta sbagliata. Assicurati di esporre la porta da cui Apache/Nginx sono effettivamente in esecuzione. Non è un'operazione banale. Se possibile, prova a impostare la porta 8080 (semplifica la vita con Cloud Run). Se vuoi mantenere la porta 80 (ad esempio perché Apache lo richiede), utilizza un comando diverso per eseguirlo:
$ docker run -it -p 8080:80 # force 80
# Use the PORT environment variable in Apache configuration files.
# https://cloud.google.com/run/docs/reference/container-contract#port
RUN sed -i 's/80/${PORT}/g' /etc/apache2/sites-available/000-default.conf /etc/apache2/ports.conf
5. Modulo 3: esegui il deployment dell'app in Cloud Run
Perché scegliere Cloud Run?
Domanda legittima. Anni fa, avresti sicuramente scelto Google App Engine.
In parole povere, oggi Cloud Run ha uno stack tecnologico più recente, è più facile da implementare, è più economico e riduce le risorse a 0 quando non lo utilizzi. Grazie alla flessibilità di eseguire qualsiasi contenitore senza stato e all'integrazione con vari servizi Google Cloud, è ideale per il deployment di microservizi e applicazioni moderne con un overhead minimo e la massima efficienza.
Nello specifico, Cloud Run è una piattaforma completamente gestita di Google Cloud che ti consente di eseguire applicazioni containerizzate stateless in un ambiente serverless. Gestisce automaticamente tutta l'infrastruttura, eseguendo lo scale up da zero per soddisfare il traffico in entrata e lo scale down quando è inattiva, il che lo rende economico ed efficiente. Cloud Run supporta qualsiasi linguaggio o libreria, purché sia pacchettizzato in un contenitore, il che consente una grande flessibilità nello sviluppo. Si integra bene con altri servizi Google Cloud ed è adatto per la creazione di microservizi, API, siti web e applicazioni basate su eventi senza dover gestire l'infrastruttura del server.
Prerequisiti
Per completare questa operazione, devi avere installato gcloud
sulla tua macchina locale. In caso contrario, consulta le istruzioni qui. Se invece utilizzi Google Cloud Shell, non devi fare nulla.
Prima del deployment…
Se lavori nel tuo ambiente locale, autenticati su Google Cloud con quanto segue
$ gcloud auth login –update-adc # not needed in Cloud Shell
Dovresti eseguire l'autenticazione tramite un accesso OAuth sul browser. Assicurati di accedere tramite Chrome con lo stesso utente (ad es. vattelapesca@gmail.com) che ha eseguito l'accesso a Google Cloud con la fatturazione abilitata.
Abilita l'API Cloud Run con il seguente comando:
$ gcloud services enable run.googleapis.com cloudbuild.googleapis.com
A questo punto, è tutto pronto per il deployment in Cloud Run.
Esegui il deployment dell'app in Cloud Run tramite gcloud
Il comando che ti consente di eseguire il deployment dell'app su Cloud Run è gcloud run deploy
. Esistono diverse opzioni da impostare per raggiungere il tuo obiettivo. L'insieme minimo di opzioni (che puoi fornire tramite riga di comando o che lo strumento ti chiederà con un prompt interattivo) è il seguente:
- Nome del servizio Cloud Run di cui vuoi eseguire il deployment per la tua app. Un servizio Cloud Run ti restituirà un URL che fornisce un endpoint alla tua app.
- Regione Google Cloud in cui verrà eseguita l'app. (
--region
REGION) - Immagine container che racchiude la tua app.
- Variabili di ambiente che l'app deve utilizzare durante l'esecuzione.
- Il flag Allow-Unauthenticated che consente a chiunque di accedere alla tua app senza ulteriore autenticazione.
Consulta la documentazione (o scorri verso il basso per una possibile soluzione) per scoprire come applicare questa opzione alla riga di comando.
Il deployment richiederà alcuni minuti. Se è tutto corretto, nella console Google Cloud dovresti vedere qualcosa di simile a quanto mostrato di seguito.
Fai clic sull'URL fornito da Cloud Run e testa la tua applicazione. Una volta autenticato, dovresti vedere qualcosa di simile a questo.
"gcloud run deploy" senza argomenti
Potresti aver notato che gcloud run deploy
ti pone le domande giuste e completa gli spazi vuoti che hai lasciato. È fantastico!
Tuttavia, in alcuni moduli aggiungeremo questo comando a un attivatore Cloud Build, quindi non possiamo permetterci domande interattive. Dobbiamo compilare ogni opzione del comando. Quindi vuoi creare la gcloud run deploy --option1 blah --foo bar --region your-fav-region
dorata. Come procedi?
- Ripeti i passaggi 2-3-4 finché gcloud non smette di fare domande:
- [LOOP]
gcloud run deploy
con le opzioni trovate finora - [LOOP] i sistemi richiedono l'opzione X
- [LOOP] Cerca nella documentazione pubblica come configurare X dall'interfaccia a riga di comando aggiungendo l'opzione
--my-option [my-value]
. - Torna al passaggio 2, a meno che gcloud non venga completato senza ulteriori domande.
- Questo gcloud run deploy BLAH BLAH BLAH è fantastico. Salva il comando da qualche parte, ti servirà in seguito per il passaggio Cloud Build.
Una possibile soluzione è disponibile qui. I documenti sono disponibili qui.
Evviva 🎉🎉🎉 Hai eseguito il deployment dell'app in Google Cloud completando il primo passaggio della modernizzazione.
6. Modulo 4: password pulita con Secret Manager
Nel passaggio precedente abbiamo potuto eseguire il deployment e l'esecuzione della nostra app in Cloud Run. Tuttavia, lo abbiamo fatto con una cattiva pratica di sicurezza: fornendo alcuni secret in testo non cifrato.
Prima iterazione: aggiorna il file config.php per utilizzare ENV
Potresti aver notato che abbiamo inserito la password del database direttamente nel codice del file config.php. Va bene per scopi di test e per verificare se l'app funziona. Tuttavia, non puoi eseguire commit/utilizzare codice in un ambiente di produzione. La password (e altri parametri di connessione al database) devono essere letti dinamicamente e forniti all'app in fase di esecuzione. Modifica il file config.php in modo che legga i parametri del database dalle variabili ENV. In caso di errore, ti consigliamo di impostare i valori predefiniti. Questa opzione è utile nel caso in cui non riesci a caricare l'ambiente, in quanto l'output della pagina ti indicherà se vengono utilizzati i valori predefiniti. Riempi gli spazi vuoti e sostituisci il codice in config.php.
<?php
// Database configuration with ENV variables. Set default values as well
$db_host = getenv('DB_HOST') ?: 'localhost';
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: 'wrong_password';
// Note getenv() is PHP 5.3 compatible
try {
$pdo = new PDO("mysql:host=$db_host;dbname=$db_name", $db_user, $db_pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Errore di connessione: " . $e->getMessage());
}
session_start();
?>
Poiché l'app è in container, devi fornire un modo per fornire le variabili ENV all'app. Questo può essere fatto in diversi modi:
- Al momento della compilazione, nel Dockerfile. Aggiungi al Dockerfile precedente i 4 parametri utilizzando la sintassi ENV DB_VAR=VALORE_VAR_AMBIENTE. Verranno impostati valori predefiniti che possono essere sostituiti in fase di esecuzione. Ad esempio, "DB_NAME" e "DB_USER" potrebbero essere impostati qui e non altrove.
- In fase di esecuzione. Puoi configurare queste variabili per Cloud Run, sia dall'interfaccia a riga di comando sia dall'interfaccia utente. Questo è il posto giusto per inserire tutte e quattro le variabili (a meno che tu non voglia mantenere i valori predefiniti impostati in Dockerfile).
In localhost, ti consigliamo di inserire le variabili ENV in un file .env
(controlla la cartella solutions).
Inoltre, assicurati che .env sia aggiunto a .gitignore
: non vuoi inviare i tuoi secret a GitHub.
echo .env >> .gitignore
Dopodiché puoi testare l'istanza localmente:
docker run -it -p 8080:8080 --env-file .env my-php-app-docker
Ora hai ottenuto quanto segue:
- L'app leggerà la variabile in modo dinamico dall'ambiente
- Hai migliorato la sicurezza perché hai rimosso la password del database dal codice.
Ora puoi eseguire il deployment di una nuova revisione in Cloud Run. Passiamo all'interfaccia utente e impostiamo le variabili di ambiente manualmente:
- Vai alla pagina https://console.cloud.google.com/run.
- Fai clic sulla tua app
- Fai clic su "Modifica ed esegui il deployment di una nuova revisione".
- Nella prima scheda "Contenitori", fai clic sulla scheda inferiore "Variabili e secret".
- Fai clic su "+ Aggiungi variabile" e aggiungi tutte le variabili necessarie. Il risultato dovrebbe essere simile a questo:
È perfetto? No, il tuo PASS è ancora visibile alla maggior parte degli operatori. Questo problema può essere mitigato con Google Cloud Secret Manager.
Seconda iterazione: Secret Manager
Le tue password sono scomparse dal tuo codice: vittoria! Ma aspetta, siamo al sicuro?
Le tue password sono comunque visibili a chiunque abbia accesso alla console Google Cloud. Infatti, se accedi al file di deployment YAML di Cloud Run, potrai recuperarlo. In alternativa, se provi a modificare o implementare una nuova revisione di Cloud Run, la password è visibile nella sezione Variabili e segreti, come mostrato negli screenshot di seguito.
Secret Manager di Google Cloud è un servizio centralizzato e sicuro per la gestione di informazioni sensibili come chiavi API, password, certificati e altri secret.
Ti consente di archiviare, gestire e accedere ai secret con autorizzazioni granulari e crittografia avanzata. Integrato con Identity and Access Management (IAM) di Google Cloud, Secret Manager ti consente di controllare chi può accedere a segreti specifici, garantendo la sicurezza dei dati e la conformità alle normative.
Supporta inoltre la rotazione e il controllo della versione automatici delle chiavi, semplificando la gestione del ciclo di vita delle chiavi e migliorando la sicurezza nelle applicazioni nei servizi Google Cloud.
Per accedere a Secret Manager, vai dal menu a tre linee ai servizi Sicurezza e individua Secret Manager nella sezione Protezione dei dati, come mostrato nello screenshot di seguito.
Una volta lì, abilita l'API Secret Manager come mostrato nella seguente immagine.
- Ora fai clic su "Crea un secret": chiamiamolo in modo razionale:
- Nome:
php-amarcord-db-pass
- Valore del secret: "la tua password del database" (ignora la parte "carica file").
- annotate questo link segreto, dovrebbe avere il seguente aspetto:
projects/123456789012/secrets/php-amarcord-db-pass
. Si tratta del puntatore univoco al tuo segreto (per Terraform, Cloud Run e altri). Il numero è il numero univoco del progetto.
Suggerimento: prova a utilizzare convenzioni di denominazione coerenti per i tuoi secret, specializzandoli da sinistra a destra, ad esempio: cloud-devrel-phpamarcord-dbpass
- Organizzazione (con l'azienda)
- Team (all'interno dell'organizzazione)
- Applicazione (all'interno del team)
- Nome della variabile (all'interno dell'app)
In questo modo, avrai espressioni regolari semplici per trovare tutti i tuoi secret per una singola app.
Creare una nuova revisione Cloud Run
Ora che abbiamo un nuovo secret, dobbiamo eliminare la variabile di ambiente DB_PASS e sostituirla con il nuovo secret. Pertanto:
- Accedere a Cloud Run utilizzando la console Google Cloud
- Scegli l'app.
- Fai clic su "Modifica ed esegui il deployment di una nuova revisione".
- Individua la scheda "Variabili e secret".
- Utilizza il pulsante "+ Fai riferimento a un segreto" per reimpostare la variabile di ambiente DB_PASS.
- Utilizza lo stesso "DB_PASS" per i secret a cui fai riferimento e utilizza la versione più recente.
Al termine, dovresti visualizzare il seguente errore
Prova a capire come risolvere il problema. Per risolvere il problema, devi accedere alla sezione IAM e amministrazione e modificare le autorizzazioni di concessione. Buon debug!
Una volta risolto il problema, torna a Cloud Run ed esegui nuovamente il deployment di una nuova revisione. Il risultato dovrebbe essere simile alla figura seguente:
Suggerimento: la Console per gli sviluppatori (UI) è ottima per segnalare i problemi di autorizzazione. Prenditi il tempo di esaminare tutti i link per le tue entità cloud.
7. Modulo 5: configurazione di CI/CD con Cloud Build
Perché una pipeline CI/CD?
A questo punto, dovresti aver digitato gcloud run deploy
alcune volte, magari rispondendo più volte alla stessa domanda.
Non vuoi più eseguire il deployment manuale dell'app con gcloud run deploy? Non sarebbe fantastico se la tua app potesse eseguire automaticamente il deployment ogni volta che esegui il push di una nuova modifica nel tuo repository Git?
Per utilizzare una pipeline CI/CD, sono necessari due elementi:
- Un repository Git personale: fortunatamente, dovresti aver già creato un fork del repository del laboratorio nel tuo account GitHub nel passaggio 2. In caso contrario, torna indietro e completa il passaggio. Il repository sottoposto a fork dovrebbe avere il seguente aspetto:
https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
- Cloud Build. Questo servizio eccezionale e economico ti consente di configurare le automazioni di compilazione per quasi tutto: Terraform, app dockerizzate e così via.
Questa sezione è incentrata sulla configurazione di Cloud Build.
Esegui Cloud Build.
Per farlo, utilizzeremo Cloud Build:
- compila il codice sorgente (con Dockerfile). Pensalo come un "grande file ZIP" che contiene tutto ciò che ti serve per compilarlo ed eseguirlo ("elemento di compilazione").
- Esegui il push di questo artefatto in Artifact Registry (AR).
- Esegui quindi un deployment da AR a Cloud Run per l'app "php-amarcord"
- Verrà creata una nuova versione ("revisione") dell'app esistente (immagina un livello con il nuovo codice) e la configureremo per dirottare il traffico verso la nuova versione se l'operazione di push andrà a buon fine.
Questo è un esempio di alcune build per la mia app php-amarcord
:
Come facciamo a fare tutto questo?
- Creando un file YAML perfetto:
cloudbuild.yaml
- Creando un trigger di Cloud Build.
- Connettiti al nostro repository GitHub tramite l'interfaccia utente di Cloud Build.
Creare un trigger (e collegare un repository)
- Vai alla pagina https://console.cloud.google.com/cloud-build/triggers.
- Fai clic su "Crea trigger".
- Compila:
- Nome: qualcosa di significativo, ad esempio
on-git-commit-build-php-app
- Evento: push al ramo
- Origine: "Connetti nuovo repository"
- Si aprirà una finestra sulla destra: "Connetti repository"
- Provider di origine: "GitHub" (primo)
- "Continua"
- Dopo l'autenticazione, si aprirà una finestra su GitHub per l'autenticazione incrociata. Segui la procedura e sii paziente. Se hai molti repository, l'operazione potrebbe richiedere un po' di tempo.
- "Seleziona repo" Seleziona il tuo account/repo e seleziona la parte "Ho capito…".
- Se ricevi il messaggio di errore: l'app GitHub non è installata in nessun repository, procedi facendo clic su "Installa Google Cloud Build" e segui le istruzioni.
Fai clic su Connetti
- Bingo! Il tuo repository è ora connesso.
- Torna alla parte Attivatore….
- Configurazione: rilevata automaticamente (*)
- Avanzate: seleziona l'account di servizio "[PROJECT_NUMBER]-compute@developer.gserviceaccount.com"
- xxxxx è l'ID progetto
- L'account di servizio Compute predefinito è adatto per un approccio di laboratorio, ma non utilizzarlo in produzione. ( Scopri di più).
- Lascia tutto invariato.
- Fai clic sul pulsante "Crea".
(*) Questo è il modo più semplice perché controlla la presenza di Dockerfile o cloudbuild.yaml. Tuttavia, cloudbuild.yaml
ti offre la possibilità di decidere cosa fare in ogni passaggio.
Ho il potere!
Ora l'attivatore non funzionerà a meno che tu non fornisca all'account di servizio Cloud Build (che cos'è un account di servizio? L'indirizzo email di un "robot" che agisce per tuo conto per un'attività, in questo caso la creazione di elementi nel cloud.
L'amministratore delegato non riuscirà a eseguire la compilazione e il deployment, a meno che tu non lo autorizzi a farlo. Per fortuna è facile.
- vai a "Cloud Build" > "Impostazioni".
- Account di servizio "[PROJECT_NUMBER]- compute@developer.gserviceaccount.com"
- Seleziona queste caselle:
- Cloud Run
- Secret Manager
- Account di servizio
- Cloud Build
- Seleziona anche "Imposta come account di servizio preferito".
Dove si trova il file YAML di Cloud Build?
Ti invitiamo vivamente a dedicare del tempo alla creazione del tuo file YAML di Cloud Build.
Tuttavia, se non hai tempo o non vuoi prenderti tempo, puoi trovare ispirazione in questa cartella di soluzioni: .solutions
Ora puoi eseguire il push di una modifica su GitHub e osservare Cloud Build.
La configurazione di Cloud Build può essere complicata. Dovresti ricevere una risposta entro:
- Controllare i log in https://console.cloud.google.com/cloud-build/builds;region=global
- Trovare l'errore.
- Correggere il codice e emettere nuovamente git commit / git push.
- A volte l'errore non è nel codice, ma in qualche configurazione. In questo caso, puoi emettere una nuova compilazione dall'interfaccia utente (Cloud Build > "Trigger" > Esegui).
Tieni presente che, se utilizzi questa soluzione, devi ancora fare un po' di lavoro. Ad esempio, devi impostare le variabili ENV per gli endpoint dev/prod appena creati:
A tale scopo, puoi procedere in uno dei due seguenti modi:
- Tramite UI: impostando di nuovo le variabili ENV
- Tramite l'CLI creando lo script "perfetto" per te. Un esempio è disponibile qui: gcloud-run-deploy.sh . Devi modificare alcune cose, ad esempio l'endpoint e il numero di progetto. Puoi trovare il numero di progetto nella Panoramica di Cloud.
Come faccio a eseguire il commit del codice su GitHub?
Non rientra nell'ambito di questo workshop insegnare il modo migliore per git push
su GitHub. Tuttavia, se non riesci a procedere e sei in Cloud Shell, hai due possibilità:
- CLI. Aggiungi una chiave SSH localmente e aggiungi un repository remoto con git@github.com:YOUR_USER/app-mod-workshop.git (anziché http)
- VSCode. Se utilizzi l'editor Cloud Shell, puoi utilizzare la scheda Controllo del codice sorgente (Ctrl-Maiusc-G), fare clic su "Sincronizza modifiche" e seguire le istruzioni. Dovresti essere in grado di autenticare il tuo account GitHub in vscode e le operazioni pull/push da lì diventano un gioco da ragazzi.
Ricordati di git add clodubuild.yaml
tra gli altri file, altrimenti non funzionerà.
"Parità dev/prod" approfondita o superficiale [facoltativo]
Se hai copiato la versione del modello da qui, avrai due versioni DEV e PROD identiche. È una funzionalità interessante e in linea con la regola 10 di The Twelve-Factor App.
Tuttavia, utilizziamo due endpoint web diversi per avere un'app che punti allo stesso database. Questo è sufficiente per un workshop, ma nella vita reale è consigliabile dedicare un po' di tempo alla creazione di un ambiente di produzione adeguato. Ciò significa avere due database (uno per lo sviluppo e uno per la produzione) e anche scegliere dove posizionarli per il ripristino di emergenza / l'alta disponibilità. Questo argomento va oltre lo scopo di questo workshop, ma è un argomento da tenere presente.
Se hai tempo di realizzare una versione "profonda" della produzione, tieni presente tutte le risorse che devi duplicare, ad esempio:
- Database Cloud SQL (e probabilmente istanza SQL).
- Bucket GCS
- Funzione Cloud.
- Potresti utilizzare Gemini 1.5 Flash come modello di sviluppo (più economico e veloce) e Gemini 1.5 Pro (più potente).
In generale, ogni volta che fai qualcosa per l'app, pensa in modo critico: la produzione deve avere lo stesso valore o meno? In caso contrario, raddoppia l'impegno. Questo è ovviamente molto più semplice con Terraform, in cui puoi inserire l'ambiente (-dev, -prod) come suffisso per le risorse.
8. Modulo 6: passaggio a Google Cloud Storage
Spazio di archiviazione
Al momento l'app memorizza lo stato in un contenitore Docker. Se la macchina si guasta, l'app esplode o semplicemente se effettui il push di una nuova revisione, verrà pianificata una nuova revisione con uno spazio di archiviazione vuoto: 🙈
Come possiamo risolvere il problema? Esistono diversi approcci.
- Memorizza le immagini nel DB. È quello che ho fatto con la mia app PHP precedente. È la soluzione più semplice perché non aggiunge complessità. Tuttavia, aggiunge latenza e carico al tuo DB.
- Esegui la migrazione dell'app Cloud Run a una soluzione ottimizzata per lo spazio di archiviazione: GCE + disco permanente? Forse GKE + Storage? Nota: ciò che guadagni in termini di controllo, lo perdi in agilità.
- Passa a GCS. Google Cloud Storage offre lo spazio di archiviazione migliore per l'intera piattaforma Google Cloud ed è la soluzione più idiomatica per il cloud. Tuttavia, richiede di utilizzare le librerie PHP. Sono disponibili librerie PHP 5.7 per GCS?
PHP 5.7
supportaComposer
? Sembra che PHP 5.3.2 sia la versione precedente supportata da Composer. - Potresti usare un sidecar Docker?
- In alternativa, puoi utilizzare i mount dei volumi Cloud Run di GCS. Sembra fantastico.
🤔 Esegui la migrazione dello spazio di archiviazione (open ended)
[A risposta aperta] In questo esercizio, ti chiediamo di trovare una soluzione per spostare le immagini in modo che rimangano in qualche modo.
Test di accettazione
Non voglio dirti la soluzione, ma voglio che succeda quanto segue:
- Carichi
newpic.jpg
. Lo vedi nell'app. - Esegui l'upgrade dell'app a una nuova versione.
newpic.jpg
è ancora visibile.
💡 Possibile soluzione (mount dei volumi Cloud Run di GCS)
Si tratta di una soluzione molto elegante che ci consente di eseguire caricamenti di file con stato senza toccare il codice (a parte la visualizzazione di una descrizione dell'immagine, ma è un'operazione banale e solo per la soddisfazione visiva).
In questo modo dovresti riuscire a montare una cartella da Cloud Run a GCS, quindi:
- Tutti i caricamenti su GCS saranno effettivamente visibili nella tua app.
- Tutti i caricamenti nella tua app verranno caricati su GCS
- La magia avverrà per gli oggetti caricati in GCS (capitolo 7).
Nota: Leggi i Termini e condizioni di FUSE. NON è accettabile se le prestazioni sono un problema.
Crea un bucket GCS
GCS è il servizio di archiviazione onnipresente di Google Cloud. È stato testato sul campo e viene utilizzato da tutti i servizi Google Cloud che richiedono spazio di archiviazione.
Tieni presente che Cloud Shell esporta PROJECT_ID come GOOGLE_CLOUD_PROJECT:
$ export PROJECT_ID=$GOOGLE_CLOUD_PROJECT
#!/bin/bash
set -euo pipefail
# Your Cloud Run Service Name, eg php-amarcord-dev
SERVICE_NAME='php-amarcord-dev'
BUCKET="${PROJECT_ID}-public-images"
GS_BUCKET="gs://${BUCKET}"
# Create bucket
gsutil mb -l "$GCP_REGION" -p "$PROJECT_ID" "$GS_BUCKET/"
# Copy original pictures there - better if you add an image of YOURS before.
gsutil cp ./uploads/*.png "$GS_BUCKET/"
Configura Cloud Run per montare il bucket nella cartella /uploads/
Ora passiamo alla parte elegante. Creiamo un volume php_uploads
e dichiariamo a Cloud Run di eseguire un montaggio FUSE su MOUNT_PATH
(ad esempio /var/www/html/uploads/
):
#!/bin/bash
set -euo pipefail
# .. keep variables from previous script..
# Uploads folder within your docker container.
# Tweak it for your app code.
MOUNT_PATH='/var/www/html/uploads/'
# Inject a volume mount to your GCS bucket in the right folder.
gcloud --project "$PROJECT_ID" beta run services update "$SERVICE_NAME" \
--region $GCP_REGION \
--execution-environment gen2 \
--add-volume=name=php_uploads,type=cloud-storage,bucket="$BUCKET" \
--add-volume-mount=volume=php_uploads,mount-path="$MOUNT_PATH"
Ora ripeti questo passaggio per tutti gli endpoint che vuoi indirizzare a Cloud Storage.
Puoi ottenere lo stesso risultato anche dall'interfaccia utente
- Nella scheda "Volumi", crea un montaggio del volume che rimandi al tuo bucket, di tipo "Bucket Cloud Storage", ad esempio con il nome "php_uploads".
- In Container > Montaggi volume, monta il volume che hai appena creato sul punto del volume richiesto dalla tua app. Dipende dal file Docker, ma potrebbe avere il seguente aspetto:
var/www/html/uploads/
.
In ogni caso, se funziona, la modifica della nuova revisione Cloud Run dovrebbe mostrare qualcosa di simile al seguente:
Ora testa la nuova applicazione caricando una nuova immagine nell'endpoint /upload.php
.
Le immagini dovrebbero essere trasferite senza problemi su GCS senza scrivere una sola riga di PHP:
Cosa è successo?
È successo qualcosa di molto magico.
Un'applicazione precedente con codice precedente continua a svolgere la sua funzione. Un nuovo stack modernizzato ci consente di avere tutte le immagini/foto della nostra app comodamente in un bucket Cloud con stato. Ora non ci sono limiti:
- Vuoi inviare un'email ogni volta che viene inviata un'immagine con tag "pericoloso" o "nudo"? Puoi farlo senza modificare il codice PHP.
- Vuoi utilizzare un modello multimodale Gemini ogni volta che ricevi un'immagine per descriverla e caricare il DB con la relativa descrizione? Puoi farlo senza modificare il codice PHP. Non mi credi? Continua a leggere nel capitolo 7.
Abbiamo appena aperto un'ampia gamma di opportunità.
9. Modulo 7: potenzia la tua app con Google Gemini
Ora hai una fantastica app PHP modernizzata e nuova di zecca (come un Fiat 126
del 2024) con spazio di archiviazione basato su cloud.
A cosa serve
Prerequisiti
Nel capitolo precedente, una soluzione modello ci ha permesso di montare le immagini /uploads/
su GCS, di fatto separando la logica dell'app dallo spazio di archiviazione delle immagini.
Per questo esercizio devi:
- Avere completato l'esercizio del capitolo 6 (spazio di archiviazione).
- Avere un bucket GCS con i caricamenti delle immagini, in cui gli utenti caricano le foto sulla tua app e le foto vengono trasferite nel bucket.
Configurare una Funzione Cloud (in Python)
Ti è mai capitato di chiederti come implementare un'applicazione basata su eventi? Ad esempio:
- quando si verifica <event> => invia un'email
- quando si verifica <event> => se <condizione> è vera, aggiorna il database.
Un evento può essere qualsiasi cosa, da un nuovo record disponibile in BigQuery a un nuovo oggetto modificato in una cartella in GCS o un nuovo messaggio in attesa in una coda in Pub/Sub.
Google Cloud supporta più paradigmi per raggiungere questo obiettivo. In particolare:
- EventArc. Scopri come ricevere gli eventi GCS. Ottimo per creare DAG e orchestrare azioni basate su if-then-else nel cloud.
- Cloud Scheduler. Ad esempio, è ideale per un cron job a mezzanotte nel cloud.
- Cloud Workflows. Analogamente a Event Arc, ti consente di
- Cloud Run Functions (note come
lambdas
). - Cloud Composer. È la versione di Google di Apache Airflow, ottima anche per i DAG.
In questo esercizio, esamineremo Cloud Function per ottenere un risultato davvero spettacolare. Ti forniremo anche esercizi facoltativi.
Tieni presente che il codice di esempio è disponibile in .solutions/
Configurare una Funzione Cloud (🐍 Python)
Stiamo cercando di creare un GCF molto ambizioso.
- Quando viene creata una nuova immagine su GCS (probabilmente perché qualcuno l'ha caricato sull'app, ma non solo)
- .. chiama Gemini per descriverla e ottenere una descrizione testuale dell'immagine .. (è consigliabile controllare il tipo MIME e assicurarsi che si tratti di un'immagine e non di un PDF, MP3 o testo)
- .. e aggiorna il DB con questa descrizione. (questa operazione potrebbe richiedere la correzione del database per aggiungere una colonna
description
alla tabellaimages
).
Esegui il patching del database per aggiungere description
alle immagini
- Apri Cloud SQL Studio:
- Inserisci il tuo utente e la tua password per il database Images
- Inserisci questo codice SQL che aggiunge una colonna per la descrizione di un'immagine:
ALTER TABLE images ADD COLUMN description TEXT;
E bingo! Prova ora a verificare se ha funzionato:
SELECT * FROM images;
Dovresti vedere la nuova colonna della descrizione:
Scrivi la funzione f(x) di Gemini
Nota: Questa funzione è stata creata con l'aiuto di Gemini Code Assist.
Nota: La creazione di questa funzione potrebbe comportare errori di autorizzazione IAM. Alcuni sono descritti di seguito nel paragrafo "Possibili errori".
- Abilita le API
- Vai alla pagina https://console.cloud.google.com/functions/list.
- Fai clic su "Crea funzione"
- Abilita le API dalla procedura guidata API:
Puoi creare il GCF dall'interfaccia utente o dalla riga di comando. Qui utilizzeremo la riga di comando.
Un possibile codice è disponibile in .solutions/
- Crea una cartella per ospitare il tuo codice, ad esempio "gcf/". Entra nella cartella.
- Crea un file
requirements.txt
:
google-cloud-storage
google-cloud-aiplatform
pymysql
- Crea una funzione Python. Codice di esempio qui: gcf/main.py.
#!/usr/bin/env python
"""Complete this"""
from google.cloud import storage
from google.cloud import aiplatform
import vertexai
from vertexai.generative_models import GenerativeModel, Part
import os
import pymysql
import pymysql.cursors
# Replace with your project ID
PROJECT_ID = "your-project-id"
GEMINI_MODEL = "gemini-1.5-pro-002"
DEFAULT_PROMPT = "Generate a caption for this image: "
def gemini_describe_image_from_gcs(gcs_url, image_prompt=DEFAULT_PROMPT):
pass
def update_db_with_description(image_filename, caption, db_user, db_pass, db_host, db_name):
pass
def generate_caption(event, context):
"""
Cloud Function triggered by a GCS event.
Args:
event (dict): The dictionary with data specific to this type of event.
context (google.cloud.functions.Context): The context parameter contains
event metadata such as event ID
and timestamp.
"""
pass
- Esegui il push della funzione. Puoi utilizzare uno script simile a questo: gcf/push-to-gcf.sh.
Nota 1. Assicurati di specificare le variabili di ambiente con i valori corretti o semplicemente aggiungile sopra (GS_BUCKET=blah
, …)
Nota 2. Verrà inviato tutto il codice locale (.
), quindi assicurati di racchiudere il codice in una cartella specifica e di utilizzare .gcloudignore
come un professionista per evitare di inviare librerie enormi. ( example).
#!/bin/bash
set -euo pipefail
# add your logic here, for instance:
source .env || exit 2
echo "Pushing ☁️ f(x)☁ to 🪣 $GS_BUCKET, along with DB config.. (DB_PASS=$DB_PASS)"
gcloud --project "$PROJECT_ID" functions deploy php_amarcord_generate_caption \
--runtime python310 \
--region "$GCP_REGION" \
--trigger-event google.cloud.storage.object.v1.finalized \
--trigger-resource "$BUCKET" \
--set-env-vars "DB_HOST=$DB_HOST,DB_NAME=$DB_NAME,DB_PASS=$DB_PASS,DB_USER=$DB_USER" \
--source . \
--entry-point generate_caption \
--gen2
Nota: in questo esempio, generate_caption
sarà il metodo invocato e la funzione cloud gli passerà l'evento GCS con tutte le informazioni pertinenti (nome del bucket, nome dell'oggetto e così via). Prenditi un po' di tempo per eseguire il debug della dict di Python dell'evento.
Testare la funzione
Test di unità
La funzione ha molti componenti in movimento. Potresti voler testare tutti i singoli.
Un esempio è in gcf/test.py.
Interfaccia utente di Cloud Functions
Prenditi anche un po' di tempo per esplorare la funzione nell'interfaccia utente. Vale la pena esplorare ogni scheda, in particolare Source
(la mia preferita), Variables
, Trigger
e Logs
. Passerai molto tempo in Logs
per risolvere i problemi (vedi anche i possibili errori nella parte inferiore di questa pagina). Assicurati inoltre di controllare Permissions
.
Test E2E
È ora di testare manualmente la funzione.
- Vai all'app e accedi
- Carica una foto (non troppo grande, abbiamo riscontrato problemi con le immagini di grandi dimensioni)
- controlla nell'interfaccia utente che l'immagine sia stata caricata.
- Verifica in Cloud SQL Studio che la descrizione sia stata aggiornata. Accedi ed esegui questa query:
SELECT * FROM images
.
È un sistema che funziona davvero bene. Potremmo anche aggiornare il frontend per mostrare questa descrizione.
Aggiornare PHP per mostrare [facoltativo]
Abbiamo dimostrato che l'app funziona. Tuttavia, sarebbe bello che anche gli utenti potessero vedere questa descrizione.
Non è necessario essere esperti di PHP per aggiungere la descrizione a index.php
. Questo codice dovrebbe funzionare (sì, anche Gemini lo ha scritto per me):
<?php if (!empty($image['description'])): ?>
<p class="font-bold">Gemini Caption:</p>
<p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>
Posiziona questo codice all'interno di foreach
in base alle tue preferenze.
Nei passaggi successivi vedremo anche una versione più bella dell'interfaccia utente, grazie a Gemini Code Assist. Una versione più leggibile potrebbe avere il seguente aspetto:
Conclusioni
Hai attivato una funzione Cloud sui nuovi oggetti che arrivano su GCS, in grado di annotare i contenuti dell'immagine come farebbe una persona e di aggiornare automaticamente il DB. Wow!
Passaggi successivi Potresti seguire lo stesso ragionamento per ottenere due ottime funzionalità.
[Facoltativo] Aggiungi altre funzioni Cloud [aperte]
Mi vengono in mente un paio di funzionalità aggiuntive.
📩 Trigger email
Un attivatore email che ti invia un'email ogni volta che qualcuno invia una foto.
- Troppo spesso? Aggiungi un'ulteriore limitazione: un'immagine GRANDE o un'immagine i cui contenuti di Gemini contengono le parole "nude/nudità/violento".
- Per saperne di più, consulta
EventArc
.
🚫 Moderazione automatica delle foto inappropriate
Al momento, un amministratore umano segnala le immagini come "inappropriate". Che ne dici di lasciare che Gemini faccia il grosso del lavoro e moderi lo spazio? Aggiungi un test per segnalare i contenuti degli attivatori inappropriati e aggiorna il DB come abbiamo appreso nella funzione precedente. Ciò significa essenzialmente prendere la funzione precedente, modificare il prompt e aggiornare il DB in base alla risposta.
Attenzione. L'IA generativa ha output imprevedibili. Assicurati che l'"output delle creatività" di Gemini sia "in linea". Potresti chiedere una risposta deterministica, ad esempio un punteggio di attendibilità da 0 a 1, un JSON e così via. Puoi ottenere questo risultato in molti modi, ad esempio: * Utilizzando le librerie Python pydantic
, langchain
e così via. * Utilizza l'output strutturato di Gemini.
Suggerimento. Puoi avere PIU' funzioni o un singolo prompt che impone una risposta JSON (funziona perfettamente con "Output strutturato di Gemini", come evidenziato sopra), ad esempio:
Quale sarebbe il prompt per generare questa immagine?
{
"description": "This is the picture of an arrosticino",
"suitable": TRUE
}
Potresti aggiungere altri campi al prompt per ottenere informazioni come: c'è qualcosa di buono? C'è qualche problema? Riconosci il luogo? Il testo è presente (l'OCR non è mai stato così facile):
goods
: "Sembra deliziosa"bads
: "Sembra cibo non salutare"OCR
: "Da consumare preferibilmente prima del 10 Novembre 2024"location
: "Pescara, Lungomare"
Anche se in genere è meglio avere una funzione N per N risultati, è incredibilmente gratificante crearne una che ne esegua 10. Consulta questo articolo di Riccardo per scoprire come.
Possibili errori (principalmente IAM / autorizzazioni)
La prima volta che ho sviluppato questa soluzione ho riscontrato alcuni problemi di autorizzazione IAM. Le aggiungerò qui per empatia e per darti alcune idee su come risolverle.
Errore: autorizzazioni insufficienti per l'account di servizio
- Tieni presente che per eseguire il deployment di una funzione GCF che ascolta un bucket GCS devi configurare le autorizzazioni appropriate per l'account di servizio che utilizzi per il job, come mostrato nella figura:
Potresti anche dover attivare le API EventArc, che diventeranno completamente disponibili dopo alcuni minuti.
Errore: comando Cloud Run mancante
- Un altro commento della UI per le autorizzazioni GCF è il seguente ( Ruolo Invoker di Cloud Run):
Questo errore può essere corretto eseguendo il comando nell'immagine, che è simile a fix-permissions.sh
Questo problema è descritto qui: https://cloud.google.com/functions/docs/securing/authenticating
Errore: limite di memoria superato
La prima volta che l'ho eseguito, i log potevano indicare: "Limite di memoria di 244 MiB superato con 270 MiB utilizzati. Valuta la possibilità di aumentare il limite di memoria, consulta https://cloud.google.com/functions/docs/configuring/memory". Ancora una volta, aggiungi RAM al tuo GCF. È facilissimo farlo nell'interfaccia utente. Ecco un possibile problema:
In alternativa, puoi anche correggere lo script di deployment di Cloud Run per aumentare MEM/CPU. L'operazione richiede un po' più di tempo.
Errore: PubSub pubblicato
La creazione di un trigger con la versione 1 di GCF ha restituito questo errore:
Anche in questo caso, il problema è facile da risolvere: vai ad IAM e concedi al tuo account di servizio il ruolo "Publisher Pub/Sub".
Errore: Vertex AI non è stato utilizzato
Se ricevi questo errore:
Autorizzazione negata: 403 L'API Vertex AI non è stata utilizzata in precedenza nel progetto YOUR_PROJECT o è disabilitata. Abilitala visitando la pagina https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT
Devi solo attivare le API Vertex AI. Il modo più semplice per abilitare TUTTE le API necessarie è il seguente:
- https://console.cloud.google.com/vertex-ai
- Fai clic su "Abilita tutte le API consigliate".
Errore: trigger EventArc non trovato.
Se ricevi questo messaggio, esegui nuovamente il deployment della funzione.
Errore: è in corso il provisioning di 400 agenti di servizio
Viene eseguito il provisioning di 400 agenti di servizio ( https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). Gli agenti di servizio sono necessari per leggere il file Cloud Storage fornito. Riprova tra qualche minuto.
In questo caso, attendi un po' di tempo o rivolgiti a un utente di Google.
10. Modulo 8: Crea SLO di disponibilità
Nel capitolo cerchiamo di raggiungere questo obiettivo:
- Creazione di SLI
- Creazione di SLO in base agli SLI
- Creazione di avvisi basati su SLO
Questo è un argomento molto caro all'autore, poiché Riccardo lavora nell'area SRE / DevOps di Google Cloud.
(a risposta aperta) Crea SLI e SLO per questa app
Quanto è buona un'app se non riesci a capire quando non è disponibile?
Che cos'è un SLO?
Oh wow! Google ha inventato gli SLO. Per saperne di più, ti consiglio di leggere:
- Libro SRE - capitolo 2 - Implementazione degli SLO. ( 👉 altri libri SRE)
- Art of SLOs ( fantastico video). È una formazione fantastica per scoprire di più su come creare un SLO perfetto per il tuo servizio.
- Corso SRE su Coursera. Ho contribuito.
Passaggio 1: crea SLI/SLO di disponibilità
Iniziamo con l'SLO di disponibilità, poiché è l'indicatore più semplice e forse più importante da misurare.
Fortunatamente, Cloud Run offre il supporto per gli SLO predefiniti grazie a Istio.
Una volta che l'app è in esecuzione su Cloud Run, è molto semplice da realizzare, mi bastano 30 secondi.
- Vai alla pagina Cloud Run.
- Fai clic/seleziona l'app.
- Seleziona la scheda
SLOs
. - Fai clic su "+ Crea SLO".
- Disponibilità, in base alla richiesta
- Continua
- Mese di calendario / 99%.
- Fai clic su "Crea SLO".
Passaggio 2: configura gli avvisi per questo SLO
Ti consiglio di creare due avvisi:
- Uno con un burnrate basso ("Slowburn") per avvisarti via email (simula un ticket con priorità bassa).
- Uno con un burnrate elevato ("Fastburn") per avvisarti via SMS (simula un ticket / cercapersone con priorità elevata)
Vai al tuo SLO tab
precedente.
Esegui questa operazione due volte:
- Fai clic su "Crea avviso SLO" (il pulsante 🔔 con un segno Più all'interno, a destra)
- Durata ricerca, Soglia burn rate:
- [FAST]. Primo:
60
min /10
x - [LENTO]. Secondo:
720
min /2
x - Canale di notifica: fai clic su Gestisci canali di notifica
- Innanzitutto, "Email" -> Aggiungi nuovo -> ..
- In secondo luogo, "SMS" -> Aggiungi nuovo -> Verifica sullo smartphone.
- Suggerimento: mi piace usare le emoji nei nomi. È divertente per le demo.
- Al termine, fai clic sulla grande X in alto a destra.
- Seleziona prima il telefono (veloce) e poi l'email (lento).
- Aggiungi della documentazione di esempio, ad esempio:
[PHP Amarcord] Riccardo told me to type sudo reboot or to check documentation in http://example.com/playbooks/1.php but I guess he was joking
.
Bingo!
Risultato finale
Possiamo considerare questo esercizio completato quando hai uno SLO funzionante + 2 avvisi per la tua disponibilità e ricevi avvisi via email e sullo smartphone.
Se vuoi, puoi aggiungere un'altra metrica Latenza (e ti incoraggio vivamente a farlo) o anche una più complessa. Per la latenza, scegli un valore che ritieni ragionevole. In caso di dubbi, scegli 200 ms.
11. Passaggi successivi
Hai completato TUTTO, cosa manca?
Ecco alcuni spunti di riflessione:
Gioca con Gemini
Puoi utilizzare Gemini in due versioni:
- Vertex AI. Il "modo Enterprise", intrecciato con il tuo account Google Cloud, che abbiamo esplorato nel capitolo 7 (GCF+Gemini). L'autenticazione funziona magicamente e i servizi si interconnettono perfettamente.
- Google AI. "Il modo del consumatore". Puoi ottenere una chiave API Gemini da qui e iniziare a creare piccoli script che possono essere collegati a qualsiasi carico di lavoro di cui disponi già (lavoro proprietario, altri cloud, localhost e così via). Basta sostituire la chiave API e il codice inizierà a funzionare magicamente.
Ti invitiamo a provare a esplorare la soluzione (2) con i tuoi progetti personali.
UI Lifting
Non sono bravo con le UI. Ma Gemini sì. Puoi semplicemente prendere una singola pagina PHP e dire qualcosa di simile:
I have a VERY old PHP application. I want to touch it as little as possible. Can you help me:
1. add some nice CSS to it, a single static include for tailwind or similar, whatever you prefer
2. Transform the image print with description into cards, which fit 4 per line in the canvas?
Here's the code:
-----------------------------------
[Paste your PHP page, for instance index.php - mind the token limit!]
Puoi ottenerlo facilmente in meno di 5 minuti, a un solo Cloud Build di distanza. :)
La risposta di Gemini è stata perfetta (non ho dovuto cambiare nulla):
Ed ecco il nuovo layout nell'app personale dell'autore:
Nota: il codice viene incollato come immagine perché non vogliamo incoraggiarti a utilizzarlo, ma a far sì che sia Gemini a scriverlo per te, con i vincoli di UI/frontend della tua creatività. Fidati, dopodiché dovrai apportare solo modifiche minime.
Sicurezza
La protezione corretta di questa app non è un obiettivo di questo workshop di 4 ore, in quanto aumenterebbe il tempo necessario per completarlo di 1-2 ordini di grandezza.
Tuttavia, questo argomento è molto importante. Abbiamo raccolto alcune idee in SECURITY
.
12. Complimenti!
Congratulazioni 🎉🎉🎉 , hai modernizzato la tua applicazione PHP precedente con Google Cloud.
In questo codelab hai appreso:
- Come eseguire il deployment di un database in Google Cloud SQL e come eseguire la migrazione del database esistente al suo interno.
- Come containerizzare l'applicazione PHP con Docker e Buildpack e archiviarne l'immagine in Google Cloud Artifact Registry
- Come eseguire il deployment dell'app containerizzata in Cloud Run e farla funzionare con Cloud SQL
- Come archiviare/utilizzare in modo segreto i parametri di configurazione sensibili (ad esempio la password del database) utilizzando Google Secret Manager
- Come configurare la pipeline CI/CD con Google Cloud Build per creare ed eseguire il deployment automatico dell'app PHP a ogni push del codice nel repository GitHub.
- Come utilizzare Cloud Storage per "eseguire il clouding" delle risorse dell'app
- Come sfruttare le tecnologie serverless per creare fantastici flussi di lavoro su Google Cloud senza toccare il codice dell'app.
- Utilizza le funzionalità multimodali di Gemini per un caso d'uso appropriato.
- Implementare i principi SRE in Google Cloud
Questo è un ottimo inizio per il tuo percorso di modernizzazione delle applicazioni con Google Cloud.
🔁 Feedback
Se vuoi raccontarci la tua esperienza con questo seminario, ti consigliamo di compilare questo modulo di feedback.
Il tuo feedback è sempre gradito, così come le RP per i frammenti di codice di cui sei particolarmente orgoglioso.
🙏 Grazie
L'autore ringrazia Mirko Gilioli e Maurizio Ipsale di Datatonic per l'aiuto fornito nella stesura e nel test della soluzione.