1. Descripción general
La serie de codelabs de Serverless Migration Station (instructivos prácticos de autoaprendizaje) y los videos relacionados tienen como objetivo ayudar a los desarrolladores de Google Cloud sin servidores a modernizar sus aplicaciones guiándolos a través de una o más migraciones, principalmente para dejar de usar servicios heredados. De esta manera, tus apps serán más portátiles y tendrás más opciones y flexibilidad, lo que te permitirá integrarte a una gama más amplia de productos de Cloud y acceder a ellos, además de actualizar con mayor facilidad a versiones de lenguaje más recientes. Si bien inicialmente se enfoca en los primeros usuarios de Cloud, principalmente desarrolladores de App Engine (entorno estándar), esta serie es lo suficientemente amplia como para incluir otras plataformas sin servidores, como Cloud Functions y Cloud Run, o en otros lugares, si corresponde.
En este codelab, aprenderás a migrar de Blobstore de App Engine a Cloud Storage. También hay migraciones implícitas de los siguientes tipos:
- Framework web
webapp2a Flask (se aborda en el Módulo 1) - NDB de App Engine a Cloud NDB para acceder a Datastore (se explica en el módulo 2)
- De Python 2 a 3 (la app migrada es compatible con Python 2 y 3)
Consulta los módulos de migración relacionados para obtener más información paso a paso.
En un próximo lab,
- Agrega el uso de la API o biblioteca de Blobstore de App Engine
- Almacena los archivos que suben los usuarios al servicio de Blobstore
- Prepárate para el siguiente paso de la migración a Cloud Storage
Requisitos
- Un proyecto de Google Cloud Platform con una cuenta de facturación de GCP activa
- Habilidades básicas de Python
- Conocimiento práctico de los comandos comunes de Linux
- Conocimientos básicos sobre el desarrollo y la implementación de apps de App Engine
- Una app de App Engine del módulo 15 en funcionamiento: completa el codelab del módulo 15 (recomendado) o copia la app del módulo 15 del repositorio
Encuesta
¿Cómo usarás este instructivo?
¿Cómo calificarías tu experiencia en Python?
¿Cómo calificarías tu experiencia en el uso de los servicios de Google Cloud?
2. Fondo
Este codelab comienza con la app de ejemplo del módulo 15 y muestra cómo migrar de Blobstore (y NDB) a Cloud Storage (y Cloud NDB). El proceso de migración implica reemplazar las dependencias de los servicios agrupados heredados de App Engine, lo que te permite mover tus apps a otra plataforma sin servidores de Cloud o a otra plataforma de hosting si lo deseas.
Esta migración requiere un poco más de esfuerzo en comparación con las otras migraciones de esta serie. Blobstore tiene dependencias en el marco de trabajo de aplicaciones web original, y es por eso que la app de ejemplo usa el framework webapp2 en lugar de Flask. En este instructivo, se presentan migraciones a Cloud Storage, Cloud NDB, Flask y Python 3.
La app aún registra las "visitas" de los usuarios finales y muestra las diez más recientes, pero el codelab anterior (módulo 15) agregó una nueva funcionalidad para adaptarse al uso de Blobstore: la app solicita a los usuarios finales que suban un artefacto (un archivo) correspondiente a su "visita". Los usuarios pueden hacerlo o seleccionar "omitir" para no participar. Independientemente de la decisión del usuario, la página siguiente renderiza el mismo resultado que las versiones anteriores de esta app, en el que se muestran las visitas más recientes. Un giro adicional es que las visitas con artefactos correspondientes incluyen un vínculo de "vista" para mostrar el artefacto de una visita. En este codelab, se implementan las migraciones mencionadas antes, a la vez que se conserva la funcionalidad descrita.
3. Configurar/trabajo previo
Antes de pasar a la parte principal del instructivo, configuremos nuestro proyecto, obtengamos el código y, luego, implementemos la app de referencia para asegurarnos de que comenzamos con un código que funciona.
1. Configura el proyecto
Si ya implementaste la app del módulo 15, te recomendamos que vuelvas a usar el mismo proyecto (y código). Como alternativa, puedes crear un proyecto nuevo o reutilizar otro existente. Asegúrate de que el proyecto tenga una cuenta de facturación activa y de que App Engine esté habilitado.
2. Obtén app de ejemplo del modelo de referencia
Uno de los requisitos previos de este codelab es tener una app de ejemplo del módulo 15 que funcione. Si no la tienes, puedes obtenerla de la carpeta "START" del módulo 15 (vínculo a continuación). En este codelab, se te guiará por cada paso y se concluirá con un código similar al que se encuentra en la carpeta "FINISH" del módulo 16.
- START: Carpeta del módulo 15 (Python 2)
- FINALIZACIÓN: Carpeta del módulo 16 (Python 2)
- Repositorio completo (para clonar o descargar el archivo ZIP)
El directorio de archivos START del módulo 15 debería verse de la siguiente manera:
$ ls README.md app.yaml main-gcs.py main.py templates
El archivo main-gcs.py es una versión alternativa de main.py del módulo 15 que permite seleccionar un bucket de Cloud Storage diferente de la URL predeterminada asignada a una app según el ID del proyecto: PROJECT_ID.appspot.com. Este archivo no tiene ninguna función en este codelab (módulo 16), excepto que se pueden aplicar técnicas de migración similares a ese archivo si se desea.
3. (vuelve a) implementa la aplicación de modelo de referencia
Los pasos del trabajo previo restantes para ejecutar ahora sin estos:
- Familiarízate con la herramienta de línea de comandos de
gcloud - Vuelve a implementar la app de muestra con
gcloud app deploy - Confirma que la app se ejecuta en App Engine sin problemas
Una vez que hayas ejecutado esos pasos correctamente y confirmes que tu app del módulo 15 funciona, En la página inicial, se muestra un formulario en el que se solicita un archivo de artefacto de visita para subir, junto con una opción, un botón "Omitir", para inhabilitar la carga:

Una vez que los usuarios suben un archivo o lo omiten, la app renderiza la página conocida "Visitas más recientes":

Las visitas que incluyan un artefacto tendrán un vínculo "ver" a la derecha de la marca de tiempo de la visita para mostrar (o descargar) el artefacto. Una vez que confirmes la funcionalidad de la app, podrás migrar de los servicios heredados de App Engine (webapp2, NDB y Blobstore) a alternativas contemporáneas (Flask, Cloud NDB y Cloud Storage).
4. Actualiza archivos de configuración
Para la versión actualizada de nuestra app, se usan tres archivos de configuración. Las tareas requeridas son las siguientes:
- Actualizar las bibliotecas de terceros integradas requeridas en
app.yamly dejar la puerta abierta para una migración a Python 3 - Agrega un
requirements.txt, que especifica todas las bibliotecas requeridas que no están integradas. - Agrega
appengine_config.pypara que la app admita bibliotecas de terceros integradas y no integradas.
app.yaml
Edita el archivo app.yaml actualizando la sección libraries. Quita jinja2 y agrega grpcio, setuptools y ssl. Elige la versión más reciente disponible para las tres bibliotecas. También agrega la directiva runtime de Python 3, pero marcada como comentario. Cuando termines, debería verse de la siguiente manera (si seleccionaste Python 3.9):
ANTES:
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: jinja2
version: latest
DESPUÉ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
Los cambios se relacionan principalmente con las bibliotecas integradas de Python 2 disponibles en los servidores de App Engine (para que no tengas que empaquetarlas por tu cuenta). Quitamos Jinja2 porque viene con Flask, que agregaremos a reqs.txt. Siempre que se usen las bibliotecas cliente de Google Cloud, como las de Cloud NDB y Cloud Storage, se necesitarán grpcio y setuptools. Por último, Cloud Storage requiere la biblioteca ssl. La directiva de entorno de ejecución marcada como comentario en la parte superior es para cuando tengas todo listo para portar esta app a Python 3. Abordaremos este tema al final de este instructivo.
requirements.txt
Agrega un archivo requirements.txt, que requiere el framework de Flask y las bibliotecas cliente de Cloud NDB y Cloud Storage, ninguna de las cuales está integrada. Crea el archivo con este contenido:
flask
google-cloud-ndb
google-cloud-storage
El entorno de ejecución de App Engine para Python 2 requiere el autoempaquetado de bibliotecas de terceros no integradas, por lo que debes ejecutar el siguiente comando para instalar estas bibliotecas en la carpeta lib:
pip install -t lib -r requirements.txt
Si tienes Python 2 y 3 en tu máquina de desarrollo, es posible que debas usar el comando pip2 para asegurarte de obtener las versiones de Python 2 de estas bibliotecas. Una vez que actualices a Python 3, ya no necesitarás empaquetar por tu cuenta.
appengine_config.py
Agrega un archivo appengine_config.py que admita bibliotecas de terceros integradas y no integradas. Crea el archivo con este contenido:
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)
Los pasos que acabas de completar deben ser similares o idénticos a los que se indican en la sección Instala bibliotecas para apps de Python 2 de la documentación de App Engine y, más específicamente, el contenido de appengine_config.py debe coincidir con lo que se indica en el paso 5.
El trabajo en los archivos de configuración está completo, así que pasemos a la aplicación.
5. Modifica los archivos de la aplicación
Importaciones
El primer conjunto de cambios para main.py incluye intercambiar todo lo que se reemplazará. Estos son los cambios:
- Flask reemplaza a
webapp2 - En lugar de usar Jinja2 de
webapp2_extras, usa el Jinja2 que viene con Flask. - Blobstore y NDB de App Engine se reemplazan por Cloud NDB y Cloud Storage
- Los controladores de Blobstore en
webappse reemplazan por una combinación del módulo de biblioteca estándario, Flask y las utilidades dewerkzeug - De forma predeterminada, Blobstore escribe en un bucket de Cloud Storage con el nombre de la URL de tu app (
PROJECT_ID.appspot.com). Como estamos migrando a la biblioteca cliente de Cloud Storage, se usagoogle.authpara obtener el ID del proyecto y especificar exactamente el mismo nombre de bucket. (Puedes cambiar el nombre del bucket, ya que no está codificado).
ANTES:
import webapp2
from webapp2_extras import jinja2
from google.appengine.ext import blobstore, ndb
from google.appengine.ext.webapp import blobstore_handlers
Implementa los cambios de la lista anterior reemplazando la sección de importación actual en main.py por el siguiente fragmento de código.
DESPUÉ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
Inicialización y compatibilidad innecesaria con Jinja2
El siguiente bloque de código que se debe reemplazar es el BaseHandler que especifica el uso de Jinja2 de webapp2_extras. Esto no es necesario porque Jinja2 viene con Flask y es su motor de plantillas predeterminado, así que quítalo.
En el módulo 16, crea una instancia de los objetos que no teníamos en la app anterior. Esto incluye inicializar la app de Flask y crear clientes de API para Cloud NDB y Cloud Storage. Por último, unimos el nombre del bucket de Cloud Storage como se describió anteriormente en la sección de importaciones. Aquí se muestra el antes y el después de implementar estas actualizaciones:
ANTES:
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))
DESPUÉS:
app = Flask(__name__)
ds_client = ndb.Client()
gcs_client = storage.Client()
_, PROJECT_ID = google.auth.default()
BUCKET = '%s.appspot.com' % PROJECT_ID
Actualiza el acceso a Datastore
Cloud NDB es, en su mayoría, compatible con App Engine NDB. Una diferencia que ya se mencionó es la necesidad de un cliente de API. Otra es que esta última requiere que el acceso a Datastore se controle mediante el administrador de contexto de Python del cliente de API. En esencia, esto significa que todas las llamadas de acceso a Datastore que usan la biblioteca cliente de Cloud NDB solo pueden ocurrir dentro de los bloques with de Python.
Ese es un cambio. El otro es que Cloud Storage no admite Blobstore ni sus objetos, p. ej., BlobKey, por lo que debes cambiar file_blob por ndb.StringProperty. A continuación, se muestran la clase de modelo de datos y las funciones store_visit() y fetch_visits() actualizadas que reflejan estos cambios:
ANTES:
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)
DESPUÉ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)
Aquí tienes una representación gráfica de los cambios que se realizaron hasta el momento:

Actualiza los controladores
Controlador de carga
Los controladores en webapp2 son clases, mientras que en Flask son funciones. En lugar de un método de verbo HTTP, Flask usa el verbo para decorar la función. Blobstore y sus controladores webapp se reemplazan por la funcionalidad de Cloud Storage, así como por Flask y sus utilidades:
ANTES:
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)
DESPUÉ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)
Algunas notas sobre esta actualización:
- En lugar de un
blob_id, los artefactos de archivo ahora se identifican por el nombre de archivo (fname) si está presente, yNonede lo contrario (el usuario optó por no subir un archivo). - Los controladores de Blobstore abstrajeron el proceso de carga de sus usuarios, pero Cloud Storage no lo hace, por lo que puedes ver el código recién agregado que establece el objeto blob y la ubicación (bucket) del archivo, así como la llamada que realiza la carga real. (
upload_from_file()). webapp2usa una tabla de enrutamiento en la parte inferior del archivo de la aplicación, mientras que las rutas de Flask se encuentran en cada controlador decorado.- Ambos controladores finalizan su funcionalidad redireccionando a la página principal (
/) y conservando la solicitudPOSTcon un código de retorno HTTP 307.
Controlador de descargas
La actualización del controlador de descargas sigue un patrón similar al del controlador de cargas, solo que hay mucho menos código para revisar. Reemplaza la funcionalidad de Blobstore y webapp por los equivalentes de Cloud Storage y Flask:
ANTES:
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)
DESPUÉ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)
Notas sobre esta actualización:
- Nuevamente, Flask decora las funciones de controlador con su ruta, mientras que
webapplo hace en una tabla de enrutamiento en la parte inferior, por lo que reconoce la sintaxis de coincidencia de patrones de este último (('/view/([^/]+)?') en comparación con la de Flask ('/view/<path:fname>'). - Al igual que con el controlador de carga, se requiere un poco más de trabajo en el lado de Cloud Storage para la funcionalidad abstraída por los controladores de Blobstore, es decir, identificar el archivo (BLOB) en cuestión y descargar de forma explícita el objeto binario en comparación con la llamada de método
send_blob()única del controlador de Blobstore. - En ambos casos, se devuelve un error HTTP 404 al usuario si no se encuentra un artefacto.
Controlador principal
Los cambios finales en la aplicación principal se realizan en el controlador principal. Los métodos de verbo HTTP webapp2 se reemplazan por una sola función que combina su funcionalidad. Reemplaza la clase MainHandler por la función root() y quita la tabla de enrutamiento webapp2, como se muestra a continuación:
ANTES:
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)
DESPUÉ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)
En lugar de separar los métodos get() y post(), son esencialmente una sentencia if-else en root(). Además, como root() es una sola función, solo hay una llamada para renderizar la plantilla para GET y POST, mientras que no es posible en webapp2.
Aquí tienes una representación gráfica de este segundo y último conjunto de cambios en main.py:

"Mejora" de retrocompatibilidad (opcional)
Por lo tanto, la solución que se creó anteriormente funciona a la perfección, pero solo si comienzas desde cero y no tienes archivos creados por Blobstore. Como actualizamos la app para identificar los archivos por nombre en lugar de BlobKey, la app del módulo 16 completada tal como está no podrá ver los archivos de Blobstore. En otras palabras, realizamos un cambio incompatible con versiones anteriores cuando hicimos esta migración. Ahora, presentamos una versión alternativa de main.py llamada main-migrate.py (que se encuentra en el repositorio) que intenta cerrar esta brecha.
La primera "extensión" que admite archivos creados por Blobstore es un modelo de datos que tiene un BlobKeyProperty (además de un StringProperty para los archivos creados por 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 propiedad file_blob se usará para identificar los archivos creados por Blobstore, mientras que file_gcs es para los archivos de Cloud Storage. Ahora, cuando crees visitas nuevas, almacena de forma explícita un valor en file_gcs en lugar de file_blob, de modo que store_visit se vea un poco diferente:
ANTES:
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()
DESPUÉ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()
Cuando recuperes las visitas más recientes, "normaliza" los datos antes de enviarlos a la plantilla:
ANTES:
@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)
DESPUÉ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)
A continuación, confirma la existencia de file_blob o file_gcs (o ninguna de las dos). Si hay un archivo disponible, elige el que existe y usa ese identificador (BlobKey para los archivos creados por Blobstore o el nombre de archivo para los archivos creados por Cloud Storage). Cuando decimos "archivos creados por Cloud Storage", nos referimos a los archivos creados con la biblioteca cliente de Cloud Storage. Blobstore también escribe en Cloud Storage, pero, en este caso, serían archivos creados por Blobstore.
Ahora, lo que es más importante, ¿qué es esta función etl_visits() que se usa para normalizar o realizar el proceso de ETL (extracción, transformación y carga) de los datos para el usuario final? El aspecto resultante será el siguiente:
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]
Probablemente se vea como esperabas: el código recorre todas las visitas y, para cada una, toma los datos del visitante y de la marca de tiempo de forma literal, luego verifica si existe file_gcs o file_blob y, si es así, elige uno de ellos (o None si no existe ninguno).
Aquí tienes una ilustración de las diferencias entre main.py y main-migrate.py:

Si comienzas desde cero sin archivos creados por Blobstore, usa main.py, pero si estás en transición y deseas que se admitan los archivos creados por Blobstore y Cloud Storage, consulta main-migrate.py como un ejemplo de cómo abordar este caso para ayudarte a planificar las migraciones de tus propias apps. Cuando se realizan migraciones complejas, es probable que surjan casos especiales, por lo que este ejemplo tiene como objetivo mostrar una mayor afinidad con la modernización de apps reales con datos reales.
6. Resumen/Limpieza
En esta sección, se concluye este codelab con la implementación de la app y la verificación de que funcione según lo previsto y en cualquier resultado reflejado. Después de la validación de la app, realiza los pasos de limpieza y considera los pasos siguientes.
Implementa y verifica la aplicación
Antes de volver a implementar tu app, asegúrate de ejecutar pip install -t lib -r requirements.txt para obtener esas bibliotecas de terceros autoagrupadas en paquetes en la carpeta lib. Si quieres ejecutar la solución retrocompatible, primero cambia el nombre de main-migrate.py a main.py. Ahora, ejecuta gcloud app deploy y confirma que la app funcione de manera idéntica a la del módulo 15. La pantalla del formulario se ve de la siguiente manera:

La página de visitas más recientes se ve de la siguiente manera:

Felicitaciones por completar este codelab en el que se reemplaza Blobstore de App Engine por Cloud Storage, NDB de App Engine por Cloud NDB y webapp2 por Flask. Tu código ahora debería coincidir con el que se encuentra en la carpeta FINISH (Módulo 16). La alternativa main-migrate.py también está presente en esa carpeta.
"Migración" a Python 3
La directiva runtime de Python 3 marcada como comentario en la parte superior de app.yaml es todo lo que se necesita para transferir esta app a Python 3. El código fuente en sí ya es compatible con Python 3, por lo que no es necesario realizar cambios allí. Para implementar esto como una app de Python 3, sigue estos pasos:
- Quita el comentario de la directiva
runtimede Python 3 en la parte superior deapp.yaml. - Borra todas las demás líneas de
app.yaml. - Borra el archivo
appengine_config.py. (no se usa en el entorno de ejecución de Python 3) - Borra la carpeta
libsi existe. (innecesario con el entorno de ejecución de Python 3)
Limpia
General
Si terminaste por ahora, te recomendamos que inhabilites tu app de App Engine para evitar que se generen cargos de facturación. Sin embargo, si quieres realizar más pruebas o experimentos, la plataforma de App Engine tiene una cuota gratuita, por lo que, siempre que no excedas ese nivel de uso, no se te cobrará. Eso es para el procesamiento, pero también puede haber cargos por los servicios de App Engine pertinentes, así que consulta su página de precios para obtener más información. Si esta migración involucra otros servicios de Cloud, estos se facturan por separado. En cualquier caso, si corresponde, consulta la sección "Específico de este codelab" que aparece más abajo.
Para que tengas toda la información, la implementación en una plataforma de computación sin servidores de Google Cloud, como App Engine, genera costos menores de compilación y almacenamiento. Cloud Build tiene su propia cuota gratuita, al igual que Cloud Storage. El almacenamiento de esa imagen consume parte de esa cuota. Sin embargo, es posible que vivas en una región que no tenga ese nivel gratuito, por lo que debes tener en cuenta el uso del almacenamiento para minimizar los costos potenciales. Estas son algunas de las "carpetas" específicas de Cloud Storage que debes revisar:
console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/imagesconsole.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com- Los vínculos de almacenamiento anteriores dependen de tu
PROJECT_IDy de la ubicación de *LOC*, por ejemplo, "us" si tu app se aloja en EE.UU.
Por otro lado, si no vas a continuar con esta aplicación ni con otros codelabs de migración relacionados y quieres borrar todo por completo, cierra el proyecto.
Específico de este codelab
Los servicios que se indican a continuación son exclusivos de este codelab. Consulta la documentación de cada producto para obtener más información:
- El servicio Blobstore de App Engine se rige por las cuotas y los límites de datos almacenados, por lo que debes revisarlos, así como la página de precios de los servicios agrupados heredados.
- Cloud Storage tiene un nivel gratuito para regiones específicas. Consulta también su página de precios generales para obtener más información.
- El servicio de App Engine Datastore lo proporciona Cloud Datastore (Cloud Firestore en modo Datastore), que también tiene un nivel gratuito. Consulta su página de precios para obtener más información".
Ten en cuenta que, si migraste del módulo 15 al 16, seguirás teniendo datos en Blobstore, por lo que incluimos su información de precios más arriba.
Próximos pasos
Además de este instructivo, hay otros módulos de migración que se enfocan en dejar de usar los servicios agrupados heredados, como los siguientes:
- Módulo 2: Migra de
ndbde App Engine a Cloud NDB - Módulos 7 a 9: Migra de las tareas de envío de la lista de tareas en cola de App Engine a Cloud Tasks
- Módulos 12 y 13: Migra de Memcache de App Engine a Cloud Memorystore
- Módulos 18 y 19: Migra de la lista de tareas en cola de App Engine (tareas de extracción) a Cloud Pub/Sub
App Engine ya no es la única plataforma sin servidores en Google Cloud. Si tienes una app de App Engine pequeña o una con funcionalidad limitada y deseas convertirla en un microservicio independiente, o si quieres dividir una app monolítica en varios componentes reutilizables, estos son buenos motivos para considerar migrar a Cloud Functions. Si la creación de contenedores se convirtió en parte de tu flujo de trabajo de desarrollo de aplicaciones, en especial si consiste en una canalización de CI/CD (integración continua/entrega o implementación continuas), considera migrar a Cloud Run. Estas situaciones se abordan en los siguientes módulos:
- Migra de App Engine a Cloud Functions: consulta el módulo 11
- Migra de App Engine a Cloud Run: Consulta el módulo 4 para alojar tu app en contenedores con Docker o el módulo 5 para hacerlo sin contenedores, conocimientos de Docker o
Dockerfiles
Cambiar a otra plataforma sin servidores es opcional, y te recomendamos que consideres las mejores opciones para tus apps y casos de uso antes de realizar cualquier cambio.
Independientemente del módulo de migración que consideres a continuación, se puede acceder a todo el contenido de la estación de migración sin servidores (codelabs, videos y código fuente [cuando esté disponible]) en su repositorio de código abierto. El archivo README del repositorio también proporciona orientación sobre qué migraciones considerar y cualquier "orden" relevante de los módulos de migración.
7. Recursos adicionales
Problemas o comentarios sobre el codelab
Si encuentras algún problema con este Codelab, primero busca el problema antes de enviarlo. Vínculos para buscar y crear problemas nuevos:
Recursos de migración
En la siguiente tabla, se incluyen vínculos a las carpetas del repositorio para el módulo 15 (START) y el módulo 16 (FINISH). También se puede acceder a ellos desde el repositorio de todas las migraciones de codelabs de App Engine, que puedes clonar o descargar como un archivo ZIP.
Codelab | Python 2 | Python 3 |
Módulo 15 | N/A | |
Módulo 16 (este codelab) | (igual que Python 2) |
Recursos en línea
A continuación, se incluyen recursos en línea que pueden ser pertinentes para este instructivo:
Blobstore de App Engine y Cloud Storage
- Servicio de Blobstore de App Engine
- Migra a la biblioteca cliente de Cloud Storage
- Página principal de Cloud Storage
- Documentación de Cloud Storage
Plataforma de App Engine
- Documentación de App Engine
- Entorno de ejecución de Python 2 de App Engine (entorno estándar)
- Usa bibliotecas integradas de App Engine en App Engine para Python 2
- Entorno de ejecución de Python 3 de App Engine (entorno estándar)
- Diferencias entre los entornos de ejecución de Python 2 y 3 de App Engine (entorno estándar)
- Guía de migración de Python 2 a 3 en App Engine (entorno estándar)
- Información sobre los precios y las cuotas de App Engine
- Lanzamiento de la plataforma de App Engine de segunda generación (2018)
- Comparación de las plataformas de primera y segunda generación
- Asistencia a largo plazo para entornos de ejecución heredados
- Repositorio de muestras de migración de documentación
- Repositorio de muestras de migración aportadas por la comunidad
Información de otra nube
- Python en Google Cloud Platform
- Bibliotecas cliente de Python de Google Cloud
- Nivel "Siempre gratuito" de Google Cloud
- SDK de Google Cloud (herramienta de línea de comandos de
gcloud) - Toda la documentación de Google Cloud
Python
- Sistemas de plantillas de Django y Jinja2
- Framework web de
webapp2 - Documentación de
webapp2 webapp2_extrasvínculos- Documentación de Jinja2 de
webapp2_extras - Framework web de Flask
Videos
- Serverless Migration Station
- Serverless Expeditions
- Suscríbete a Google Cloud Tech
- Suscríbete a Google Developers
Licencia
Este trabajo cuenta con una licencia Atribución 2.0 Genérica de Creative Commons.