Atelier App Mod

1. Introduction

Dernière mise à jour:01/11/2024

Comment moderniser une ancienne application PHP sur Google Cloud ?

(📽️ Vidéo d'introduction de 7 minutes à cet atelier de programmation )

Il est courant que des applications anciennes exécutées sur site doivent être modernisées. Cela signifie les rendre évolutifs, sécurisés et déployables dans différents environnements.

Au cours de cet atelier, vous allez :

  1. Conteneurisez l'application PHP.
  2. Migrez vers un service de base de données géré ( Cloud SQL).
  3. Déployez dans Cloud Run (alternative sans opérations à GKE/Kubernetes).
  4. Sécuriser l'application avec Identity and Access Management (IAM) et Secret Manager.
  5. Définissez un pipeline CI/CD via Cloud Build. Cloud Build peut être connecté à votre dépôt Git hébergé sur des fournisseurs Git populaires tels que GitHub ou GitLab, et être déclenché à chaque push vers le dépôt principal, par exemple.
  6. Hébergez les images de l'application sur Cloud Storage. Cela se fait via le montage, et aucun code n'est nécessaire pour modifier l'application.
  7. Lancement de la fonctionnalité IA de génération via Gemini, orchestrée via Cloud Functions (sans serveur).
  8. Familiarisez-vous avec les objectifs de disponibilité et l'exploitation de votre application récemment actualisée.

En suivant ces étapes, vous pouvez moderniser progressivement votre application PHP, en améliorant son évolutivité, sa sécurité et sa flexibilité de déploiement. De plus, passer à Google Cloud vous permet d'exploiter sa puissante infrastructure et ses services pour vous assurer que votre application s'exécute correctement dans un environnement cloud natif.

Nous pensons que ce que vous apprendrez en suivant ces étapes simples peut être appliqué à votre propre application et à votre organisation avec une autre langue/pile et d'autres cas d'utilisation.

À propos de l'application

L'application ( code, sous licence MIT) que vous allez dupliquer est une application PHP 5.7 de base avec authentification MySQL. L'idée principale de l'application est de fournir une plate-forme sur laquelle les utilisateurs peuvent importer des photos, et les administrateurs peuvent taguer les images inappropriées. L'application comporte deux tables :

  • Utilisateurs : Précompilé avec les administrateurs. Les nouveaux utilisateurs peuvent s'inscrire.
  • Images Il est fourni avec quelques exemples d'images. Les utilisateurs connectés peuvent importer de nouvelles photos. Ajoutons un peu de magie ici.

Votre objectif

Nous voulons moderniser l'ancienne application afin de l'avoir dans Google Cloud. Nous tirerons parti de ses outils et services pour améliorer l'évolutivité, renforcer la sécurité, automatiser la gestion de l'infrastructure et intégrer des fonctionnalités avancées telles que le traitement des images, la surveillance et le stockage des données à l'aide de services tels que Cloud SQL, Cloud Run, Cloud Build, Secret Manager, etc.

445f7a9ae37e9b4d.png

Plus important encore, nous souhaitons le faire pas à pas afin que vous puissiez découvrir le processus de réflexion derrière chaque étape. En général, chaque étape ouvre de nouvelles possibilités pour les suivantes (par exemple, les modules 2 -> 3 et 6 -> 7).

Vous n'êtes pas encore convaincu ? Regardez cette vidéo de sept minutes sur YouTube.

Prérequis

  • Un ordinateur avec un navigateur connecté à Internet.
  • Des crédits GCP Demandez-en à votre fan Google local. ;)
  • La commande gcloud fonctionne.
  • Vous travaillez en local ? Pour le télécharger, cliquez ici. Vous aurez également besoin d'un éditeur de qualité (par exemple, VS Code ou IntelliJ).
  • Vous souhaitez tout faire dans le cloud ? Dans ce cas, vous pouvez utiliser Cloud Shell.
  • Utilisateur GitHub. Vous en avez besoin pour créer une branche du code d'origine 🧑🏻‍💻 gdgpescara/app-mod-workshop avec votre propre dépôt Git. Vous devez disposer de votre propre pipeline CI/CD (commit automatique -> compilation -> déploiement).

Vous trouverez des exemples de solutions ici:

Vous pouvez suivre cet atelier depuis votre ordinateur local ou complètement dans un navigateur.

2. Configuration du crédit et fourchette

6dafc658860c0ce5.png

Utiliser le crédit GCP et configurer votre environnement GCP [facultatif]

Pour suivre cet atelier, vous devez disposer d'un compte de facturation avec un crédit. Si vous disposez déjà de votre propre système de facturation, vous pouvez ignorer cette étape.

Créez un compte Google Gmail (*) à associer à votre crédit GCP. Demandez à votre enseignant le lien permettant d'utiliser le crédit GCP ou utilisez-le sur cette page: bit.ly/PHP-Amarcord-credits .

Connectez-vous avec le compte nouvellement créé et suivez les instructions.

ff739240dbd84a30.png

(

) Pourquoi ai-je besoin d'un tout nouveau compte Gmail ?*

Nous avons constaté que certains participants n'ont pas réussi l'atelier de programmation, car leur compte (en particulier leur adresse e-mail professionnelle ou étudiante) avait déjà été exposé à GCP et était soumis à des règles organisationnelles les empêchant de le faire. Nous vous recommandons de créer un compte Gmail ou d'utiliser un compte Gmail existant (gmail.com) sans exposition préalable à GCP.

Cliquez sur le bouton pour utiliser le crédit.

331658dc50213403.png

Remplissez le formulaire suivant avec votre nom et votre prénom, puis acceptez les conditions d'utilisation.

Vous devrez peut-être attendre quelques secondes avant que le compte de facturation ne s'affiche à l'adresse https://console.cloud.google.com/billing.

Une fois cela fait, ouvrez la console Google Cloud et créez un projet en cliquant sur le sélecteur de projet dans le menu déroulant en haut à gauche, où "Aucune organisation" s'affiche. Voir ci-dessous

bd7548f78689db0b.png

Si vous n'en avez pas, créez un projet, comme illustré dans la capture d'écran ci-dessous. L'option "NEW PROJECT" (NOUVEAU PROJET) s'affiche en haut à droite.

6c82aebcb9f5cd47.png

Veillez à associer le nouveau projet au compte de facturation d'essai GCP comme suit.

f202527d254893fb.png

Vous êtes prêt à utiliser Google Cloud Platform. Si vous débutez ou si vous souhaitez simplement tout faire dans un environnement Cloud, vous pouvez accéder à Cloud Shell et à son éditeur via le bouton suivant en haut à gauche, comme illustré ci-dessous.

7d732d7bf0deb12e.png

Assurez-vous que votre nouveau projet est sélectionné en haut à gauche:

Non sélectionné (mauvais):

c2ffd36a781b276a.png

Sélectionné (bon) :

594563c158f4f590.png

Dupliquer l'application à partir de GitHub

  1. Accédez à l'application de démonstration: https://github.com/gdgpescara/app-mod-workshop
  2. Cliquez sur 🍴 Fork (Dupliquer).
  3. Si vous n'avez pas de compte GitHub, vous devez en créer un.
  4. Modifiez les éléments comme vous le souhaitez.

734e51bfc29ee5df.png

  1. Clonez le code de l'application à l'aide de git clone https://github.com/<VOTRE-UTILISATEUR-GITHUB>/<NOM-DE-VOTRE-REPO>
  1. Ouvrez le dossier du projet cloné avec l'éditeur de votre choix. Si vous choisissez Cloud Shell, cliquez sur "Ouvrir l'éditeur", comme indiqué ci-dessous.

40f5977ea4c1d1cb.png

L'éditeur Google Cloud Shell vous fournit tout ce dont vous avez besoin, comme le montre la figure suivante.

a4e5ffb3e9a35e84.png

3. Module 1 : Créer une instance SQL

645902e511a432a6.png

Créer l'instance Google Cloud SQL

Notre application PHP se connectera à une base de données MySQL. Nous devons donc la répliquer dans Google Cloud pour faciliter la migration. Cloud SQL est la solution idéale, car elle vous permet d'exécuter une base de données MySQL entièrement gérée dans Cloud. Pour ce faire, procédez comme suit:

  1. Accédez à la page Cloud SQL : https://console.cloud.google.com/sql/instances.
  2. Cliquez sur "Créer une instance".
  3. Activez l'API (si nécessaire). Cette opération peut prendre quelques secondes.
  4. Sélectionnez MySQL.
  5. (Nous essayons de vous proposer la version la moins chère, afin qu'elle dure plus longtemps):
  • Édition : Enterprise
  • Prédéfini : développement (nous avons essayé le bac à sable, mais cela n'a pas fonctionné pour nous)
  • Mysql Ver: 5.7 (wow, a blast from the past!)
  1. ID d'instance : choisissez appmod-phpapp (si vous modifiez ce paramètre, n'oubliez pas de modifier également les futurs scripts et solutions en conséquence).
  2. Mot de passe: celui de votre choix, mais notez-le sous la forme CLOUDSQL_INSTANCE_PASSWORD
  3. Région : conservez la même que celle choisie pour le reste de l'application (par exemple, Milan = europe-west8)
  4. Disponibilité zonale: zone unique (nous économisons de l'argent pour la démonstration)

Cliquez sur le bouton "Créer une instance" pour déployer la base de données Cloud SQL. ⌛ L'opération prend environ 10 minutes.⌛ En attendant, continuez à lire la documentation. Vous pouvez également commencer à résoudre le module suivant ("Containeriser votre application PHP"), car il n'a aucune dépendance avec ce module de la première partie (jusqu'à ce que vous corrigiez la connexion à la base de données).

Remarque : Cette instance devrait vous coûter environ 7 €/jour. Assurez-vous de le lancer après l'atelier.

Créer la base de données image_catalog et l'utilisateur dans Cloud SQL

Le projet d'application est fourni avec un dossier db/ contenant deux fichiers SQL :

  1. 01_schema.sql : contient du code SQL permettant de créer deux tables contenant les données des utilisateurs et des images.
  2. 02_seed.sql : contient du code SQL permettant d'insérer des données dans les tables créées précédemment.

Ces fichiers seront utilisés ultérieurement une fois la base de données image_catalog créée. Pour ce faire, procédez comme suit:

  1. Ouvrez votre instance, puis cliquez sur l'onglet "Bases de données" :
  2. cliquez sur "Créer une base de données"
  3. appelez-le image_catalog (comme dans la configuration de l'application PHP).

997ef853e5ebd857.png

Ensuite, nous créons l'utilisateur de la base de données. Nous pouvons ainsi nous authentifier dans la base de données image_catalog.

  1. Cliquez maintenant sur l'onglet Utilisateurs.
  2. Cliquez sur "Ajouter un compte utilisateur".
  3. Utilisateur: Créons-en un:
  • Nom d'utilisateur : appmod-phpapp-user
  • Mot de passe: choisissez un mot de passe facile à retenir ou cliquez sur "Générer".
  • Conservez Autoriser tous les hôtes (%).
  1. Cliquez sur "AJOUTER".

Ouvrez la base de données pour accéder à des adresses IP connues.

Notez que dans Cloud SQL, toutes les bases de données sont nées "isolées". Vous devez configurer explicitement un réseau à partir duquel l'application peut être accessible.

  1. Cliquez sur votre instance.
  2. Ouvrez le menu "Connexions".
  3. Cliquez sur l'onglet "Mise en réseau".
  4. Cliquez sous "Réseaux autorisés". Ajoutez maintenant un sous-réseau.
  • Pour le moment, passons à "INSECURE" (NON SÉCURISÉ) afin que l'application fonctionne:
  • Nom : "Tout le monde - NON SÉCURISÉ" (pour rappel, cette solution bon marché n'est pas non plus sécurisée).
  • Réseau : "0.0.0.0/0" (Remarque: NON SÉCURISÉ !)

Cliquez sur "Enregistrer".

L'écran qui s'affiche devrait ressembler à ce qui suit :

5ccb9062a7071964.png

Remarque : Cette solution est un bon compromis pour terminer l'atelier en O(heures). Consultez toutefois le document SÉCURITÉ pour sécuriser votre solution en vue de la production.

Il est temps de tester la connexion à la base de données.

Vérifions si l'utilisateur image_catalog que nous avons créé précédemment fonctionne. Accédez à Cloud SQL Studio dans l'instance, puis saisissez la base de données, l'utilisateur et le mot de passe à authentifier, comme indiqué ci-dessous :

d56765c6154c11a4.png

Vous pouvez maintenant ouvrir l'éditeur SQL et passer à la section suivante.

Importer la base de données depuis le codebase

Utilisez l'éditeur SQL pour importer les tables image_catalog avec leurs données. Récupérer le code SQL à partir des fichiers SQL du dépôt et l'exécuter l'un après l'autre dans l'ordre séquentiel. 01_schema.sql, puis 02_seed.sql.

Deux tables devraient ensuite s'afficher dans image_catalog, à savoir users et images, comme indiqué ci-dessous:

65ba01e4c6c2dac0.png

Vous pouvez le tester en exécutant la commande suivante dans l'éditeur: select * from images;

Notez également l'adresse IP publique, car vous en aurez besoin plus tard.

4. Module 2 : Conteneuriser votre application PHP

e7f0e9979d8805f5.png

Nous voulons créer cette application pour le cloud.

Cela signifie empaqueter le code dans un fichier ZIP contenant toutes les informations nécessaires pour l'exécuter dans le cloud.

Il existe plusieurs façons de les empaqueter:

  • Docker Très populaire, mais assez complexe à configurer correctement.
  • Buildpacks Moins populaire, mais a tendance à "deviner automatiquement" ce qu'il faut créer et ce qu'il faut exécuter. Souvent, cela fonctionne tout simplement.

Dans le cadre de cet atelier, nous partons du principe que vous utilisez Docker.

Docker

Si vous souhaitez garder le contrôle, cette solution est faite pour vous. Cela est utile lorsque vous devez configurer des bibliothèques spécifiques et injecter certains comportements non évidents (un chmod dans les importations, un exécutable non standard dans votre application, etc.).

Comme nous voulons finalement déployer notre application conteneurisée sur Cloud Run, consultez la documentation suivante et essayez de remplir les espaces vides. Pour le moment, nous ne fournissons que l'essentiel. Votre fichier Dockerfile final devrait ressembler à ceci :

# Use an official PHP image with Apache
# Pull a suitable php image
FROM __________# Define the env variable for the Apache listening port 8080
ENV __________

# Set working directory inside the container
WORKDIR __________

# Install required PHP extensions: PDO, MySQL, and other dependencies
RUN __________

# Copy all application files into the container
COPY __________

# Configure Apache to listen on port 8080. Use ‘sed' command to change the default listening port.
RUN __________

# When in doubt, always expose to port 8080
EXPOSE __________

# Start Apache in the foreground
CMD __________

De plus, afin de tester notre application en local, nous devons modifier le fichier config.php de sorte que notre application PHP se connecte à la base de données MYSQL disponible sur Google CloudSQL. En vous appuyant sur ce que vous avez configuré précédemment, complétez les espaces vides.

  • Db_host est l'adresse IP publique de Cloud SQL. Vous pouvez la trouver dans la console:

bd27071bf450a8d0.png

  • Le champ "DB_name" ne doit pas changer: image_catalog
  • Db_user doit être appmod-phpapp-user.
  • Db_pass est un mot de passe que vous avez choisi. Configurez-le entre guillemets simples et échappez-le si nécessaire.
<?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();
?>

N'hésitez pas non plus à traduire les quelques articles en italien en anglais avec l'aide de Gemini.

Maintenant que vous avez le Dockerfile et que vous avez configuré votre application PHP pour qu'elle se connecte à votre base de données, essayons !

Installez Docker si vous ne l'avez pas encore fait (lien). Vous n'avez pas besoin de cela si vous utilisez Cloud Shell (n'est-ce pas génial ?).

À présent, essayez de créer et d'exécuter votre application PHP conteneurisée avec les commandes Docker de compilation et d'exécution appropriées.

  • docker build -t <IMAGE_TAG_NAME> .
  • docker run -it -p <PORT DU CONTENEUR>:<PORT DU MACHINE LOCAL> <IMAGE_TAG_NAME>

Si tout fonctionne, la page Web suivante devrait s'afficher lorsque vous êtes connecté à l'hôte local.

Si vous utilisez Cloud Shell, vous pouvez également exporter le port local (par exemple, 8080) vers votre navigateur, comme suit:

docker build -t my-php-app-docker app-mod-workshop/ -f Dockerfile

docker run -it -p 8080:8080 my-php-app-docker

Maintenant que vous savez que votre application s'exécute sur le port 8080, cliquez sur l'icône "Aperçu sur le Web" (un navigateur avec un œil), puis sur Prévisualiser sur le port 8080 (ou sur "Modifier le port" pour tout autre port).

33a24673f4550454.png

Tester le résultat dans votre navigateur

Votre application devrait maintenant se présenter comme suit :

2718ece96b1f18b6.png

Si vous vous connectez avec Admin/admin123, vous devriez voir un écran semblable à celui-ci.

68b62048c2e86aea.png

Super ! Ça fonctionne 🎉🎉🎉

Si votre dockerisation est correcte, mais que les identifiants de la base de données sont incorrects, le message suivant peut s'afficher:

e22f45b79bab86e1.png

Réessayez, vous y êtes presque !

Buildpacks [facultatif]

Avec les buildpacks, l'application est compilée automatiquement. Malheureusement, vous ne disposez pas d'un contrôle total. Vous risquez donc de vous retrouver avec une configuration inattendue.

Vous devez disposer d'une nouvelle image Docker dans votre environnement local. Vous pouvez essayer d'exécuter un conteneur pour cela, mais comme nous n'avons pas le contrôle total de la façon dont l'image a été créée, l'application risque de ne pas fonctionner. Dans tous les cas, nous vous invitons à tester cette fonctionnalité et, si vous êtes satisfait, à nous faire part de votre avis. Merci !

Enregistrer dans Artifact Registry [facultatif]

Vous devriez maintenant disposer d'une application PHP conteneurisée fonctionnelle, prête à être déployée dans le cloud. Ensuite, nous avons besoin d'un emplacement dans le cloud pour stocker notre image Docker et la rendre accessible pour le déploiement sur les services Google Cloud tels que Cloud Run. Cette solution de stockage s'appelle Artifact Registry, un service Google Cloud entièrement géré conçu pour stocker des artefacts d'application, y compris des images de conteneurs Docker, des packages Maven, des modules npm, etc.

Créons un dépôt dans Google Cloud Artifact Registry à l'aide du bouton approprié.

e1123f0c924022e6.png

Choisissez un nom valide, le format et la région appropriés pour stocker les artefacts.

4e516ed209c470ee.png

Revenez à votre balise d'environnement de développement local et transférez l'image du conteneur de l'application vers le dépôt Artifact Registry que vous venez de créer. Pour ce faire, exécutez les commandes suivantes.

  • docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
  • docker push TARGET_IMAGE[:TAG]

Le résultat doit se présenter comme suit.

1e498feb4e88be9f.png

Bravo 🎉🎉🎉, vous pouvez passer au niveau suivant.

Note. Essayez également le point de terminaison /upload.php et d'importer une image. Vous pouvez recevoir un message "Autorisation refusée". Si c'est le cas, vous devez corriger chmod/chown dans Dockerfile.

5. Module 3 : Déployer l'application sur Cloud Run

9ffca42774f6c5d1.png

Pourquoi Cloud Run ?

Bonne question ! Il y a quelques années, vous auriez certainement choisi Google App Engine.

En termes simples, Cloud Run dispose aujourd'hui d'une pile technologique plus récente, est plus facile à déployer, moins coûteux et se réduit à zéro lorsque vous ne l'utilisez pas. Grâce à sa flexibilité permettant d'exécuter n'importe quel conteneur sans état et à son intégration à divers services Google Cloud, il est idéal pour déployer des microservices et des applications modernes avec un coût minimal et une efficacité maximale.

Plus précisément, Cloud Run est une plate-forme entièrement gérée par Google Cloud qui vous permet d'exécuter des applications conteneurisées sans état dans un environnement sans serveur. Il gère automatiquement toute l'infrastructure, en effectuant un scaling à partir de zéro pour couvrir le trafic entrant et à une baisse en cas d'inactivité, ce qui rend cette solution économique et efficace. Cloud Run est compatible avec n'importe quel langage ou n'importe quelle bibliothèque, à condition qu'il soit empaqueté dans un conteneur, ce qui offre une grande flexibilité de développement. Il s'intègre bien aux autres services Google Cloud et convient à la création de microservices, d'API, de sites Web et d'applications basées sur des événements sans avoir à gérer l'infrastructure serveur.

Prérequis

Pour effectuer cette tâche, vous devez avoir installé gcloud sur votre ordinateur local. Si ce n'est pas le cas, consultez ces instructions. Si vous utilisez Google Cloud Shell, aucune action n'est requise de votre part.

Avant de déployer…

Si vous travaillez dans votre environnement local, authentifiez-vous auprès de Google Cloud à l'aide des éléments suivants :

  • $ gcloud auth login –update-adc # not needed in Cloud Shell

Vous devriez alors être authentifié via une connexion OAuth dans votre navigateur. Assurez-vous de vous connecter à Chrome avec le même utilisateur (par exemple, vattelapesca@gmail.com) qui est connecté à Google Cloud avec la facturation activée.

Activez l'API Cloud Run à l'aide de la commande suivante :

  • $ gcloud services enable run.googleapis.com

À ce stade, tout est prêt à être déployé sur Cloud Run.

Déployer votre application dans Cloud Run via gcloud

La commande qui vous permet de déployer l'application sur Cloud Run est gcloud run deploy. Vous pouvez définir plusieurs options pour atteindre votre objectif. L'ensemble minimal est le suivant:

  1. Nom du service Cloud Run que vous souhaitez déployer pour votre application. Un service Cloud Run vous renverra une URL qui fournit un point de terminaison à votre application.
  2. Région Google Cloud dans laquelle votre application sera exécutée.
  3. Image de conteneur qui encapsule votre application.
  4. Variables d'environnement que votre application doit utiliser pendant son exécution.
  5. L'option Allow-Unauthenticated (Autoriser l'accès non authentifié) qui permet à tous les utilisateurs d'accéder à votre application sans authentification supplémentaire

Consultez la documentation pour découvrir comment appliquer cette option à votre commande. Le déploiement prend quelques minutes. Si tout est correct, vous devriez voir quelque chose comme ceci dans la console Google Cloud.

ef1029fb62f8de81.png

f7191d579c21ca3e.png

Cliquez sur l'URL fournie par Cloud Run et testez votre application. Une fois authentifié, vous devriez voir quelque chose qui ressemble à ceci :

d571a90cd5a373f9.png

"gcloud run deploy" avec "no questions"

Vous avez peut-être remarqué que gcloud run deploy vous pose les bonnes questions et remplit les espaces vides que vous avez laissés. C'est incroyable !

Cependant, dans quelques modules, nous allons ajouter cette commande à un déclencheur Cloud Build afin de ne pas pouvoir autoriser les questions. Nous devons renseigner toutes les options de la commande. Vous voulez donc créer le gcloud run deploy --option1 blah --foo bar --region your-fav-region doré. Comment faut-il que vous procédiez ?

  1. Répétez les étapes 2, 3 et 4 jusqu'à ce que gcloud cesse de poser des questions:
  2. [LOOP] gcloud run deploy avec les options trouvées jusqu'à présent
  3. Les systèmes [LOOP] demandent l'option X.
  4. [LOOP] Recherchez dans la documentation publique comment configurer X à partir de la CLI en ajoutant l'option --my-option [my-value].
  5. Revenons maintenant à l'étape 2, à moins que gcloud ne termine sans d'autres questions.
  6. Cette commande gcloud run deploy BLAH BLAH BLAH est géniale ! Enregistrez la commande quelque part, car vous en aurez besoin plus tard pour l'étape Cloud Build.

Vous trouverez une solution sur cette page.

Hourra 🎉🎉🎉 ! Vous avez réussi à déployer votre application dans Google Cloud, ce qui constitue la première étape de la modernisation.

6. Module 4: Nettoyer les mots de passe avec Secret Manager

95cd57b03b4e3c73.png

À l'étape précédente, nous avons pu déployer et exécuter notre application dans Cloud Run. Cependant, nous l'avons fait avec une mauvaise pratique de sécurité: fournir quelques secrets en texte clair.

Première itération : mettez à jour votre fichier config.php pour utiliser ENV

Vous avez peut-être remarqué que nous avons placé le mot de passe de la base de données directement dans le code du fichier config.php. Cela convient pour les tests et pour vérifier si l'application fonctionne. Toutefois, vous ne pouvez pas valider ni utiliser un tel code dans un environnement de production. Le mot de passe (et les autres paramètres de connexion à la base de données) doit être lu de manière dynamique et fourni à l'application au moment de l'exécution. Modifiez le fichier config.php afin qu'il lise les paramètres de la base de données à partir des variables d'environnement. En cas d'échec, vous devez envisager de définir des valeurs par défaut. Cela est utile si vous ne parvenez pas à charger ENV. La sortie de la page vous indiquera alors si elle utilise les valeurs par défaut. Complétez les espaces et remplacez le code dans le fichier config.php.

<?php
// Database configuration with ENV variables. Set default values as well 
$db_host = getenv('DB_HOST') ?: _______;
$db_name = getenv('DB_NAME') ?: 'image_catalog';
$db_user = getenv('DB_USER') ?: 'appmod-phpapp-user';
$db_pass = getenv('DB_PASS') ?: _______;
// 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();
?>

Étant donné que votre application est conteneurisée, vous devez fournir un moyen de fournir les variables ENV à l'application. Vous pouvez le faire de plusieurs manières :

  • Au moment de la compilation, dans le fichier Dockerfile. Ajoutez les quatre paramètres à votre Dockerfile précédent à l'aide de la syntaxe ENV DB_VAR=ENV_VAR_VALUE. Les valeurs par défaut peuvent être remplacées lors de l'exécution. Par exemple, "DB_NAME" et "DB_USER" peuvent être définis ici et nulle part ailleurs.
  • Lors de l'exécution. Vous pouvez configurer ces variables pour Cloud Run, à la fois à partir de la CLI et de l'UI. C'est l'endroit idéal pour placer vos quatre variables (sauf si vous souhaitez conserver les valeurs par défaut définies dans le fichier Dockerfile).

Dans localhost, vous pouvez placer vos variables ENV dans un fichier .env (consultez le dossier solutions).

Assurez-vous également que .env est ajouté à votre .gitignore : vous ne voulez pas envoyer vos secrets sur GitHub.

echo .env >> .gitignore

Vous pouvez ensuite tester l'instance localement :

docker run -it -p 8080:8080 --env-file .env my-php-app-docker

Vous avez maintenant accompli les tâches suivantes :

  1. Votre application lira la variable de manière dynamique à partir de votre ENV.
  2. Vous avez amélioré la sécurité en supprimant le mot de passe de la base de données de votre code.)

Vous pouvez maintenant déployer une nouvelle révision sur Cloud Run. Passons à l'interface utilisateur et définissons les variables d'environnement manuellement:

  • Accédez à https://console.cloud.google.com/run.
  • Cliquez sur votre application.
  • Cliquez sur "Modifier et déployer une nouvelle révision".
  • Dans le premier onglet "Conteneur(s)", cliquez sur l'onglet inférieur "Variables et secrets".
  • Cliquez sur "+ Ajouter une variable" et ajoutez toutes les variables nécessaires. Vous devriez obtenir quelque chose comme ceci :

7a5fbfa448544d3.png

f2780c35585388ca.png

Est-ce parfait ? Non. La plupart des opérateurs peuvent toujours voir votre PASS. Ce problème peut être atténué à l'aide de Google Cloud Secret Manager.

Deuxième itération: Secret Manager

Vos mots de passe ont disparu de votre propre code : victoire ! Mais attendez, sommes-nous déjà à l'abri ?

Vos mots de passe restent visibles par toute personne ayant accès à la console Google Cloud. En fait, si vous accédez au fichier de déploiement YAML de Cloud Run, vous pourrez le récupérer. Si vous essayez de modifier ou de déployer une nouvelle version Cloud Run, le mot de passe s'affiche dans la section "Variables et secrets", comme illustré dans les captures d'écran ci-dessous.

Secret Manager de Google Cloud est un service centralisé et sécurisé qui permet de gérer des informations sensibles telles que des clés API, des mots de passe, des certificats et d'autres secrets.

Il vous permet de stocker, de gérer et d'accéder aux secrets avec des autorisations précises et un chiffrement robuste. Intégré à Identity and Access Management (IAM) de Google Cloud, Secret Manager vous permet de contrôler qui peut accéder à des secrets spécifiques, ce qui garantit la sécurité des données et la conformité aux réglementations.

Il est également compatible avec la rotation et la gestion automatiques des secrets, ce qui simplifie la gestion du cycle de vie des secrets et améliore la sécurité des applications dans les services Google Cloud.

Pour accéder à Secret Manager, accédez aux services Sécurité dans le menu hamburger, puis recherchez-le dans la section Protection des données, comme illustré dans la capture d'écran ci-dessous.

6df83a1c3cb757f6.png

Activez l'API Secret Manager comme indiqué sur l'image ci-dessous.

a96c312e2c098db1.png

  • Cliquez maintenant sur Créer un secret. Nommons-le de manière rationnelle :
  • Nom : php-amarcord-db-pass
  • Valeur secrète : votre mot de passe de base de données (ignorez la partie "fichier d'importation").
  • annotate ce lien secret, doit ressembler à projects/123456789012/secrets/php-amarcord-db-pass. Il s'agit du pointeur unique vers votre secret (pour Terraform, Cloud Run et d'autres). Il s'agit de votre numéro de projet unique.

Conseil: Essayez d'utiliser des conventions d'attribution de noms cohérentes pour vos secrets, en spécialisé de gauche à droite, par exemple: cloud-devrel-phpamarcord-dbpass

  • Organisation (avec l'entreprise)
  • Équipe (dans l'organisation)
  • Demande (au sein de l'équipe)
  • Nom de la variable (dans l'application)

Vous pourrez ainsi utiliser des expressions régulières simples pour trouver tous vos secrets pour une seule application.

Créer une révision Cloud Run

Maintenant qu'un nouveau secret est en place, nous devons nous débarrasser de la variable ENV DB_PASS et la remplacer par le nouveau secret. Exemple :

  • Accéder à Cloud Run à l'aide de la console Google Cloud
  • Sélectionnez l'application.
  • Cliquez sur "Modifier et déployer une nouvelle révision".
  • recherchez l'onglet "Variables et secrets".
  • Utilisez le bouton "+ Référencer un secret" pour réinitialiser la variable ENV DB_PASS.
  • Utilisez le même "DB_PASS" pour les secrets référencés et utilisez la dernière version.

9ed4e35be7654dcb.png

Vous devriez alors recevoir l'erreur suivante :

da0ccd7af39b04ed.png

Essayez de trouver comment le résoudre. Pour résoudre ce problème, vous devez accéder à la section IAM et administration et modifier les autorisations accordées. Bon débogage !

Une fois que vous avez trouvé la solution, revenez à Cloud Run et redéployez une nouvelle version. Le résultat doit se présenter comme suit :

e89f9ca780169b6b.png

Conseil : La console du développeur (UI) est très utile pour identifier les problèmes d'autorisation. Prenez le temps d'explorer tous les liens de vos entités Cloud.

7. Module 5 : Configurer votre CI/CD avec Cloud Build

ba49b033c11be94c.png

Pourquoi un pipeline CI/CD ?

À ce stade, vous devriez avoir saisi gcloud run deploy plusieurs fois, et peut-être répondu à la même question plusieurs fois.

Vous en avez assez de déployer manuellement votre application avec gcloud run deploy ? N'est-il pas pratique que votre application puisse se déployer automatiquement chaque fois que vous envoyez une nouvelle modification dans votre dépôt Git ?

Pour utiliser un pipeline CI/CD, vous avez besoin de deux éléments:

  1. Un dépôt Git personnel: heureusement, vous avez déjà dupliqué le dépôt de l'atelier dans votre compte GitHub à l'étape 2. Dans le cas contraire, revenez en arrière et effectuez cette étape. Votre dépôt du fork doit se présenter comme suit : https://github.com/<YOUR_GITHUB_USER>/app-mod-workshop
  2. Cloud Build. Ce service incroyable et abordable vous permet de configurer des automatisations de compilation pour à peu près tout: Terraform, applications dockerisées, etc.

Cette section explique comment configurer Cloud Build.

Découvrez Cloud Build !

Pour ce faire, nous allons utiliser Cloud Build :

  • compiler votre source (avec Dockerfile) ; Il s'agit d'un "gros fichier ZIP" qui contient tout ce dont vous avez besoin pour le compiler et l'exécuter (votre "artefact de compilation").
  • Transférez cet artefact vers Artifact Registry (AR).
  • Déployez ensuite AR vers Cloud Run pour l'application "php-amarcord".
  • Une nouvelle version ("révision") de l'application existante sera créée (pensez à une couche avec le nouveau code). Nous la configurerons pour rediriger le trafic vers la nouvelle version si le transfert aboutit.

Voici quelques exemples de builds pour mon application php-amarcord :

f30f42d4571ad5e2.png

Comment parvenons-nous à faire tout cela ?

  1. En créant un fichier YAML parfait: cloudbuild.yaml
  2. en créant un déclencheur Cloud Build.
  3. En vous connectant à notre dépôt GitHub via l'interface utilisateur de Cloud Build.

Créer un déclencheur (et connecter un dépôt)

  • Accédez à https://console.cloud.google.com/cloud-build/triggers.
  • Cliquez sur "Créer un déclencheur".
  • Compilation :
  • Nom: un nom explicite, par exemple on-git-commit-build-php-app
  • Événement: Déployer sur la branche
  • Source: "Connect new repository" (Associer un nouveau dépôt) texte alternatif
  • Une fenêtre s'ouvre sur la droite : "Connect repository" (Connecter un dépôt).
  • Fournisseur de source : "Github" (premier)
  • "Continuer"
  • Authenticate ouvre une fenêtre sur GitHub pour effectuer une authentification croisée. Suivez la procédure et soyez patient. Si vous avez de nombreux dépôts, cela peut prendre un certain temps.
  • "Sélectionner un dépôt". Sélectionnez votre compte/dépôt, puis cochez la case "J'ai compris...".
  • Si le message d'erreur indiquant que l'application GitHub n'est installée sur aucun de vos dépôts s'affiche, cliquez sur "Install Google Cloud Build" (Installer Google Cloud Build), puis suivez les instructions.
  • 23e0e0f1219afea3.pngCliquez sur "Se connecter".
  • bafd904ec07122d2.png
  • Bravo ! Votre dépôt est désormais associé.
  • Revenons à la partie "Déclencheur".
  • Configuration : Autodétectée (*)
  • Avancé: sélectionnez le compte de service "[PROJECT_NUMBER]- compute@developer.gserviceaccount.com"
  • xxxxx est l'ID de votre projet.
  • Le compte de service Compute par défaut est adapté à une approche de laboratoire. N'utilisez pas ce compte en production. ( En savoir plus)
  • ne pas modifier le reste.
  • Cliquez sur le bouton "Créer".

(*) C'est le moyen le plus simple de vérifier la présence de Dockerfile ou de cloudbuild.yaml. Toutefois, le cloudbuild.yaml vous permet de décider de ce que vous devez faire à chaque étape.

J'ai la puissance !

Le déclencheur ne fonctionnera désormais que si vous attribuez le compte de service Cloud Build (qu'est-ce qu'un compte de service ? l'adresse e-mail d'un "robot" qui agit en votre nom pour une tâche, en l'occurrence la création de produits dans le cloud).

Votre SA ne pourra pas créer ni déployer l'application, sauf si vous lui en donnez l'autorisation. Heureusement, c'est facile !

  • accédez à Cloud Build > Settings (Cloud Build > Paramètres).
  • Compte de service "[PROJECT_NUMBER]- compute@developer.gserviceaccount.com"
  • Cochez les cases suivantes:
  • Cloud Run
  • Secret Manager
  • Comptes de service
  • Cloud Build
  • Cochez également la case "Définir comme compte de service préféré"

8715acca72286a46.png

Où se trouve le fichier YAML Cloud Build ?

Nous vous encourageons vivement à consacrer du temps à la création de votre propre fichier YAML Cloud Build.

Toutefois, si vous n'avez pas le temps ou si vous le souhaitez, vous pouvez trouver des idées dans ce dossier de solutions: .solutions.

Vous pouvez maintenant pousser une modification sur GitHub et observer Cloud Build à son tour.

La configuration de Cloud Build peut s'avérer délicate. Vous devrez peut-être échanger plusieurs fois avec l'équipe d'assistance:

  • Vérifier les journaux sur https://console.cloud.google.com/cloud-build/builds;region=global
  • Trouver votre erreur
  • Correction dans le code et nouvelle émission de git commit / git push.
  • Parfois, l'erreur ne se trouve pas dans le code, mais dans une configuration. Dans ce cas, vous pouvez générer une nouvelle compilation à partir de l'interface utilisateur (Cloud Build > Déclencheurs > Exécuter).

97acd16980a144ab.png

Notez que si vous utilisez cette solution, le travail n'est pas terminé. Par exemple, vous devez définir les variables ENV pour les nouveaux points de terminaison de développement/production:

3da8723e4ff80c0a.png

Pour cela, vous avez le choix entre deux méthodes :

  • Via l'interface utilisateur : en définissant à nouveau les variables ENV
  • Via la CLI en créant le script "parfait" pour vous. Vous trouverez un exemple ici : gcloud-run-deploy.sh. Vous devez modifier quelques éléments, comme le point de terminaison et le numéro de projet. Vous trouverez votre numéro de projet dans la section Présentation de Cloud.

Comment valider du code sur GitHub ?

Il n'entre pas dans le cadre de cet atelier de vous expliquer la meilleure façon de git push sur GitHub. Toutefois, si vous êtes bloqué et que vous utilisez Cloud Shell, vous avez deux options:

  1. CLI Ajoutez une clé SSH localement et ajoutez un dépôt distant avec git@github.com:VOTRE_UTILISATEUR/app-mod-workshop.git (au lieu de http).
  2. VS Code. Si vous utilisez l'éditeur Cloud Shell, vous pouvez utiliser l'onglet "Source control" (Contrôle des sources, Ctrl+Maj+G), cliquer sur "sync changes" (Synchroniser les modifications) et suivre les instructions. Vous devriez pouvoir authentifier votre compte GitHub dans VSCode. Les opérations de pull/push deviennent alors un jeu d'enfant.

f0d53f839c7fa3b6.png

N'oubliez pas de git add clodubuild.yaml, entre autres fichiers. Sinon, cela ne fonctionnera pas.

"parité dev/prod" profonde ou superficielle [facultatif]

Si vous avez copié la version du modèle depuis cette page, vous obtiendrez deux versions DEV et PROD identiques. C'est bien, et cela correspond à la règle 10 de l'application à 12 facteurs.

Cependant, nous utilisons deux points de terminaison Web différents pour que l'application pointe vers la même base de données. Cela suffit pour un atelier. Toutefois, dans la pratique, vous devez prendre le temps de créer un environnement de production approprié. Cela implique de disposer de deux bases de données (une pour le développement et l'autre pour la production) et de choisir également où les stocker pour la reprise après sinistre ou la haute disponibilité. Cela dépasse le cadre de cet atelier, mais c'est un sujet à réfléchir.

Si vous avez le temps de créer une version "approfondie" de la production, n'oubliez pas toutes les ressources que vous devez dupliquer, par exemple:

  • Base de données Cloud SQL (et probablement une instance SQL).
  • Bucket GCS
  • Fonction Cloud
  • Vous pouvez utiliser Gemini 1.5 Flash comme modèle en développement (moins cher, plus rapide) et Gemini 1.5 Pro (plus puissant).

En règle générale, chaque fois que vous modifiez l'application, réfléchissez de manière critique: la production doit-elle avoir la même valeur ou non ? Si ce n'est pas le cas, redoublez d'efforts. Cela est bien sûr beaucoup plus facile avec Terraform, où vous pouvez injecter votre environnement (-dev, -prod) en tant que suffixe à vos ressources.

8. Module 6 : Passer à Google Cloud Storage

a680e0f287dd2dfb.png

Stockage

Actuellement, l'application stocke l'état dans un conteneur Docker. Si la machine tombe en panne, si l'application plante ou si vous poussez une nouvelle version, une nouvelle version sera planifiée, avec un stockage réinitialisé (=> vide). 🙈

Comment y remédier ? Il existe plusieurs approches.

  1. Stockez les images dans la base de données. C'est ce que j'ai fini par faire avec mon ancienne application PHP. Il s'agit de la solution la plus simple, car elle n'ajoute pas de complexité. Mais cela ajoute de la latence et de la charge à votre base de données.
  2. Migrez votre application Cloud Run vers une solution économe en espace de stockage : GCE + disque persistant. GKE + Stockage ?
  3. Passez à GCS. Google Cloud Storage offre un stockage de premier ordre pour l'ensemble de Google Cloud. Il s'agit de la solution la plus idiomatique de Google Cloud. Toutefois, cela nécessite de se familiariser avec les bibliothèques PHP. Existe-t-il des bibliothèques PHP 5.7 pour GCS ? PHP 5.7 est-il même compatible avec Composer (il semble que PHP 5.3.2 est la version la plus ancienne compatible avec Composer) ?
  4. Utiliser un sidecar Docker ?
  5. Vous pouvez également utiliser les installations de volume Cloud Run de GCS. Ça a l'air incroyable.

🤔 Migrer l'espace de stockage (champ libre)

[Question ouverte] Dans cet exercice, nous vous invitons à trouver une solution pour déplacer vos images de manière persistante.

Test d'acceptation

Je ne veux pas vous donner la solution, mais je veux que cela se produise:

  1. Vous importez newpic.jpg. Il apparaît dans l'application.
  2. Vous mettez à niveau l'application vers une nouvelle version.
  3. newpic.jpg est toujours là, visible.

💡 Solution possible (montage de volumes GCS Cloud Run)

Il s'agit d'une solution très élégante qui nous permet d'effectuer des importations de fichiers avec état sans toucher TOUT le code (à l'exception de l'affichage d'une description d'image, mais c'est trivial et pour une simple satisfaction oculaire).

Vous devriez pouvoir monter un dossier de Cloud Run vers GCS. Pour ce faire:

  1. Toutes les importations dans GCS seront visibles dans votre application.
  2. Toutes les importations dans votre application seront en fait importées dans GCS.
  3. La magie opère sur les objets importés dans GCS (chapitre 7).

Remarque : Veuillez lire les conditions d'utilisation de FUSE. Ce n'est PAS acceptable si les performances sont un problème.

Créer un bucket GCS

GCS est le service de stockage omniprésent de Google Cloud. Il a fait ses preuves et est utilisé par tous les services GCP nécessitant de l'espace de stockage.

Notez que Cloud Shell exporte PROJECT_ID en tant que 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/"

Configurer Cloud Run pour monter le bucket dans le dossier /uploads/

Passons maintenant à la partie élégante. Nous créons un volume php_uploads et demandons à Cloud Run d'effectuer une installation FUSE sur MOUNT_PATH (par exemple, /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"

Répétez cette étape pour tous les points de terminaison que vous souhaitez rediriger vers Cloud Storage.

Vous pouvez également obtenir le même résultat à partir de l'UI

  1. Dans l'onglet "Volumes" (Volumes), créez un montage de volume pointant vers votre bucket, de type "bucket Cloud Storage", par exemple avec le nom "php_uploads".
  2. Sous "Container(s) > Volume Mounts" (Conteneurs > Installations de volume), installez le volume que vous venez de créer au point d'installation demandé par votre application. Cela dépend du fichier Docker, mais cela peut ressembler à var/www/html/uploads/.

Dans tous les cas, si cela fonctionne, la modification de la nouvelle révision Cloud Run devrait ressembler à ceci:

6c2bb98fc1b0e077.png

Testez maintenant la nouvelle application qui importe une nouvelle image dans le point de terminaison /upload.php.

Les images doivent s'afficher sans problème sur GCS sans écrire une seule ligne de code PHP:

70032b216afee2d7.png

Que s'est-il passé ?

Un événement magique s'est produit.

Une ancienne application avec un ancien code continue de fonctionner. Une nouvelle pile modernisée nous permet de placer toutes les images de notre application dans un bucket Cloud avec état. Désormais, le ciel est la limite :

  • Vous souhaitez envoyer un e-mail chaque fois qu'une image avec la mention "dangereux" ou "nu" est reçue ? Vous pouvez le faire sans modifier le code PHP.
  • Vous voulez utiliser un modèle multimodal Gemini chaque fois qu'une image arrive pour la décrire, et importer la base de données avec sa description ? Vous pouvez le faire sans toucher au code PHP. Vous ne me croyez pas ? Poursuivez votre lecture au chapitre 7.

Nous venons de découvrir un vaste champ d'opportunités.

9. Module 7 : Optimiser votre application avec Google Gemini

c00425f0ad83b32c.png

Vous disposez désormais d'une nouvelle application PHP moderne et brillante (comme une Fiat 126 de 2024) avec un stockage cloudifié.

À quoi sert-il ?

Prérequis

Dans le chapitre précédent, une solution modèle nous a permis de monter des images /uploads/ sur GCS, de facto séparant la logique de l'application du stockage des images.

Pour cet exercice, vous devez :

  • Avoir terminé l'exercice du chapitre 6 (stockage)
  • Vous devez disposer d'un bucket GCS contenant les images importées, dans lequel les utilisateurs importent des images dans votre application.

Configurer une fonction Cloud (en Python)

Vous êtes-vous déjà demandé comment implémenter une application basée sur des événements ? Par exemple :

  • lorsque <événement> se produit => envoyer un e-mail
  • Lorsque <événement> se produit => si <condition> est vraie, mettez à jour la base de données.

Un événement peut être n'importe quoi, par exemple un nouvel enregistrement disponible dans BigQuery, un nouvel objet modifié dans un dossier de GCS ou un nouveau message en attente dans une file d'attente dans Pub/Sub.

Google Cloud prend en charge plusieurs paradigmes pour y parvenir. Plus précisément :

Dans cet exercice, nous allons nous pencher sur la fonction Cloud pour obtenir un résultat spectaculaire. Nous vous fournirons également des exercices facultatifs.

Notez qu'un exemple de code est fourni sous .solutions/.

Configurer une fonction Cloud (🐍 Python)

Nous essayons de créer un CHF très ambitieux.

  1. Lorsqu'une image est créée dans GCS. (probablement parce que quelqu'un l'a importé dans l'application, mais pas seulement).
  2. ... appeler Gemini pour la décrire et obtenir une description textuelle de l'image...
  3. .. et mettez à jour la base de données avec cette description. (vous devrez peut-être appliquer un correctif à la base de données pour ajouter une colonne description à la table images).

Appliquer un correctif à la base de données pour ajouter description aux images

  1. Ouvrez Cloud SQL Studio :

b92b07c4cba658ef.png

  1. Saisissez votre nom d'utilisateur et votre mot de passe pour la base de données d'images
  2. Injectez cette instruction SQL qui ajoute une colonne pour la description d'une image:

ALTER TABLE images ADD COLUMN description TEXT;

3691aced78a6389.png

Et bingo ! Essayez maintenant de vérifier si cela a fonctionné :

SELECT * FROM images;

La nouvelle colonne de description devrait s'afficher:

bed69d6ad0263114.png

Écrire la fonction Gemini f(x)

Remarque : Cette fonction a été créée avec l'aide de Gemini Code Assist.

Remarque : La création de cette fonction peut entraîner des erreurs d'autorisation IAM. Certaines sont décrites ci-dessous, dans le paragraphe "Erreurs possibles".

  1. Activer les API
  2. Accédez à https://console.cloud.google.com/functions/list.
  3. Cliquez sur "Créer une fonction".
  4. Assistant Activer les API à partir de l'API:

d22b82658cfd4c48.png

Vous pouvez créer le GCF à partir de l'UI ou de la ligne de commande. Nous allons ici utiliser la ligne de commande.

Vous trouverez un code possible sous .solutions/.

  1. Créez un dossier pour héberger votre code, par exemple "gcf/". Accédez au dossier.
  2. Créez un fichier requirements.txt :
google-cloud-storage
google-cloud-aiplatform
pymysql
  1. Créez une fonction Python. Voici un exemple de code: 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
  1. Transférez la fonction. Vous pouvez utiliser un script semblable à celui-ci: gcf/push-to-gcf.sh.

Remarque 1 Assurez-vous de définir les ENV avec les valeurs appropriées, ou ajoutez-les simplement en haut (GS_BUCKET=blah, etc.) :

Remarque 2. Tout le code local (.) sera ainsi transféré. Veillez donc à placer votre code dans un dossier spécifique et à utiliser .gcloudignore comme un pro pour éviter de transférer d'énormes bibliothèques. ( exemple).

#!/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

Remarque: Dans cet exemple, generate_caption est la méthode appelée, et la fonction Cloud lui transmet l'événement GCS avec toutes les informations pertinentes (nom du bucket, nom de l'objet, etc.). Prenez le temps de déboguer cet événement du dictionnaire Python.

Tester la fonction

Tests unitaires

La fonction comporte de nombreuses pièces mobiles. Vous voudrez peut-être pouvoir tester tous les éléments individuels.

Vous trouverez un exemple dans gcf/test.py.

Interface utilisateur de Cloud Functions

Prenez également le temps d'explorer votre fonction dans l'interface utilisateur. Chaque onglet mérite d'être exploré, en particulier Source (mon préféré), Variables, Trigger et Logs. Vous passerez beaucoup de temps dans Logs pour résoudre les erreurs (voir également les erreurs possibles en bas de cette page). Veillez également à consulter Permissions.

cf3ded30d532a2c7.png

Test d'E2E

Il est temps de tester manuellement la fonction.

  1. Accédez à votre application et connectez-vous
  2. Importez une image (pas trop grande, nous avons constaté des problèmes avec les images de grande taille).
  3. Vérifiez dans l'UI que l'image est importée.
  4. Vérifiez dans Cloud SQL Studio que la description a bien été mise à jour. Connectez-vous et exécutez cette requête: SELECT * FROM images.

43a680b12dbbdda0.png

Et il est efficace ! Il est possible que nous souhaitions également mettre à jour l'interface pour afficher cette description.

Mettre à jour PHP pour afficher [facultatif]

Nous avons prouvé que l'application fonctionne. Cependant, il serait utile que les utilisateurs puissent également voir cette description.

Il n'est pas nécessaire d'être un expert en PHP pour ajouter la description à index.php. Ce code devrait fonctionner (oui, Gemini l'a écrit pour moi aussi):

<?php if (!empty($image['description'])): ?>
    <p class="font-bold">Gemini Caption:</p>
    <p class="italic"><?php echo $image['description']; ?></p>
<?php endif; ?>

Placez ce code dans foreach à votre convenance.

Dans les étapes suivantes, nous verrons également une version plus attrayante de l'interface utilisateur, grâce à Gemini Code Assist. Une version soignée peut ressembler à ceci:

fdc12de0c88c4464.png

Conclusions

Vous avez obtenu une fonction Cloud déclenchée sur de nouveaux objets arrivant sur GCS, capable d'annoter le contenu de l'image comme le ferait un être humain et de mettre à jour automatiquement la base de données. Impressionnant !

Étape suivante Vous pouvez suivre le même raisonnement pour obtenir deux fonctionnalités de qualité.

[Facultatif] Ajouter d'autres Cloud Functions [sans limite]

Je pense à quelques fonctionnalités supplémentaires.

Déclencheur par e-mail

Un déclencheur d'e-mail qui vous envoie un e-mail chaque fois qu'une personne envoie une photo.

  • Trop souvent ? Ajoutez une autre contrainte : une grande image ou une image dont le contenu Gemini contient les mots "nu/nudité/violent".
  • Pensez à vérifier EventArc.

🚫 Modération automatique des images inappropriées

Actuellement, un administrateur humain signale les images comme "inappropriées". Que diriez-vous de laisser Gemini s'occuper de la modération de l'espace ? Ajoutez un test pour signaler le contenu inapproprié du déclencheur et mettre à jour la base de données, comme nous l'avons vu dans la fonction précédente. Cela signifie essentiellement de prendre la fonction précédente, de modifier l'invite et de mettre à jour la base de données en fonction de la réponse.

Mise en garde Les résultats de l'IA générative sont imprévisibles. Assurez-vous que la "sortie de création" de Gemini est "sur rails". Vous pouvez demander une réponse déterministe, comme un score de confiance de 0 à 1, un JSON, etc. Vous pouvez y parvenir de plusieurs façons, par exemple : * Utiliser les bibliothèques Python pydantic, langchain, etc. * Utiliser l'output structuré Gemini.

Conseil Vous pouvez avoir plusieurs fonctions ou une seule invite qui applique une réponse JSON (fonctionne parfaitement avec "Gemini Structured Output", comme indiqué ci-dessus), par exemple :

Quelle requête pour générer cela ?

{
    "description": "This is the picture of an arrosticino",
    "suitable": TRUE
}

Vous pouvez ajouter des champs supplémentaires à l'invite pour obtenir des insights, par exemple: y a-t-il quelque chose de positif à ce sujet ? Vous n'êtes pas content ? Reconnaissez-vous ce lieu ? La miniature comporte-t-elle du texte (la reconnaissance optique de caractères n'a jamais été aussi simple) :

  • goods : "On dirait que c'est délicieux."
  • bads : "Ça ressemble à de mauvaises aliments"
  • OCR: "Da consumare preferibilmente prima del 10 Novembre 2024"
  • location : "Pescara, Lungomare"

Bien qu'il soit généralement préférable d'avoir une fonction N pour N résultats, il est extrêmement gratifiant d'en créer une qui en effectue 10. Pour savoir comment procéder, consultez cet article de Riccardo.

Erreurs possibles (principalement IAM/autorisations)

Lorsque j'ai développé cette solution, j'ai eu des problèmes d'autorisation IAM. Je les ajouterai ici pour faire preuve d'empathie et vous donner des idées pour les résoudre.

Erreur: autorisations insuffisantes pour le compte de service

  1. Notez que pour déployer une fonction GCF qui écoute un bucket GCS, vous devez configurer les autorisations appropriées pour le compte de service que vous utilisez pour la tâche, comme illustré ci-dessous :

22f51012fa6b4a24.png

Vous devrez peut-être également activer les API EventArc (quelques minutes avant qu'elles ne soient complètement disponibles).

Erreur : Demandeur Cloud Run manquant

  1. Voici un autre commentaire de l'UI concernant l'autorisation GCF ( Rôle de demandeur Cloud Run):

be72e17294f2d3f3.png

Vous pouvez corriger cette erreur en exécutant la commande dans l'image. Elle est semblable à fix-permissions.sh.

Ce problème est décrit ici: https://cloud.google.com/functions/docs/securing/authenticating.

Erreur : Limite de mémoire dépassée

La première fois que je l'ai exécuté, mes journaux ont indiqué: "Limite de mémoire de 244 Mo dépassée avec 270 Mo utilisés. Envisagez d'augmenter la limite de mémoire. Pour en savoir plus, consultez la page https://cloud.google.com/functions/docs/configuring/memory." Ajoutez de la RAM à votre GCF. C'est très facile à faire dans l'interface utilisateur. Voici un obstacle possible:

bed69d6ad0263114.png

Vous pouvez également corriger votre script de déploiement Cloud Run pour augmenter la mémoire/la CPU. Cette opération prend un peu plus de temps.

Erreur : PubSub publié

La création d'un déclencheur avec GCF v1 provoquait l'erreur suivante:

e5c338ee35ad4c24.png

Pour résoudre ce problème, accédez à IAM et attribuez le rôle "Éditeur Pub/Sub" à votre compte de service.

Erreur : Vertex AI n'a pas été utilisé

Si ce message d'erreur s'affiche:

Accès refusé : 403 L'API Vertex AI n'a jamais été utilisée dans le projet YOUR_PROJECT ou elle est désactivée. Pour l'activer, rendez-vous sur https://console.developers.google.com/apis/api/aiplatform.googleapis.com/overview?project=YOR_PROJECT.

Il vous suffit d'activer les API Vertex AI. Le moyen le plus simple d'activer TOUTES les API nécessaires est le suivant :

  1. https://console.cloud.google.com/vertex-ai
  2. Cliquez sur "Activer toutes les API recommandées".

492f05ac377f3630.png

Erreur : Déclencheur EventArc introuvable.

Si vous obtenez cette erreur, veuillez redéployer la fonction.

8ec4fc11833d7420.png

Erreur : 400 agents de service en cours de provisionnement

400 agents de service sont en cours de provisionnement ( https://cloud.google.com/vertex-ai/docs/general/access-control#service-agents). Les agents de service sont nécessaires pour lire le fichier Cloud Storage fourni. Veuillez donc réessayer dans quelques minutes.

Si cela se produit, attendez un peu ou demandez à un Googleur.

10. Module 8 : Créer des SLO de disponibilité

Dans ce chapitre, nous essayons d'atteindre les objectifs suivants :

  1. Créer des SLI
  2. Créer des SLO basés sur les SLI
  3. Créer des alertes basées sur des SLO

f63426182c052123.png

Il s'agit d'un sujet cher à l'auteur, car Riccardo travaille dans le domaine de l'SRE / DevOps de Google Cloud.

(question ouverte) Créez des SLI et des SLO pour cette application.

Dans quelle mesure une application est-elle performante si vous ne pouvez pas savoir qu'elle est en panne ?

Qu'est-ce qu'un SLO ?

Oh mon Dieu ! Google a inventé les SLO. Pour en savoir plus, je vous suggère de consulter les ressources suivantes :

Étape 1 : Créez un SLI/un SLO de disponibilité

Commençons par l'objectif de disponibilité, car il s'agit de l'élément le plus facile à mesurer et peut-être le plus important.

Heureusement, Cloud Run est compatible avec les SLO prédéfinis, grâce à Istio.

Une fois votre application sur Cloud Run, c'est super simple à faire. Cela me prend 30 secondes.

  • Accédez à votre page Cloud Run.
  • Cliquez/sélectionnez votre application.
  • Sélectionnez l'onglet SLOs.
  • Cliquez sur "+ Créer un SLO".
  • Disponibilité, basée sur les requêtes
  • Continuer
  • Mois calendaire / 99 %
  • cliquez sur "Créer un SLO".

e471c7ebdc56cdf6.png

Étape 2 : Configurer les alertes pour ce SLO

Je vous suggère de créer deux alertes:

  1. Un avec un faible taux de consommation ("Slowburn") pour vous envoyer une alerte par e-mail (simule un ticket de faible priorité).
  2. Un avec un débit de combustion élevé ("Fastburn") pour vous alerter par SMS (simule un ticket de priorité élevée ou un bipeur)

Accédez à votre SLO tab précédent.

Effectuez cette opération deux fois:

314bfd6b9ef0a260.png

  • Cliquez sur "Créer une alerte SLO" (bouton 🔔 avec un signe plus à droite).
  • Durée de l'analyse, seuil du taux d'utilisation :
  • [RAPIDE]. Première : 60 min/10 x
  • [LENT]. Seconde : 720 min / 2 x
  • Canal de notification: cliquez sur "Gérer les canaux de notification".
  • Tout d'abord, "E-mail" -> Ajouter -> ..
  • Deuxièmement, "SMS" -> "Ajouter" -> "Valider sur le téléphone".
  • Conseil: j'aime bien utiliser des emoji dans les noms ! C'est amusant pour les démonstrations.
  • lorsque vous avez terminé, cliquez sur le grand X en haut à droite.
  • Sélectionnez d'abord le téléphone (rapide), puis l'adresse e-mail (lent).
  • Ajoutez des exemples de documentation, par exemple :
  • [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.

Bravo !

Résultat final

Vous pouvez considérer cet exercice comme terminé une fois que vous avez défini un SLO opérationnel et deux alertes pour votre disponibilité, et que ces alertes sont envoyées par e-mail et sur votre téléphone.

Si vous le souhaitez, vous pouvez ajouter une latence (et je vous y encourage vivement) ou même une latence plus complexe. Pour la latence, choisissez une valeur que vous jugez raisonnable. En cas de doute, choisissez 200 ms.

11. Étapes suivantes

Vous avez tout fait, qu'est-ce qui manque ?

Voici quelques points à prendre en compte:

Jouer avec Gemini

Il existe deux versions de Gemini:

  1. Vertex AI La méthode "Enterprise", qui s'intègre à votre GCP, que nous avons abordée dans le chapitre 7 (GCF+Gemini). L'authentification fonctionne comme par magie, et les services s'interconnectent parfaitement.
  2. IA de Google "Parcours consommateur". Vous pouvez obtenir une clé API Gemini sur cette page et commencer à créer de petits scripts qui peuvent être associés à n'importe quelle charge de travail que vous possédez déjà (travail propriétaire, autres clouds, localhost, etc.). Il vous suffit de remplacer votre clé API pour que le code commence à fonctionner comme par magie.

Nous vous encourageons à explorer le (2) avec vos propres projets.

Refonte de l'interface utilisateur

Je ne suis pas doué pour les interfaces utilisateur. Mais Gemini l'est ! Vous pouvez simplement prendre une seule page PHP et dire quelque chose comme ceci:

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!]

Vous pouvez facilement y parvenir en moins de cinq minutes, avec un seul Cloud Build. :)

La réponse de Gemini était parfaite (c'est-à-dire que je n'ai rien eu à modifier):

8a3d5fe37ec40bf8.png

Voici la nouvelle mise en page dans l'application personnelle de l'auteur:

81620eb90ae3229a.png

Remarque : Le code est collé sous forme d'image, car nous ne voulons pas vous encourager à l'utiliser, mais à demander à Gemini de l'écrire pour vous, avec vos propres contraintes d'UI/interface utilisateur. Faites-nous confiance, vous n'aurez ensuite que des modifications très mineures à apporter.

Sécurité

Sécuriser correctement cette application n'est pas un objectif pour cet atelier de quatre heures.

Pour obtenir des idées, consultez la page SECURITY doc.

12. Félicitations !

Félicitations 🎉🎉🎉 , vous avez réussi à moderniser votre ancienne application PHP avec Google Cloud.

24cb9a39b1841fbd.png

En résumé, voici ce que vous avez appris au cours de cet atelier de programmation:

  • Découvrez comment déployer une base de données MYSQL dans Google Cloud SQL et comment y migrer votre base de données existante.
  • Conteneuriser votre application PHP avec Docker et Buildpacks, et stocker son image dans Google Cloud Artifact Registry
  • Déployer votre application conteneurisée sur Cloud Run et l'exécuter avec Cloud SQL
  • Stocker/utiliser de manière secrète des paramètres de configuration sensibles (tels que le mot de passe de la base de données) à l'aide de Google Secret Manager
  • Découvrez comment configurer votre pipeline CI/CD avec Google Cloud Build pour compiler et déployer automatiquement votre application PHP à chaque transfert de code vers votre dépôt GitHub.
  • Utiliser Cloud Storage pour "cloudifier" les ressources de votre application
  • Découvrez comment exploiter les technologies sans serveur pour créer des workflows exceptionnels sur Google Cloud sans modifier le code de votre application.
  • Utilisez les fonctionnalités multimodales de Gemini pour un cas d'utilisation approprié.

C'est un bon début pour votre parcours dans la modernisation des applications avec Google Cloud.

🔁 Commentaires

Si vous souhaitez nous faire part de votre expérience de cet atelier, remplissez ce formulaire de commentaires.

Nous attendons vos commentaires et vos communiqués pour les éléments de code dont vous êtes particulièrement fier.

ↀ Merci

L'auteur tient à remercier Mirko Gilioli et Maurizio Ipsale de Datatonic pour leur aide dans la rédaction et le test de la solution.