Migrer d'App Engine vers Cloud Storage (module 16)

1. Présentation

La série d'ateliers de programmation sur la station de migration sans serveur (tutoriels pratiques et d'auto-formation) et les vidéos associées visent à aider les développeurs sans serveur Google Cloud à moderniser leurs applications en les guidant dans une ou plusieurs migrations, principalement en abandonnant les anciens services. Vous améliorez ainsi la portabilité de vos applications, et vous bénéficiez de plus d'options et de flexibilité. Vous pouvez ainsi intégrer un plus large éventail de produits Cloud et y accéder, et passer plus facilement à de nouvelles langues. Bien qu'elle s'adresse initialement aux utilisateurs les plus anciens du cloud, principalement les développeurs d'environnements App Engine (standard), cette série est suffisamment large pour inclure d'autres plates-formes sans serveur telles que Cloud Functions et Cloud Run, ou ailleurs, le cas échéant.

Dans cet atelier de programmation, vous apprendrez à effectuer une migration du service Blobstore d'App Engine vers Cloud Storage. Il existe également des migrations implicites à partir de:

Pour obtenir des informations détaillées, reportez-vous aux modules de migration associés.

Vous apprendrez à

  • Ajouter l'utilisation de l'API/de la bibliothèque Blobstore d'App Engine
  • Stocker les importations des utilisateurs dans le service Blobstore
  • Préparez la prochaine étape de migration vers Cloud Storage

Prérequis

Enquête

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Quel est votre niveau d'expérience avec Python ?

Débutant Intermédiaire Expert

Quel est votre niveau d'expérience avec les services Google Cloud ?

<ph type="x-smartling-placeholder"></ph> Débutant Intermédiaire Expert
.

2. Contexte

Cet atelier de programmation commence par l'application exemple du module 15 et montre comment effectuer une migration de gsutil (et de la bibliothèque NDB) vers Cloud Storage (et Cloud NDB). Le processus de migration implique le remplacement des dépendances aux anciens services groupés d'App Engine, ce qui vous permet de déplacer vos applications vers une autre plate-forme cloud sans serveur ou une autre plate-forme d'hébergement, si vous le souhaitez.

Cette migration demande un peu plus d'efforts que les autres migrations de cette série. L'application exemple utilise l'environnement webapp2 plutôt que Flask, car elle possède des dépendances sur l'environnement logiciel webapp d'origine. Ce tutoriel présente les migrations vers Cloud Storage, Cloud NDB, Flask et Python 3.

L'application enregistre toujours les "visites" des utilisateurs finaux. et affiche les 10 dernières, mais l'atelier de programmation précédent (module 15) a ajouté une nouvelle fonctionnalité pour prendre en charge l'utilisation du paquet: l'application invite les utilisateurs finaux à télécharger un artefact (un fichier) correspondant à leur "visite". Les utilisateurs peuvent le faire ou sélectionner "Ignorer" pour refuser. Quelle que soit la décision de l'utilisateur, la page suivante affiche le même résultat que les incarnations précédentes de cette application, en affichant les visites les plus récentes. Autre nouveauté : les visites accompagnées d'artefacts affichent une "vue" lien permettant d'afficher l'artefact d'une visite. Cet atelier de programmation implémente les migrations mentionnées précédemment tout en conservant les fonctionnalités décrites.

3. Configuration/Préparation

Avant de passer à la partie principale du tutoriel, nous allons configurer notre projet, récupérer le code, puis déployer l'application de base pour savoir si nous avons commencé avec du code fonctionnel.

1. Configurer le projet

Si vous avez déjà déployé l'application du module 15, nous vous recommandons de réutiliser ce projet (et ce même code). Vous pouvez également créer un projet ou réutiliser un autre projet existant. Assurez-vous que le projet dispose d'un compte de facturation actif et qu'App Engine est activé.

2. Obtenir un exemple d'application de référence

L'une des conditions préalables à cet atelier de programmation est de disposer d'une application exemple fonctionnelle du module 15. Si vous ne l'avez pas, vous pouvez l'obtenir à partir du module 15, intitulé "DÉMARRER". (lien ci-dessous). Cet atelier de programmation présente chaque étape, se terminant par un code semblable à celui du module 16 "FINISH" .

Le répertoire des fichiers de démarrage du module 15 devrait ressembler à ceci:

$ ls
README.md       app.yaml        main-gcs.py     main.py         templates

Le fichier main-gcs.py est une version alternative de main.py du module 15 qui permet de sélectionner un bucket Cloud Storage différent de l'URL par défaut attribuée à une application en fonction de l'ID du projet: PROJECT_ID.appspot.com. Ce fichier ne joue aucun rôle dans cet atelier de programmation (module 16), sauf que des techniques de migration similaires peuvent être appliquées à ce fichier, si vous le souhaitez.

3. (Re)Déployer l'application de référence

Étapes préliminaires restantes :

  1. Familiarisez-vous avec l'outil de ligne de commande gcloud
  2. Redéployez l'exemple d'application avec gcloud app deploy
  3. Vérifier que l'application s'exécute sans problème sur App Engine

Une fois que vous avez exécuté ces étapes et vérifié que votre application du module 15 fonctionne. La page initiale accueille les utilisateurs avec un formulaire leur demandant d'importer un fichier d'artefact de visite à importer et une option "ignorer" , pour désactiver cette fonctionnalité:

f5b5f9f19d8ae978.png

Lorsque les utilisateurs importent un fichier ou l'ignorent, l'application affiche les "visites les plus récentes". :

f5ac6b98ee8a34cb.png

Les visites présentant un artefact auront une "vue" à droite de l'horodatage de la visite pour afficher (ou télécharger) l'artefact. Une fois que vous avez vérifié le fonctionnement de l'application, vous êtes prêt à migrer des anciens services App Engine (webapp2, NDK, Blobstore) vers des alternatives contemporaines (Flask, Cloud NDB, Cloud Storage).

4. Mettre à jour les fichiers de configuration

Trois fichiers de configuration entrent en jeu pour la version mise à jour de notre application. Les tâches requises sont les suivantes:

  1. Mettre à jour les bibliothèques tierces requises dans app.yaml et laisser la porte ouverte à une migration Python 3
  2. Ajoutez un requirements.txt qui spécifie toutes les bibliothèques requises qui ne sont pas intégrées.
  3. Ajout de appengine_config.py pour que l'application soit compatible avec les bibliothèques tierces intégrées et non intégrées.

app.yaml

Modifiez votre fichier app.yaml en mettant à jour la section libraries. Supprimez jinja2, puis ajoutez grpcio, setuptools et ssl. Choisissez la dernière version disponible pour les trois bibliothèques. Ajoutez également la directive Python 3 runtime, mais en ajoutant un commentaire. Lorsque vous avez terminé, l'application doit se présenter comme suit (si vous avez sélectionné Python 3.9):

AVANT:

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: jinja2
  version: latest

APRÈS:

#runtime: python39
runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest
- name: ssl
  version: latest

Ces modifications concernent principalement les bibliothèques intégrées Python 2 disponibles sur les serveurs App Engine (vous n'avez donc pas besoin de les regrouper). Nous avons supprimé Jinja2, car il est fourni avec Flask, que nous allons ajouter au fichier reqs.txt. Chaque fois que des bibliothèques clientes Google Cloud, telles que celles pour Cloud NDB et Cloud Storage, sont utilisées, grpcio et setuptools sont nécessaires. Enfin, Cloud Storage lui-même nécessite la bibliothèque SSL. La directive d'exécution commentée en haut de l'écran est utile lorsque vous êtes prêt à transférer cette application vers Python 3. Nous aborderons ce sujet à la fin de ce tutoriel.

requirements.txt

Ajoutez un fichier requirements.txt nécessitant le framework Flask, ainsi que les bibliothèques clientes Cloud NDB et Cloud Storage, qui ne sont pas intégrées. Créez le fichier avec le contenu suivant:

flask
google-cloud-ndb
google-cloud-storage

L'environnement d'exécution Python 2 App Engine nécessite l'auto-intégration de bibliothèques tierces non intégrées. Vous devez donc exécuter la commande suivante pour installer ces bibliothèques dans le dossier "lib" :

pip install -t lib -r requirements.txt

Si Python 2 et 3 sont installés sur votre ordinateur de développement, vous devrez peut-être exécuter la commande pip2 pour vous assurer d'obtenir les versions Python 2 de ces bibliothèques. Une fois que vous êtes passé à Python 3, vous n'avez plus besoin de procéder à l'auto-intégration.

appengine_config.py

Ajoutez un fichier appengine_config.py compatible avec les bibliothèques tierces intégrées et non intégrées. Créez le fichier avec le contenu suivant:

import pkg_resources
from google.appengine.ext import vendor

# Set PATH to your libraries folder.
PATH = 'lib'
# Add libraries installed in the PATH folder.
vendor.add(PATH)
# Add libraries to pkg_resources working set to find the distribution.
pkg_resources.working_set.add_entry(PATH)

Les étapes que vous venez d'effectuer doivent être semblables ou identiques à celles indiquées dans la section Installer des bibliothèques pour les applications Python 2 de la documentation App Engine. Plus précisément, le contenu de appengine_config.py doit correspondre à celui de l'étape 5.

Le travail sur les fichiers de configuration étant terminé, passons à l'application.

5. Modifier les fichiers d'application

Importations

Le premier ensemble de modifications pour main.py consiste à remplacer tous les éléments. Voici ce qui va changer:

  1. webapp2 est remplacé par Flask
  2. Au lieu d'utiliser Jinja2 depuis webapp2_extras, utilisez le Jinja2 fourni avec Flask.
  3. Remplacement des API Blobstore et de service par niveau d'App Engine par Cloud NDB et Cloud Storage
  4. Les gestionnaires Blobstore de webapp sont remplacés par une combinaison des utilitaires du module de bibliothèque standard io, de Flask et des utilitaires werkzeug.
  5. Par défaut, Blobstore écrit dans un bucket Cloud Storage nommé d'après l'URL de votre application (PROJECT_ID.appspot.com). Comme nous effectuons le portage vers la bibliothèque cliente Cloud Storage, google.auth est utilisé pour obtenir l'ID de projet afin de spécifier exactement le même nom de bucket. (Vous pouvez modifier le nom du bucket, car il n'est plus codé en dur.)

AVANT:

import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers

Implémentez les modifications de la liste ci-dessus en remplaçant la section d'importation actuelle dans main.py par l'extrait de code ci-dessous.

APRÈS:

import io

from flask import (Flask, abort, redirect, render_template,
        request, send_file, url_for)
from werkzeug.utils import secure_filename

import google.auth
from google.cloud import exceptions, ndb, storage

Initialisation et prise en charge inutile de Jinja2

Le bloc de code suivant à remplacer est le BaseHandler, qui spécifie l'utilisation de Jinja2 à partir de webapp2_extras. Cette opération n'est pas nécessaire, car Jinja2 est fourni avec Flask et est son moteur de création de modèles par défaut. Supprimez-le.

Du côté du module 16, instanciez les objets dont nous n'avions pas dans l'ancienne application. Cela inclut l'initialisation de l'application Flask et la création de clients API pour Cloud NDB et Cloud Storage. Enfin, nous avons rassemblé le nom du bucket Cloud Storage, comme décrit ci-dessus dans la section des importations. Voici ce qui se passe avant et après la mise en œuvre de ces mises à jour:

AVANT:

class BaseHandler(webapp2.RequestHandler):
    'Derived request handler mixing-in Jinja2 support'
    @webapp2.cached_property
    def jinja2(self):
        return jinja2.get_jinja2(app=self.app)

    def render_response(self, _template, **context):
        self.response.write(self.jinja2.render_template(_template, **context))

APRÈS:

app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID

Mettre à jour l'accès à Datastore

Cloud NDB est principalement compatible avec App Engine NDB. Une différence déjà abordée est la nécessité d'un client API. Dans le second cas, l'accès à Datastore doit être contrôlé par le gestionnaire de contexte Python du client API. En résumé, cela signifie que tous les appels d'accès Datastore utilisant la bibliothèque cliente Cloud NDB ne peuvent avoir lieu que dans des blocs Python with.

C'est un changement : L'autre est que le StatefulSet et ses objets (par exemple, Les BlobKey ne sont pas compatibles avec Cloud Storage. Vous devez donc remplacer file_blob par ndb.StringProperty. Vous trouverez ci-dessous la classe du modèle de données, ainsi que les fonctions store_visit() et fetch_visits() mises à jour qui reflètent ces modifications:

AVANT:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent),
            file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

APRÈS:

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.StringProperty()

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

Voici une illustration des modifications apportées jusqu'à présent:

a8f74ca392275822.png

Mettre à jour les gestionnaires

Gestionnaire d'importation

Les gestionnaires dans webapp2 sont des classes alors qu'il s'agit de fonctions dans Flask. Au lieu d'une méthode de verbe HTTP, Flask utilise le verbe pour décorer la fonction. Les fonctionnalités de Cloud Storage ainsi que de Flask et de ses utilitaires ont été remplacées par des fonctionnalités de Cloud Storage et de ses gestionnaires webapp:

AVANT:

class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    'Upload blob (POST) handler'
    def post(self):
        uploads = self.get_uploads()
        blob_id = uploads[0].key() if uploads else None
        store_visit(self.request.remote_addr, self.request.user_agent, blob_id)
        self.redirect('/', code=307)

APRÈS:

@app.route('/upload', methods=['POST'])
def upload():
    'Upload blob (POST) handler'
    fname = None
    upload = request.files.get('file', None)
    if upload:
        fname = secure_filename(upload.filename)
        blob = gcs_client.bucket(BUCKET).blob(fname)
        blob.upload_from_file(upload, content_type=upload.content_type)
    store_visit(request.remote_addr, request.user_agent, fname)
    return redirect(url_for('root'), code=307)

Remarques concernant cette mise à jour:

  • Plutôt que blob_id, les artefacts des fichiers sont désormais identifiés par le nom de fichier (fname) s'il est présent et par None dans le cas contraire (l'utilisateur a désactivé l'importation d'un fichier).
  • En revanche, ce n'est pas le cas de Cloud Storage, qui a fait abstraction du processus d'importation des utilisateurs par les gestionnaires Blobstore. Vous pouvez donc voir le code qui vient d'être ajouté qui définit l'objet blob et l'emplacement (bucket) du fichier, ainsi que l'appel qui effectue l'importation proprement dite. (upload_from_file()).
  • webapp2 utilise une table de routage en bas du fichier de l'application, tandis que les routes Flask sont trouvées dans chaque gestionnaire décoré.
  • Les deux gestionnaires résument leur fonctionnalité en redirigeant vers la page d'accueil ( /) tout en conservant la requête POST avec un code de retour HTTP 307.

Gestionnaire de téléchargement

La mise à jour du gestionnaire de téléchargement suit un schéma semblable à celui du gestionnaire d'importation, mais il y a beaucoup moins de code à examiner. Remplacez les fonctionnalités Blobstore et webapp par les équivalents Cloud Storage et Flask:

AVANT:

class ViewBlobHandler(blobstore_handlers.BlobstoreDownloadHandler):
    'view uploaded blob (GET) handler'
    def get(self, blob_key):
        self.send_blob(blob_key) if blobstore.get(blob_key) else self.error(404)

APRÈS:

@app.route('/view/<path:fname>')
def view(fname):
    'view uploaded blob (GET) handler'
    blob = gcs_client.bucket(BUCKET).blob(fname)
    try:
        media = blob.download_as_bytes()
    except exceptions.NotFound:
        abort(404)
    return send_file(io.BytesIO(media), mimetype=blob.content_type)

Remarques sur cette mise à jour:

  • Là encore, Flask décore les fonctions du gestionnaire avec sa route, tandis que webapp le fait dans une table de routage en bas. Vous devez donc reconnaître la syntaxe de correspondance de modèle ('/view/([^/]+)?') de Flask ('/view/<path:fname>').
  • Comme pour le gestionnaire d'importation, Cloud Storage demande un peu plus de travail pour permettre l'abstraction des fonctionnalités par les gestionnaires Blobstore, à savoir identifier le fichier (blob) en question et télécharger explicitement le binaire par rapport à l'appel de méthode send_blob() unique du gestionnaire Blobstore.
  • Dans les deux cas, une erreur HTTP 404 est renvoyée à l'utilisateur si aucun artefact n'est trouvé.

Gestionnaire principal

Les dernières modifications apportées à l'application principale sont effectuées dans le gestionnaire principal. Les méthodes de verbes HTTP webapp2 sont remplacées par une seule fonction combinant leurs fonctionnalités. Remplacez la classe MainHandler par la fonction root() et supprimez la table de routage webapp2, comme indiqué ci-dessous:

AVANT:

class MainHandler(BaseHandler):
    'main application (GET/POST) handler'
    def get(self):
        self.render_response('index.html',
                upload_url=blobstore.create_upload_url('/upload'))

    def post(self):
        visits = fetch_visits(10)
        self.render_response('index.html', visits=visits)

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/upload', UploadHandler),
    ('/view/([^/]+)?', ViewBlobHandler),
], debug=True)

APRÈS:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

Plutôt que de séparer les méthodes get() et post(), il s'agit essentiellement d'une instruction if-else dans root(). De plus, comme root() est une fonction unique, il n'y a qu'un seul appel pour afficher le modèle à la fois pour GET et POST, ce qui n'est pas vraiment possible dans webapp2.

Voici une illustration de ce deuxième et dernier ensemble de modifications apportées à main.py:

5ec38818c32fec2.png

(Facultatif) Rétrocompatibilité "Amélioration"

La solution créée ci-dessus fonctionne donc parfaitement... mais seulement si vous partez de zéro et que vous n'avez pas de fichiers créés par Blobstore. Étant donné que nous avons mis à jour l'application pour identifier les fichiers par nom de fichier au lieu de BlobKey, l'application du module 16 terminée ne pourra pas afficher les fichiers Blobstore. En d'autres termes, nous avons effectué cette migration avec une modification incompatible avec les versions antérieures. Nous présentons maintenant une autre version de main.py appelée main-migrate.py (disponible dans le dépôt) qui tente de combler cet écart.

La première "extension" pour prendre en charge les fichiers créés par Blobstore est un modèle de données doté d'un BlobKeyProperty (en plus d'un StringProperty pour les fichiers créés par Cloud Storage):

class Visit(ndb.Model):
    'Visit entity registers visitor IP address & timestamp'
    visitor   = ndb.StringProperty()
    timestamp = ndb.DateTimeProperty(auto_now_add=True)
    file_blob = ndb.BlobKeyProperty()  # backwards-compatibility
    file_gcs  = ndb.StringProperty()

La propriété file_blob permet d'identifier les fichiers créés par le StatefulSet, tandis que file_gcs concerne les fichiers Cloud Storage. Désormais, lorsque vous créez des visites, stockez explicitement une valeur dans file_gcs au lieu de file_blob. La valeur "store_visit" [visite du magasin] est donc un peu différente:

AVANT:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_blob=upload_key).put()

APRÈS:

def store_visit(remote_addr, user_agent, upload_key):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent),
                file_gcs=upload_key).put()

Lors de la récupération des visites les plus récentes, sélectionnez "normaliser". avant de les envoyer au modèle:

AVANT:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = fetch_visits(10)
    return render_template('index.html', **context)

APRÈS:

@app.route('/', methods=['GET', 'POST'])
def root():
    'main application (GET/POST) handler'
    context = {}
    if request.method == 'GET':
        context['upload_url'] = url_for('upload')
    else:
        context['visits'] = etl_visits(fetch_visits(10))
    return render_template('index.html', **context)

Vérifiez ensuite l'existence de file_blob ou file_gcs (ou aucune). Si un fichier est disponible, choisissez-en un qui existe et utilisez cet identifiant (BlobKey pour les fichiers créés par le paquet ou nom de fichier pour les fichiers créés par Cloud Storage). Lorsque nous parlons de « fichiers créés dans Cloud Storage », nous faisons référence aux fichiers créés à l'aide de la bibliothèque cliente Cloud Storage. Le service écrit également dans Cloud Storage, mais dans le cas présent, il s'agirait de fichiers créés par le service.

Plus important encore, quelle est la fonction etl_visits() permettant de normaliser les données de l'utilisateur final ou de les extraire (extraire, transformer et charger) en mode ETL ? Elle se présente comme suit :

def etl_visits(visits):
    return [{
            'visitor': v.visitor,
            'timestamp': v.timestamp,
            'file_blob': v.file_gcs if hasattr(v, 'file_gcs') \
                    and v.file_gcs else v.file_blob
            } for v in visits]

Cela ressemble probablement à ce à quoi vous vous attendiez: le code passe en boucle sur toutes les visites et, pour chaque visite, prend mot à mot les données concernant le visiteur et l'horodatage, puis vérifie si file_gcs ou file_blob existent. Si c'est le cas, il sélectionne l'une d'entre elles (ou None s'il n'en existe aucune).

Voici une illustration des différences entre main.py et main-migrate.py:

718b05b2adadb2e1.png

Si vous partez de zéro sans les fichiers créés par Blobstore, utilisez main.py. Toutefois, si vous effectuez une transition et souhaitez prendre en charge des fichiers créés à la fois par Blobstore et Cloud Storage, consultez main-migrate.py pour voir un exemple de scénario qui vous aidera à planifier les migrations de vos propres applications. Lors de migrations complexes, des cas particuliers sont susceptibles de se produire. Cet exemple montre donc une plus grande affinité pour la modernisation d'applications réelles avec des données réelles.

6. Résumé/Nettoyage

Cette section conclut cet atelier de programmation en déployant l'application, en vérifiant qu'elle fonctionne comme prévu et dans tout résultat réfléchi. Après la validation de l'application, effectuez toutes les étapes de nettoyage et réfléchissez aux prochaines étapes.

Déployer et vérifier l'application

Avant de redéployer votre application, veillez à exécuter pip install -t lib -r requirements.txt pour obtenir ces bibliothèques tierces auto-intégrées dans le dossier lib. Si vous souhaitez exécuter la solution rétrocompatible, renommez d'abord main-migrate.py en tant que main.py. Exécutez maintenant gcloud app deploy et vérifiez que l'application fonctionne de la même manière que l'application du module 15. L'écran du formulaire se présente comme suit:

f5b5f9f19d8ae978.png

La page des visites les plus récentes se présente comme suit:

f5ac6b98ee8a34cb.png

Félicitations ! Vous avez terminé cet atelier de programmation qui a remplacé le service PVC d'App Engine par Cloud Storage, App Engine NDB par Cloud NDB et webapp2 par Flask. Votre code devrait maintenant correspondre à ce qui se trouve dans le dossier FINISH (Module 16). Le fichier main-migrate.py alternatif est également présent dans ce dossier.

"Migration" Python 3

La directive Python 3 runtime mise en commentaire en haut de app.yaml suffit pour porter cette application vers Python 3. Le code source lui-même est déjà compatible avec Python 3. Aucune modification n'est donc nécessaire. Pour déployer cela en tant qu'application Python 3, procédez comme suit:

  1. Annulez la mise en commentaire de la directive Python 3 runtime en haut de app.yaml.
  2. Supprimez toutes les autres lignes de app.yaml.
  3. Supprimez le fichier appengine_config.py. (non utilisé dans l'environnement d'exécution Python 3)
  4. Supprimez le dossier lib s'il existe. (inutile avec l'environnement d'exécution Python 3)

Effectuer un nettoyage

Général

Si vous avez terminé, nous vous recommandons de désactiver votre application App Engine afin d'éviter que des frais ne vous soient facturés. Toutefois, si vous souhaitez effectuer d'autres tests, la plate-forme App Engine dispose d'un quota sans frais. Tant que vous ne dépassez pas ce niveau d'utilisation, aucuns frais ne vous seront facturés. Cela concerne le calcul, mais des frais peuvent également s'appliquer pour les services App Engine concernés. Pour en savoir plus, consultez sa page des tarifs. Si cette migration implique d'autres services cloud, ceux-ci sont facturés séparément. Dans les deux cas, le cas échéant, consultez la section "Informations spécifiques à cet atelier de programmation" ci-dessous.

Afin d'informer l'ensemble des utilisateurs, le déploiement sur une plate-forme de calcul sans serveur Google Cloud comme App Engine entraîne des coûts minimes de compilation et de stockage. Cloud Build et Cloud Storage disposent de leur propre quota sans frais. Le stockage de cette image utilise une partie de ce quota. Cependant, vous pouvez résider dans une région qui n'offre pas ce type de version sans frais. Vous devez donc surveiller l'utilisation de votre espace de stockage afin de réduire les coûts potentiels. "Dossiers" Cloud Storage spécifiques vous devez examiner:

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • Les liens de stockage ci-dessus dépendent de votre PROJECT_ID et de votre *LOC*ation (par exemple, "us") si votre application est hébergée aux États-Unis.

En revanche, si vous ne comptez pas utiliser cette application ou d'autres ateliers de programmation liés à la migration, et que vous souhaitez tout supprimer complètement, arrêtez votre projet.

Spécifique à cet atelier de programmation

Les services listés ci-dessous sont propres à cet atelier de programmation. Pour en savoir plus, consultez la documentation de chaque produit:

Notez que si vous êtes passé du module 15 au module 16, vous disposerez toujours de données dans le StatefulSet, c'est pourquoi nous incluons ses informations tarifaires ci-dessus.

Étapes suivantes

Au-delà de ce tutoriel, d'autres modules de migration à envisager concernant l'abandon des anciens services groupés sont les suivants:

  • Module 2: Migrer de l'environnement ndb App Engine vers Cloud NDB
  • Modules 7 à 9: migration des tâches d'envoi de la file d'attente des tâches App Engine vers Cloud Tasks
  • Modules 12 à 13: Migrer de Memcache d'App Engine vers Cloud Memorystore
  • Modules 18 à 19: Migrer de la file d'attente de tâches App Engine (tâches d'extraction) vers Cloud Pub/Sub

App Engine n'est plus la seule plate-forme sans serveur de Google Cloud. Si vous disposez d'une petite application App Engine ou d'une application aux fonctionnalités limitées et que vous souhaitez la transformer en microservice autonome, ou si vous voulez diviser une application monolithique en plusieurs composants réutilisables, nous vous recommandons de passer à Cloud Functions. Si la conteneurisation fait désormais partie de votre workflow de développement d'applications, en particulier si elle consiste en un pipeline CI/CD (intégration continue/livraison continue ou déploiement), envisagez de migrer vers Cloud Run. Ces scénarios sont abordés dans les modules suivants:

  • Effectuer une migration d'App Engine vers Cloud Functions: consultez le Module 11
  • Effectuer une migration d'App Engine vers Cloud Run: consultez le module 4 pour conteneuriser votre application avec Docker, ou le module 5 pour effectuer cette opération sans conteneur, ni connaissance de Docker ou Dockerfile.

Le passage à une autre plate-forme sans serveur est facultatif. Nous vous recommandons de réfléchir aux meilleures options pour vos applications et cas d'utilisation avant d'apporter des modifications.

Quel que soit le module de migration que vous envisagez ensuite, tout le contenu de la station de migration sans serveur (ateliers de programmation, vidéos, code source [si disponible]) est accessible dans son dépôt Open Source. Le fichier README du dépôt fournit également des indications sur les migrations à prendre en compte et sur l'ordre d'exécution approprié. des modules de migration.

7. Ressources supplémentaires

Commentaires et problèmes concernant les ateliers de programmation

Si vous rencontrez des problèmes avec cet atelier de programmation, commencez par faire une recherche avant de les signaler. Liens vers la recherche et la création d'un signalement :

Ressources de migration

Le tableau ci-dessous contient des liens vers les dossiers de dépôt des modules 15 (START) et 16 (FINISH). Vous pouvez également y accéder à partir du dépôt de toutes les migrations de l'atelier de programmation App Engine que vous pouvez cloner ou télécharger sous forme de fichier ZIP.

Atelier de programmation

Python 2

Python 3

Module 15

code

N/A

Module 16 (cet atelier de programmation)

code

(comme Python 2)

Ressources en ligne

Vous trouverez ci-dessous des ressources en ligne qui peuvent vous être utiles pour ce tutoriel:

Service App Engine et Cloud Storage

Plate-forme App Engine

Autres informations sur le cloud

Python

Vidéos

Licence

Ce document est publié sous une licence Creative Commons Attribution 2.0 Generic.