EP 02 : Premiers pas avec App Engine
INTRODUCTION
Résumé de l’épisode précédent : Dans l’épisode 1, nous avons vu une présentation détaillée du service App Engine. Si vous ne l’avez pas encore lu, je vous conseille de commencer par là : "EP 01 : Et si on découvrait ensemble des outils GCP..."
Objectif de l’article : être capable de faire ses premiers pas dans App Engine.
À qui s’adresse le service App Engine ? Ce service est accessible à tout type de profil mais il s’adresse particulièrement aux développeurs et à ceux qui souhaitent se lancer dans l’aventure du Cloud sans connaissances approfondies en administration Systèmes et Réseaux.
Outil utilisé : je vais utiliser le CLI de Google pour faire toutes les opérations sur App Engine et non l'interface. Si vous voulez une présentation de l'interface par service, cela peut faire l'objet d'article, il suffit d’en faire la demande.
LAB
Pour ce lab, vous incarnerez un développeur avec une idée de génie et vous voulez vous lancer sans trop dépenser. Nous allons prendre un exemple de code : attention celui-ci est ultra complexe ;-) et voir comment le déployer sur App Engine afin de profiter de l'expertise de Google sur l'infrastructure, ce qui vous permet de rester concentré sur votre projet.
Déroulé du lab : Nous allons d’abord déployer une application Go qui, pour la version v1, mettra en ligne un joyeux "hello, world :)". Puis nous verrons comment faire le versioning de notre application afin de faciliter les montées de versions.
Plan du lab :
- I. Présentation du code.
- II. Comment déployer son code ?
- III. Comment faire une mise à jour ?
- IV. Pour aller plus loin…
I. Présentation du code
Voici le code révolutionnaire qui consiste à afficher le message "hello, World!" aux personnes qui visitent notre application.
Fichier hello.go
package main
import (
"fmt"
"log"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", indexHandler)
port := os.Getenv("PORT")
if port == "" {
port = "8080"
log.Printf("Defaulting to port %s", port)
}
log.Printf("Listening on port %s", port)
if err := http.ListenAndServe(":"+port, nil); err != nil {
log.Fatal(err)
}
}
func indexHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/" {
http.NotFound(w, r)
return
}
fmt.Fprint(w, "Hello, World!")
}
Nous plaçons ce code go dans un répertoire que nous appelons ici hello, comme ceci :
hello
├── app.yaml
└── hello.go
Je vois déjà votre surprise avec l'apparition d'un ficher dont nous n'avons pas encore parlé. Ne vous inquiétez pas, celui-ci sera présenté dans la partie suivante. Je vous invite à faire une modification du texte "Hello, World!" à chaque nouvelle version, afin de constater le changement lors des mises en production.
II. Comment déployer son code ?
Nous avons le code de notre application mais comment faire pour le déployer sur App Engine ? Tout n'est pas si magique que cela, nous devons, dans notre cas, fournir un fichier de configuration app.yaml à Google, qui va permettre à ce dernier de connaître l'environnement d'exécution dont nous avons besoin.
Ce fichier, qui est très simple ici, peut contenir plusieurs paramètres autres que le runtime comme :
- les variables d'environnement propres à l'application,
- la configuration des handlers (la gestion des urls pour faire simple),
- la gestion des services et du scaling.
Le fichier de configuration de l’application app.yaml :
runtime: go112
inbound_services:
- warmup
Ici nous spécifions que nous voulons un environnement d'exécution Go, et que nous activons les requêtes de préchauffage, ce qui permet d'améliorer les performances. Nous en aurons besoin pour la migration du trafic notamment.
Déployons notre application.
gcloud app deploy --version v1
Simple et efficace. L'option --version n'est pas obligatoire car Google va en choisir une pour nous, mais pour une raison de clarté, je vous conseille de mettre votre nommage de version dès l'initialisation de votre projet.
Une fois que le CLI nous rend la main, nous pouvons voir le résultat en utilisant :
- soit la commande gcloud app browse
- soit l'url https://PROJECT_ID.REGION_ID.r.appspot.com
Résultat :
gcloud app versions list
SERVICE VERSION.ID TRAFFIC_SPLIT LAST_DEPLOYED SERVING_STATUS
default v1 1.00 2020-05-04T16:14:07+02:00 SERVING
Et nous avons dans notre navigateur Hello, World!
III. Comment faire une mise à jour ?
1. Les deux modes de déploiement
Il existe plusieurs moyens de mettre en ligne les nouvelles versions de notre application :
- La première option, qui est la plus simple, est d'effectuer un déploiement.
- La seconde option est de déployer la nouvelle version sans la promouvoir.
L'option la plus simple est d'effectuer un déploiement. La nouvelle version de notre application sera mise en ligne et la totalité du trafic sera migrée vers cette version.
Simple, mais... Si jamais vous avez un bug, que se passe-t-il ? Tous vos clients sont impactés par celui-ci. Je ne vous conseille donc pas cette méthode, mais je vais quand même vous la présenter.
gcloud app deploy --version v2
Résultat :
gcloud app versions list
SERVICE VERSION.ID TRAFFIC_SPLIT LAST_DEPLOYED SERVING_STATUS
default v1 0.00 2020-05-04T16:14:07+02:00 SERVING
default v2 1.00 2020-05-04T16:18:31+02:00 SERVING
Nous le voyons bien ici avec la colonne TRAFFIC_SPLIT, celle-ci nous indique que la totalité du trafic est maintenant migrée vers la version v2. Et, dans mon cas, je me retrouve avec le message "Hello, AWCC!".
La seconde option est de déployer la nouvelle version sans la promouvoir. Pour faire cela, nous devons déployer notre application en disant à Google de ne surtout pas exposer notre application avec l'option --no-promote.
gcloud app deploy --no-promote --version v3
Résultat :
gcloud app versions list
SERVICE VERSION.ID TRAFFIC_SPLIT LAST_DEPLOYED SERVING_STATUS
default v1 0.00 2020-05-04T16:14:07+02:00 SERVING
default v2 1.00 2020-05-04T16:18:31+02:00 SERVING
default v3 0.00 2020-05-04T16:25:34+02:00 SERVING
Ici le trafic est toujours sur l'ancienne version avec mon message "Hello, AWCC!". Nous pouvons si nous le souhaitons tester la version non promue avec l'url suivante :
2. Redirection du trafic
Nous avons deux possibilités qui s'offrent maintenant à nous :
- la migration brutale du trafic
- la migration progressive du trafic.
Migration brutale du trafic :
gcloud app services set-traffic default --splits v1=1
Résultat :
gcloud app versions list
SERVICE VERSION.ID TRAFFIC_SPLIT LAST_DEPLOYED SERVING_STATUS
default v1 1.00 2020-05-04T16:14:07+02:00 SERVING
default v2 0.00 2020-05-04T16:18:31+02:00 SERVING
default v3 0.00 2020-05-04T16:25:34+02:00 SERVING
Votre migration a réussi, très bien ! Mais si vous avez un fort trafic lors de votre migration, vous constaterez de fortes latences car aucune machine n'était instanciée au moment du changement.
Migration progressive du trafic.
Deux solutions possibles pour la migration progressive du trafic :
- nous laissons Google faire la migration du trafic
- nous nous en chargeons.
gcloud app services set-traffic default --splits v2=1 --migrate
Avec l'option --migrate, Google va migrer progressivement le trafic sur la nouvelle version afin de lui permettre d'instancer suffisamment de ressources pour répondre à la charge.
Nous allons répartir un pourcentage du trafic sur la nouvelle version afin d'analyser son comportement pour la détection d'erreur, la latence, etc.
gcloud app services set-traffic default --splits v2=90,v3=10 --split-by random
L'option --split-by nous permet de choisir comment faire la migration du trafic. Nous avons la possibilité de choisir entre Ip, Cookie et Random.
Résultat :
gcloud app versions list
SERVICE VERSION.ID TRAFFIC_SPLIT LAST_DEPLOYED SERVING_STATUS
default v1 0.00 2020-05-04T16:14:07+02:00 SERVING
default v2 0.90 2020-05-04T16:18:31+02:00 SERVING
default v3 0.10 2020-05-04T16:25:34+02:00 SERVING
Si tout nous semble correct, nous allons progressivement migrer la totalité du trafic sur notre nouvelle version.
IV. Pour aller plus loin…
Vous allez me dire : "oui, dans la vraie vie, les apps ne font pas qu'un hello world !".
Il est évident que, pour passer sur ce service, nous allons devoir structurer notre application en micro-services et que, pour le stockage, nous allons utiliser des services managés de Google comme CloudSql, Memcache, FireStore, GCS...
Dans notre lab, nous avons déployé une application sur le service "default" qui est défini par notre fichier 'app.yaml'. Si nous avons besoin de plusieurs services pour créer une application plus complexe, cela est possible en créant des répertoires distincts pour chacun de nos services avec son code et son fichier de configuration (app.yaml).
Nous allons voir ci-dessous l'aspect que peut avoir une application avec deux services : un frontend et un backend.
app
├── back
│ ├── back.go
│ └── back.yaml
├── dispatch.yaml
└── front
├── front.go
└── front.yaml
Je pense que vous allez me dire "Oh, le fichier dispatch là, d'où sort-il ?". Eh oui, je n'en ai pas parlé avant car le fichier disptach.yaml est un fichier optionnel qui permet tout simplement d'appliquer des règles de routage sur les services.
CONCLUSION
J'espère que cet article vous sera utile et vous permettra de faire vos premiers pas avec le service App Engine. Il existe un panel d'outils pour App Engine qui permettent de créer des applications robustes. Mais, pour découvrir tous les outils, il faudra se montrer patient et attendre un autre épisode consacré à ce service. A très bientôt !
équipe alter way Cloud consulting
Découvrez les derniers articles d'alter way
- kubevpn
- Kubernetes 1.32
- re:Invent 2024 : AWS mise tout sur l'IA pour son Cloud
- OVHcloud Summit 2024 : L’innovation au cœur d’un cloud souverain et performant
- Big Data & AI Paris 2024 : L'IA au cœur de toutes les transformations.
- Un retour vers l'open-source ? Vos outils DevOps préférés et leurs equivalents open-source.