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écurisez 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 progressivement moderniser 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 bifurquer 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 images. Nous allons ajouter un peu de magie ici.

Votre objectif

Nous souhaitons moderniser l'ancienne application afin de l'intégrer à Google Cloud. Nous allons exploiter 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 d'images, la surveillance et le stockage de données à l'aide de services tels que Cloud SQL, Cloud Run, Cloud Build, Secret Manager et plus encore.

445f7a9ae37e9b4d.png

Plus important encore, nous voulons le faire étape par étape afin que vous puissiez apprendre 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 7 minutes sur YouTube.

Prérequis

  • Un ordinateur équipé d'un navigateur et connecté à Internet
  • Des crédits GCP Demandez-en à votre fan Google local. ;)
  • La commande gcloud fonctionne.
  • Travaillez-vous en mode local ? Téléchargez-le ici. Vous aurez également besoin d'un éditeur de qualité (par exemple, VS Code ou IntelliJ).
  • Vous souhaitez tout faire dans le cloud ? Vous pouvez ensuite 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. Cela vous permet de 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 qui les empêchaient de le faire. Nous vous recommandons de créer un compte Gmail ou d'utiliser un compte Gmail existant (gmail.com) qui n'a jamais été utilisé avec 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.

Ouvrez ensuite 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-en un, comme illustré dans la capture d'écran ci-dessous. L'option "NEW PROJECT" (NOUVEAU PROJET) s'affiche en haut à droite.

6c82aebcb9f5cd47.png

Assurez-vous d'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 êtes débutant ou si vous souhaitez simplement effectuer toutes les tâches 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

Forker l'application depuis GitHub

  1. Accédez à l'application de démonstration: https://github.com/gdgpescara/app-mod-workshop
  2. Cliquez sur 🍴 Fork (Dupliquer).
  3. Si vous ne possédez 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
  2. git clone https://github.com/YOUR-GITHUB-USER/YOUR-REPO-NAME
  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

Vous disposez de tout ce dont vous avez besoin avec l'éditeur Google Cloud Shell, comme le montre la figure suivante.

a4e5ffb3e9a35e84.png

Pour ce faire, cliquez sur "Ouvrir un dossier", puis sélectionnez le dossier, probablement app-mod-workshop dans votre dossier d'accueil.

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 il vous permet d'exécuter une base de données MySQL entièrement gérée dans le 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é)
  • Version MySQL: 5.7 (wow, un souvenir du passé !)
  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. Veillez à le faire tourner 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 des données sur les utilisateurs et les 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

Nous créons ensuite 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".

Ouvrir la base de données aux adresses IP connues

Notez que toutes les bases de données de Cloud SQL sont "isolées" par défaut. 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 réseau (un sous-réseau).
  • Pour l'instant, choisissons des paramètres rapides, mais NON SÉCURISÉS, afin que l'application fonctionne. Vous pourrez la limiter plus tard aux adresses IP de confiance:
  • Nom: "Tout le monde dans le monde - INSECURE".
  • Réseau: "0.0.0.0/0"" (remarque: il s'agit de la partie NON SÉCURISÉE)
  • Cliquez sur "OK".
  1. 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 à partir du code source

Utilisez l'éditeur SQL pour importer les tables image_catalog avec leurs données. Copiez le code SQL des fichiers du dépôt ( 01_schema.sql, puis 02_seed.sql) et exécutez-les l'un après l'autre dans l'ordre séquentiel.

Vous devriez alors obtenir deux tables dans image_catalog, à savoir users et images, comme illustré 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 de l'instance Cloud SQL, car vous en aurez besoin plus tard. Pour obtenir l'adresse IP, accédez à la page principale de l'instance Cloud SQL, sous la section Présentation. (Vue d'ensemble > Se connecter à cette instance > Adresse IP publique).

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.

Vous pouvez le faire de plusieurs façons:

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

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

Si vous avez choisi d'utiliser Cloud Shell, il est temps de le rouvrir (cliquez en haut à droite de la console Cloud).

ec6a6b90b39e03e.png

Un shell pratique devrait s'ouvrir en bas de la page, où vous devriez avoir créé un fork du code à l'étape de configuration.

6999b906c0dedeb7.png

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. Comment le porter à partir de PHP 8 vers PHP 5.7 ? Vous pouvez peut-être utiliser Gemini pour cela. Vous pouvez également utiliser cette version prédéfinie:

fbd8c2ace2faa70b.png

La dernière version de Dockerfile est disponible sur cette page.

Pour tester notre application localement, nous devons modifier le fichier config.php afin que notre application PHP se connecte à la base de données MYSQL disponible sur Google CloudSQL. Sur la base de ce que vous avez configuré précédemment, complétez les espaces vides:

<?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 est l'adresse IP publique de Cloud SQL. Vous la trouverez dans la console SQL:

bd27071bf450a8d0.png

  • DB_NAME ne doit pas être modifié: image_catalog
  • DB_USER doit être appmod-phpapp-user.
  • DB_PASS est un élément que vous avez choisi. Configurez-le entre guillemets simples et échappez-le si nécessaire.

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 vous connecter à 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.

Essayez maintenant de créer et d'exécuter votre application PHP conteneurisée à l'aide des commandes de compilation et d'exécution Docker appropriées.

# 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

Si tout fonctionne, vous devriez voir la page Web suivante lorsque vous êtes connecté à l'hôte local. Votre application s'exécute maintenant 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 "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 ! À part le texte italien, tout 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 êtes presque là !

Enregistrement dans Artifact Registry [facultatif]

Vous devriez maintenant disposer d'une application PHP conteneurisée fonctionnelle, prête à être déployée dans le cloud. Nous avons ensuite besoin d'un emplacement dans le cloud pour stocker notre image Docker et la rendre accessible pour le déploiement dans 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 à l'étape suivante. Avant cela, prenez deux minutes pour essayer l'importation, la connexion et la déconnexion, et vous familiariser avec les points de terminaison de l'application.Vous en aurez besoin plus tard.

Erreurs possibles

Si vous rencontrez des erreurs de conteneurisation, essayez d'utiliser Gemini pour expliquer et corriger l'erreur en fournissant les informations suivantes:

  • Votre Dockerfile actuel
  • L'erreur reçue
  • [si nécessaire] le code PHP exécuté.

Autorisations d'importation Essayez également le point de terminaison /upload.php et d'importer une image. L'erreur ci-dessous peut s'afficher. Si c'est le cas, vous devez corriger chmod/chown dans Dockerfile.

Avertissement: move_uploaded_file(uploads/image (3).png): échec de l'ouverture du flux: autorisation refusée dans /var/www/html/upload.php à la ligne 11

PDOException "driver not found" (ou "Errore di connessione: driver not found"). Assurez-vous que votre Dockerfile contient les bibliothèques PDO appropriées pour mysql (pdo_mysql) afin de vous connecter à la base de données. Inspirez-vous des solutions proposées dans cette page.

Impossible de transférer votre demande vers un backend. Impossible de se connecter à un serveur sur le port 8080. Cela signifie que vous exposez probablement le mauvais port. Assurez-vous d'exposer le port à partir duquel Apache/Nginx diffusent réellement. Ce n'est pas anodin. Si possible, essayez de définir ce port sur 8080 (cela facilite la tâche avec Cloud Run). Si vous souhaitez conserver le port 80 (par exemple, parce qu'Apache le souhaite), utilisez une autre commande pour l'exécuter:

$ 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. Module 3: Déployer l'application sur Cloud Run

9ffca42774f6c5d1.png

Pourquoi utiliser 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 à la hausse à partir de zéro pour répondre au trafic entrant et à la baisse lorsqu'il est inactif. Il est donc économique et efficace. Cloud Run est compatible avec n'importe quel langage ou bibliothèque, à condition qu'ils soient empaquetés dans un conteneur. Cela offre une grande flexibilité pour le 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 avec les é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 avec la commande suivante:

  • $ gcloud services enable run.googleapis.com cloudbuild.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 d'options (que vous pouvez fournir via la ligne de commande ou que l'outil vous demandera via une invite interactive) 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 s'exécutera. (--region REGION)
  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 les utilisateurs non authentifiés) permet à tous les utilisateurs d'accéder à votre application sans authentification supplémentaire.

Consultez la documentation (ou faites défiler la page pour trouver une solution possible) pour savoir comment appliquer cette option à votre ligne de commande.

Le déploiement prendra 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" sans argument

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. Nous ne pouvons donc pas nous permettre de poser des questions interactives. Nous devons renseigner toutes les options de la commande. Vous souhaitez donc créer l'gcloud run deploy --option1 blah --foo bar --region your-fav-region dorée. 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. [LOOP] Les systèmes 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. Revenez à l'étape 2, sauf si gcloud se termine sans autre question.
  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.

Pour trouver une solution, cliquez ici. Pour en savoir plus, consultez la documentation.

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 le mot 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 en suivant une mauvaise pratique de sécurité: fournir des 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) doivent être lus de manière dynamique et fournis à 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. Si cela ne fonctionne pas, vous pouvez 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') ?: '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();
?>

É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 désormais déployer une nouvelle version 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 carte. Vous pouvez y remédier avec Google Cloud Secret Manager.

Deuxième itération: Secret Manager

Vos mots de passe ont disparu de votre propre code: mission accomplie ! Mais attendez, sommes-nous déjà en sécurité ?

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 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 "importer le fichier").
  • 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 de nommage cohérentes pour vos secrets, en les spécialisant de gauche à droite, par exemple: cloud-devrel-phpamarcord-dbpass

  • Organisation (avec l'entreprise)
  • Équipe (dans l'organisation)
  • Application (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 que nous avons mis en place un nouveau secret, nous devons supprimer 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 d'environnement 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 une solution. Pour résoudre ce problème, accédez à la section IAM et administration, puis modifiez les autorisations d'octroi. 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 encore et encore.

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 y parvenir ?

  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 l'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 "Je comprends…".
  • Si l'erreur suivante s'affiche : "L'application GitHub n'est installée dans aucun de vos dépôts", cliquez sur "Installer Google Cloud Build", puis suivez les instructions.
  • 23e0e0f1219afea3.pngCliquez sur "Se connecter".
  • bafd904ec07122d2.png
  • Bravo ! Votre dépôt est désormais associé.
  • Reprenons 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 modifiez pas les autres paramètres.
  • Cliquez sur le bouton "Créer".

(*) Il s'agit du moyen le plus simple, car il recherche Dockerfile ou 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 ? Adresse e-mail d'un "robot" qui effectue une tâche en votre nom (dans ce cas, la création d'éléments dans le cloud).

Votre SA ne pourra pas créer ni déployer l'application, sauf si vous lui en donnez l'autorisation. Heureusement, la procédure est simple.

  • Accédez à "Cloud Build" > Settings (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 "Définir comme compte de service préféré".

8715acca72286a46.png

Où se trouve le fichier YAML de 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 ne souhaitez pas vous y attarder, vous pouvez trouver de l'inspiration dans ce dossier de solutions: .solutions

Vous pouvez maintenant pousser une modification sur GitHub et observer Cloud Build à l'œuvre.

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'UI (compilation cloud > "Déclencheurs" > Exécuter).

97acd16980a144ab.png

Notez que si vous utilisez cette solution, vous devez encore effectuer quelques tâches. Par exemple, vous devez définir les variables ENV pour les points de terminaison de développement/production nouvellement créés:

3da8723e4ff80c0a.png

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

  • Via l'UI : 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 certains é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 vers 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. VSCode. 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 parmi les autres fichiers, sinon cela ne fonctionnera pas.

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

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

Toutefois, 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 signifie que vous devez disposer de deux bases de données (une pour le développement et une pour la production), et choisir où les placer pour la reprise après sinistre et 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, doublez vos 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

dc3a4b8ea92aaef6.png

Actuellement, l'application stocke l'état dans un conteneur Docker. Si la machine tombe en panne, si l'application explose ou si vous poussez une nouvelle révision, une nouvelle révision sera planifiée, avec un nouvel espace de stockage 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 + Storage ? Remarque: Vous gagnez en contrôle, mais vous perdez en agilité.
  3. Accédez à 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 compatible avec Composer ? (il semble que PHP 5.3.2 soit 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. C'est incroyable.

🤔 Migrer le stockage (question ouverte)

[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 dire la solution, mais je veux que vous fassiez ce qui suit:

  1. Vous importez newpic.jpg. Vous le voyez 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 le code DU TOUT (à l'exception de l'affichage d'une description d'image, mais c'est anodin et juste pour le plaisir des yeux).

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 effectuer la même opération à 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 tout fonctionne, vous devriez voir quelque chose comme ceci lorsque vous modifiez la nouvelle révision Cloud Run:

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 le libellé "dangereux" ou "nu" est reçue ? Vous pouvez le faire sans modifier le code PHP.
  • Vous souhaitez utiliser un modèle multimodal Gemini chaque fois qu'une image est reçue pour la décrire et importer la base de données avec sa description ? Vous pouvez le faire sans modifier le 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 et qui les transfère vers votre bucket.

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 propose plusieurs paradigmes pour y parvenir. Plus précisément:

Dans cet exercice, nous allons nous intéresser à Cloud Functions pour obtenir un résultat assez 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 GCF très ambitieux.

  1. Lorsqu'une image est créée sur GCS (probablement parce qu'un utilisateur l'a mis en ligne dans l'application, mais pas seulement)
  2. .. appeler Gemini pour le décrire et obtenir une description textuelle de l'image .. (il serait préférable de vérifier le MIME et de s'assurer qu'il s'agit d'une image et non d'un PDF, d'un MP3 ou d'un texte)
  3. .. et mettez à jour la base de données avec cette description. (vous devrez peut-être corriger la base de données pour ajouter une colonne description au tableau images).

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

  1. Ouvrez Cloud SQL Studio:

b92b07c4cba658ef.png

  1. Indiquez votre nom d'utilisateur et votre mot de passe pour la base de données 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 f(x) dans Gemini

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. Activez les API depuis l'assistant d'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. 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 fournir les valeurs appropriées aux ENV, 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 sera la méthode appelée, et la fonction Cloud transmettra l'événement GCS avec toutes les informations pertinentes (nom du bucket, nom de l'objet, etc.). Prenez le temps de déboguer ce dictionnaire Python d'événement.

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 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 volumineuses).
  3. Vérifiez dans l'UI que l'image est importée.
  4. Vérifiez dans Cloud SQL Studio que la description a été mise à jour. Connectez-vous et exécutez cette requête: SELECT * FROM images.

43a680b12dbbdda0.png

Et il est efficace ! Nous pouvons également mettre à jour le frontend pour afficher cette description.

Mettre à jour PHP pour afficher [facultatif]

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

Nous n'avons pas besoin d'être des experts 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; ?>

Positionnez ce code dans foreach à votre guise.

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

Une fonction Cloud est déclenchée lorsque de nouveaux objets arrivent sur GCS. Elle peut annoter le contenu de l'image comme le ferait un humain et 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 par 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". Pourquoi ne pas laisser Gemini s'occuper de la modération de l'espace ? Ajoutez un test pour signaler le contenu inapproprié du déclencheur et mettez à 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 différentes manières, 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 "Sortie structurée Gemini", 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 tels que "Y a-t-il quelque chose de positif à ce sujet ?". Vous n'êtes pas satisfait ? Reconnaissez-vous ce lieu ? La photo contient-elle du texte (l'OCR n'a jamais été aussi simple):

  • goods: "Il semble que ce soit de la nourriture délicieuse"
  • bads: "Cela ressemble à de la nourriture malsaine"
  • 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 pour la première fois, j'ai rencontré 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, ce qui prendra quelques minutes avant qu'elles ne soient entièrement disponibles.

Erreur: Demandeur Cloud Run manquant

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

be72e17294f2d3f3.png

Pour corriger cette erreur, exécutez la commande de l'image, qui 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. 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'UI. Voici un problème 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 la version 1 de GCF a généré une erreur:

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, accédez à 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 rencontrez ce problème, 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). Ils sont nécessaires pour lire le fichier Cloud Storage fourni. Veuillez donc réessayer dans quelques minutes.

Dans ce cas, patientez 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.

Quelle est la qualité d'une application si vous ne pouvez pas savoir quand 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: Configurez 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.

Répétez 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 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

Vous pouvez utiliser Gemini de deux manières différentes:

  1. Vertex AI La méthode "Enterprise", étroitement liée à 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 à essayer d'explorer (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/frontend créatives. Croyez-moi, vous n'aurez ensuite que des modifications très mineures à apporter.

Sécurité

La sécurisation appropriée de cette application n'est pas un objectif de cet atelier de quatre heures, car cela augmenterait la durée de l'atelier d'un à deux ordres de grandeur.

Cependant, ce sujet est très important. Nous avons rassemblé quelques idées dans SECURITY.

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 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 la faire fonctionner 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é.
  • Implémenter les principes SRE dans Google Cloud

C'est un excellent début pour votre parcours de 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.