App Engine Blobstore から Cloud Storage への移行(モジュール 16)

1. 概要

Serverless Migration Station の Codelab シリーズ(セルフペース型のハンズオン チュートリアル)と関連動画は、Google Cloud サーバーレス デベロッパーが主にレガシー サービスからの移行を 1 つ以上の移行を通じてガイドし、アプリをモダナイズできるようにすることを目的としています。これにより、アプリのポータビリティが高まり、選択肢と柔軟性が増し、より広範な Cloud プロダクトと統合してアクセスできるようになり、より新しい言語リリースに簡単にアップグレードできるようになります。当初は初期の Cloud ユーザー、主に App Engine(スタンダード環境)のデベロッパーを対象としていますが、Cloud FunctionsCloud Run など、その他のサーバーレス プラットフォーム(該当する場合)まで幅広くカバーしています。

この Codelab では、App Engine Blobstore から Cloud Storage に移行する方法を説明します。以下からの暗黙的な移行もあります。

詳しい手順については、関連する移行モジュールをご覧ください。

GCP コンソールの

  • App Engine Blobstore API/ライブラリの使用を追加する
  • Blobstore サービスへのユーザーのアップロードを保存する
  • Cloud Storage への移行に向けた次のステップの準備

必要なもの

アンケート

このチュートリアルをどのように使用されますか?

通読のみ 通読して演習を行う

Python のご利用経験はどの程度ありますか?

初心者 中級者 上級者

Google Cloud サービスの使用経験はどの程度ありますか?

<ph type="x-smartling-placeholder"></ph> 初心者 中級 上達 をご覧ください。

2. 背景情報

この Codelab は、モジュール 15 のサンプルアプリから始まり、Blobstore(および NDB)から Cloud Storage(および Cloud NDB)に移行する方法を示します。移行プロセスでは、App Engine の以前のバンドル サービスの依存関係を置き換えます。必要に応じて、アプリを別の Cloud サーバーレス プラットフォームや他のホスティング プラットフォームに移行できます。

この移行は、このシリーズの他の移行と比べて少し手間がかかります。Blobstore は元の webapp フレームワークと依存関係があるため、サンプルアプリでは Flask ではなく webapp2 フレームワークを使用しています。このチュートリアルでは、Cloud Storage、Cloud NDB、Flask、Python 3 への移行について説明します。

アプリはエンドユーザーの「訪問」を登録します。直近の 10 件を表示しますが、前(モジュール 15)の Codelab では Blobstore に対応するために新機能が追加されています。これは、エンドユーザーに対し、訪問に対応するアーティファクト(ファイル)をアップロードするよう促すプロンプトです。ユーザーはこの操作を行うか、[スキップ] を選択できます。オプトアウトします。ユーザーの判断にかかわらず、次のページでは、このアプリの前身と同じ出力が表示され、最新のアクセスが表示されます。さらに、対応するアーティファクトがある訪問には「ビュー」が加わります。リンクを使用して訪問のアーティファクトを表示します。この Codelab では、説明されている機能を維持しながら、前述の移行を実装します。

3. 設定/事前作業

チュートリアルの主要部分に進む前に、プロジェクトを設定し、コードを取得してから、ベースライン アプリをデプロイして、コードの作業を開始できるようにします。

1. プロジェクトのセットアップ

モジュール 15 アプリをすでにデプロイしている場合は、同じプロジェクト(およびコード)を再利用することをおすすめします。あるいは、新しいプロジェクトを作成することも、別の既存のプロジェクトを再利用することもできます。プロジェクトに有効な請求先アカウントがあり、App Engine が有効になっていることを確認します。

2. ベースラインのサンプルアプリを取得する

この Codelab の前提条件の 1 つは、モジュール 15 のサンプルアプリを使用することです。ない場合は、モジュール 15 の「開始」から取得できます。(下記のリンクを参照)。この Codelab では各ステップを紹介し、最後にモジュール 16 の「FINISH」に似たコードで締めくくります。フォルダに配置されます。

モジュール 15 の開始ファイルのディレクトリは次のようになります。

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

main-gcs.py ファイルはモジュール 15 の main.py の代替バージョンであり、プロジェクトの ID に基づいてアプリに割り当てられたデフォルトの URL(PROJECT_ID.appspot.com)とは異なる Cloud Storage バケットを選択できます。このファイルは、この Codelab(モジュール 16)では使用されませんが、必要に応じて同様の移行手法をファイルに適用できる点が異なります。

3. ベースライン アプリを(再)デプロイする

この段階で実施する必要がある残りの事前作業のステップ:

  1. gcloud コマンドライン ツールを学びなおす
  2. gcloud app deploy を使用してサンプルアプリを再デプロイする
  3. アプリが App Engine で問題なく動作することを確認する

上記の手順を正常に実行し、モジュール 15 アプリが機能することを確認します。最初のページでは、訪問アーティファクト ファイルのアップロードを求めるフォームと [スキップ] オプションがユーザーに表示されます。無効にするには、次の操作を行います。

f5b5f9f19d8ae978.png

ユーザーがファイルをアップロードまたはスキップすると、なじみのある「直近のアクセス」がアプリに表示されます。ページ:

f5ac6b98ee8a34cb.png

アーティファクトを含む訪問には「ビュー」が表示されます。クリックして、アーティファクトを表示(またはダウンロード)できます。アプリの機能を確認したら、App Engine のレガシー サービス(webapp2、NDB、Blobstore)から最新の代替サービス(Flask、Cloud NDB、Cloud Storage)に移行できます。

4. 構成ファイルを更新する

アプリのアップデート バージョンには 3 つの構成ファイルが関係します。必要なタスクは次のとおりです。

  1. app.yaml で必要な組み込みサードパーティ ライブラリを更新し、Python 3 に移行できる状態にしておきます。
  2. 組み込みではない必要なライブラリをすべて指定する requirements.txt を追加します。
  3. appengine_config.py を追加して、アプリが組み込みサードパーティ ライブラリと非組み込みサードパーティ ライブラリの両方をサポートするようにします。

app.yaml

libraries セクションを更新して、app.yaml ファイルを編集します。jinja2 を削除し、grpciosetuptoolsssl を追加します。3 つのライブラリすべてで利用可能な最新バージョンを選択してください。また、Python 3 の runtime ディレクティブも追加しますが、コメントアウトします。完了すると、次のようになります(Python 3.9 を選択した場合)。

変更前:

runtime: python27
threadsafe: yes
api_version: 1

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

libraries:
- name: jinja2
  version: latest

変更後:

#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

この変更は主に、App Engine サーバーで利用可能な Python 2 組み込みライブラリに関するものです(自己バンドルする必要はありません)。Jinja2 は Flask に付属しているため削除し、reqs.txt に追加します。Cloud NDB や Cloud Storage 用など、Google Cloud クライアント ライブラリを使用する場合は常に、grpcio と setuptools が必要です。最後に、Cloud Storage 自体に SSL ライブラリが必要です。上部のコメントアウトされたランタイム ディレクティブは、このアプリを Python 3 に移植する準備ができたときのためのものです。このトピックについては、このチュートリアルの最後に説明します。

requirements.txt

requirements.txt ファイルを追加します。Flask フレームワークと、Cloud NDB および Cloud Storage のクライアント ライブラリはいずれも組み込みではありません。次の内容のファイルを作成します。

flask
google-cloud-ndb
google-cloud-storage

Python 2 App Engine ランタイムでは、サードパーティが組み込まれていないライブラリを自己バンドルする必要があるため、次のコマンドを実行してこれらのライブラリを lib フォルダにインストールします。

pip install -t lib -r requirements.txt

開発マシンに Python 2 と Python 3 の両方がある場合は、これらのライブラリの Python 2 バージョンを確実に取得するために、pip2 コマンドを使用する必要があります。Python 3 にアップグレードしたら、自己バンドル化する必要はありません。

appengine_config.py

組み込みサードパーティ ライブラリと非組み込みサードパーティ ライブラリをサポートする appengine_config.py ファイルを追加します。次の内容のファイルを作成します。

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)

たった今完了した手順は、App Engine ドキュメントの Python 2 アプリ用ライブラリのインストール セクションに記載されている手順とほぼ同じか、まったく同じです。具体的には、appengine_config.py の内容が手順 5 の内容と一致している必要があります。

構成ファイルの作業が完了したので、アプリケーションに進みましょう。

5. アプリケーション ファイルを変更する

インポート

main.py の最初の変更セットには、置換されるすべての項目のスワップアウトが含まれます。変更点は次のとおりです。

  1. webapp2 は Flask に置き換えられます。
  2. webapp2_extras の Jinja2 を使用する代わりに、Flask に付属する Jinja2 を使用します。
  3. App Engine Blobstore と NDB は Cloud NDB と Cloud Storage に置き換えられます
  4. webapp の Blobstore ハンドラは、io 標準ライブラリ モジュール、Flask、werkzeug ユーティリティの組み合わせに置き換えられます。
  5. デフォルトでは、Blobstore はアプリの URL(PROJECT_ID.appspot.com)に基づいた名前の Cloud Storage バケットに書き込みます。Cloud Storage クライアント ライブラリに移植するため、google.auth を使用してプロジェクト ID を取得し、まったく同じバケット名を指定します。(バケット名はハードコードされなくなったため、変更できます)。

変更前:

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

main.py の現在のインポート セクションを以下のコード スニペットに置き換えて、上記のリストの変更を実装します。

変更後:

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

初期化と不要な Jinja2 サポート

次に置き換えるコードブロックは、webapp2_extras の Jinja2 の使用を指定する BaseHandler です。Jinja2 には Flask に付属しており、Jinja2 のデフォルトのテンプレート エンジンであるため、これは不要です。

モジュール 16 側では、古いアプリになかったオブジェクトをインスタンス化します。これには、Flask アプリの初期化と、Cloud NDB および Cloud Storage 用の API クライアントの作成が含まれます。最後に、インポートのセクションで前述したように、Cloud Storage バケット名をまとめます。これらの更新の実装前と実装後は次のとおりです。

変更前:

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))

変更後:

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

Datastore アクセスを更新する

Cloud NDB は、App Engine NDB とほぼ互換性があります。すでに説明した違いの一つは、API クライアントが必要であるという点です。後者の場合は、データストアへのアクセスが API クライアントの Python コンテキスト マネージャーによって制御される必要があります。つまり、Cloud NDB クライアント ライブラリを使用した Datastore アクセス呼び出しはすべて、Python の with ブロック内でのみ実行できます。

これは 1 回の変更です。もう 1 つは、Blobstore とそのオブジェクトです(例:BlobKey は Cloud Storage でサポートされていないため、代わりに file_blobndb.StringProperty に変更します。以下は、これらの変更を反映したデータモデル クラスと、更新された store_visit() 関数と fetch_visits() 関数です。

変更前:

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)

変更後:

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)

以下は、これまでに行われた変更を画像で表したものです。

a8f74ca392275822.png

ハンドラの更新

アップロード ハンドラ

webapp2 のハンドラは、Flask では関数ですが、クラスです。Flask は、HTTP 動詞メソッドの代わりに動詞を使用して関数を装飾します。Blobstore とその webapp ハンドラは、Cloud Storage の機能に加えて、Flask とそのユーティリティに置き換えられます。

変更前:

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)

変更後:

@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)

この更新に関する注意事項:

  • ファイル アーティファクトは、blob_id ではなくファイル名(fname)で識別されるようになりました(存在する場合)。また、存在しない場合は None(ユーザーがファイルのアップロードを無効にしました)で識別されるようになりました。
  • Blobstore ハンドラではユーザーがアップロード プロセスを抽象化していますが、Cloud Storage は抽象化していないので、ファイルの blob オブジェクトと場所(バケット)を設定する新しく追加されたコードや、実際のアップロードを実行する呼び出しを確認できます。(upload_from_file())を更新します。
  • webapp2 はアプリケーション ファイルの下部にあるルーティング テーブルを使用しますが、Flask のルートは各装飾ハンドラ内にあります。
  • どちらのハンドラも、ホームにリダイレクト(/)することで機能をまとめますが、POST リクエストは HTTP 307 戻りコードを保持します。

ハンドラのダウンロード

ダウンロード ハンドラの更新はアップロード ハンドラと同様のパターンに従いますが、確認するコードが大幅に減るだけです。Blobstore と webapp の機能を Cloud Storage と Flask の同等の機能に置き換えます。

変更前:

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)

変更後:

@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)

この更新に関する注意事項:

  • 繰り返しになりますが、Flask はハンドラ関数をルートでデコレートしますが、webapp は下部のルーティング テーブルでデコレートするため、後者のパターン マッチング構文(('/view/([^/]+)?')と Flask('/view/<path:fname>')の違いに注意してください。
  • アップロード ハンドラと同様に、Blobstore ハンドラによって抽象化される機能(対象のファイル(blob)を識別し、バイナリを明示的にダウンロードする Blobstore ハンドラの send_blob() メソッド呼び出しではなく)について、Cloud Storage 側でもう少し作業が必要になります。
  • いずれの場合も、アーティファクトが見つからない場合は HTTP 404 エラーがユーザーに返されます。

メインハンドラ

メイン アプリケーションの最終的な変更は、メイン ハンドラで行われます。HTTP 動詞 webapp2 のメソッドは、それらの機能を組み合わせた単一の関数に置き換えられます。次のように、MainHandler クラスを root() 関数に置き換え、webapp2 ルーティング テーブルを削除します。

変更前:

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)

変更後:

@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)

get() メソッドと post() メソッドを分離するのではなく、本質的には root() 内の if-else ステートメントです。また、root() は単一の関数であるため、GETPOST の両方のテンプレートをレンダリングする呼び出しは 1 回だけですが、webapp2 では実際には不可能です。

次に示すのは、main.py の 2 つ目(最後)の変更を図で表したものです。

5ec38818c32fec2.png

(省略可)下位互換性の「拡張」

したがって、上記で作成したソリューションは問題なく機能しますが、ゼロから始める場合で、Blobstore によって作成されたファイルがない場合に限られます。BlobKey ではなくファイル名でファイルを識別するようアプリを更新したため、完成したモジュール 16 のアプリはそのままでは Blobstore ファイルを表示できません。つまり、この移行を実施する際に、下位互換性のない変更が行われました。このギャップを埋めようとしているのが、main-migrate.py(リポジトリにあります)という main.py の代替バージョンです。

1 つ目の「拡張機能」はBlobstore によって作成されたファイルをサポートするには、(Cloud Storage で作成されたファイル用の StringProperty に加えて)BlobKeyProperty を含むデータモデルを使用します。

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()

file_blob プロパティは Blobstore によって作成されたファイルの識別に使用されますが、file_gcs は Cloud Storage ファイルに使用されます。新しい訪問を作成するときは、file_blob ではなく file_gcs に明示的に値を保存するため、store_visit の内容が若干異なります。

変更前:

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 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()

直近のアクセスを取得する際に「正規化」します。変換してからテンプレートに送信します。

変更前:

@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)

変更後:

@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)

次に、file_blob または file_gcs が存在する(またはどちらも存在しない)ことを確認します。使用可能なファイルがある場合は、存在するファイルを選択して、その識別子(Blobstore によって作成されたファイルの場合は BlobKey、Cloud Storage によって作成されたファイルの場合はファイル名)を使用します。「Cloud Storage で作成されたファイル」とは、つまり、Cloud Storage クライアント ライブラリを使用して作成されたファイルです。Blobstore は Cloud Storage にも書き込みますが、この場合は Blobstore によって作成されたファイルになります。

さらに重要なこととして、エンドユーザーのデータの正規化または ETL(抽出、変換、読み込み)に使用する、この etl_visits() 関数は何ですか。たとえば、次のようになります。

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]

おそらく期待どおりのようです。すべての訪問について、すべての訪問について、訪問者とタイムスタンプのデータをそのまま取得して、file_gcs または file_blob が存在するかどうかを確認し、存在する場合はいずれか 1 つを選択します(どちらも存在しない場合は None)。

main.pymain-migrate.py の違いを以下に示します。

718b05b2adadb2e1.png

Blobstore によって作成されたファイルを使用せずにゼロから開始する場合は、main.py を使用してください。ただし、移行する場合、Blobstore Cloud Storage の両方で作成されたファイルをサポートする必要がある場合は、main-migrate.py を参照して、アプリの移行計画の例として、アプリ移行計画の例としてご確認ください。複雑な移行では特殊なケースが生じる可能性が高く、この例は、実際のデータを使用して実際のアプリをモダナイズすることに対する親和性が高いことを示しています。

6. 概要/クリーンアップ

このセクションでは、この Codelab の締めくくりとして、アプリをデプロイし、意図したとおりに動作することを確認し、反映された出力を確認します。アプリの検証後、クリーンアップ手順を実施し、次のステップを検討します。

アプリケーションのデプロイと検証

アプリを再デプロイする前に、必ず pip install -t lib -r requirements.txt を実行して、セルフバンドルのサードパーティ ライブラリを lib フォルダから取得してください。下位互換性のあるソリューションを実行する場合は、まず main-migrate.py の名前を main.py に変更します。次に、gcloud app deploy を実行して、アプリがモジュール 15 のアプリと同じように動作することを確認します。フォーム画面は次のようになります。

f5b5f9f19d8ae978.png

[最新の訪問履歴] ページは次のようになります。

f5ac6b98ee8a34cb.png

これで、この Codelab は終了です。App Engine Blobstore を Cloud Storage に、App Engine NDB を Cloud NDB に、webapp2 を Flask に置き換えました。コードが FINISH(モジュール 16)フォルダの内容と一致しているはずです。このフォルダには代替の main-migrate.py もあります。

Python 3 の「移行」

このアプリを Python 3 に移植するために必要なのは、app.yaml の先頭にあるコメントアウトされた Python 3 runtime ディレクティブだけです。ソースコード自体はすでに Python 3 と互換性があるため、変更する必要はありません。これを Python 3 アプリとしてデプロイするには、次の手順を行います。

  1. app.yaml の先頭にある Python 3 runtime ディレクティブをコメント化解除します。
  2. app.yaml の他のすべての行を削除します。
  3. appengine_config.py ファイルを削除します。(Python 3 ランタイムでは使用しません)
  4. lib フォルダが存在する場合は削除します。(Python 3 ランタイムでは不要)

クリーンアップ

全般

現時点で完了したら、課金が発生しないように App Engine アプリを無効にすることをおすすめします。さらにテストや実験を行う場合は、App Engine プラットフォームに無料の割り当てが用意されています。この使用量ティアを超えない限り、料金は発生しません。これはコンピューティングに関するものですが、関連する App Engine サービスに対して料金が発生する場合もあります。詳細については、料金ページをご覧ください。この移行に他のクラウド サービスが含まれる場合、それらは別途請求されます。いずれの場合も、該当する場合は「この Codelab に固有の情報」をご覧ください。セクションをご覧ください。

App Engine のような Google Cloud サーバーレス コンピューティング プラットフォームにデプロイすると、わずかなビルドとストレージの費用が発生します。Cloud Build には、Cloud Storage と同様に無料の割り当てがあります。イメージのストレージが割り当ての一部を使い果たします。ただし、このような無料枠がない地域に住んでいる可能性もあるため、潜在的な費用を最小限に抑えるためにストレージの使用量に注意してください。特定の Cloud Storage「フォルダ」確認すべき項目には

  • 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
  • 上記のストレージ リンクは、ご利用の PROJECT_ID と *LOC*に依存します(例: 「us」)アプリが米国でホストされている場合は、

一方、このアプリケーションや他の関連する移行 Codelab を続行せず、すべてを完全に削除したい場合は、プロジェクトをシャットダウンします。

この Codelab のみ

以下に示すサービスは、この Codelab に固有のものです。詳細については、各プロダクトのドキュメントをご覧ください。

モジュール 15 から 16 に移行した場合、Blobstore にはまだデータが存在するため、その料金情報を上に記載しています。

次のステップ

このチュートリアル以外にも、以前のバンドル サービスからの移行に重点を置いた他の移行モジュールを以下に示します。

App Engine はもはや Google Cloud の唯一のサーバーレス プラットフォームではありません。小規模な App Engine アプリまたは機能が限られているアプリをスタンドアロンのマイクロサービスに変換したい場合、またはモノリシック アプリを複数の再利用可能なコンポーネントに分割する必要がある場合は、こうした理由から Cloud Functions への移行を検討することをおすすめします。コンテナ化がアプリケーション開発ワークフローの一部になっている場合、特に CI/CD(継続的インテグレーション/継続的デリバリーまたはデプロイ)パイプラインで構成されている場合は、Cloud Run への移行を検討してください。これらのシナリオについては、次のモジュールで説明します。

  • App Engine から Cloud Functions への移行: モジュール 11 を参照
  • App Engine から Cloud Run への移行: モジュール 4 を参照して、Docker を使用してアプリをコンテナ化するか、モジュール 5 を参照して、コンテナ、Docker の知識、または Dockerfile を使用せずに

別のサーバーレス プラットフォームへの切り替えは任意です。変更を行う前に、アプリやユースケースに最適なオプションを検討することをおすすめします。

次に検討する移行モジュールに関係なく、Serverless Migration Station のすべてのコンテンツ(Codelab、動画、ソースコード(利用可能な場合))には、オープンソース リポジトリからアクセスできます。リポジトリの README には、検討すべき移行や関連する「順序」に関するガイダンスも用意されています。概要をまとめたものです

7. 参考情報

Codelab の問題/フィードバック

この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:

移行に関するリソース

以下の表に、モジュール 15(START)とモジュール 16(FINISH)のリポジトリ フォルダへのリンクを示します。これらは、すべての App Engine Codelab 移行用のリポジトリからもアクセスでき、ZIP ファイルのクローンを作成したりダウンロードしたりできます。

Codelab

Python 2

Python 3

モジュール 15

コード

なし

モジュール 16(この Codelab)

コード

(Python 2 と同じ)

オンライン リソース

このチュートリアルに関連する可能性のあるオンライン リソースは次のとおりです。

App Engine Blobstore と Cloud Storage

App Engine プラットフォーム

Cloud のその他の情報

Python

動画

ライセンス

この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。