1. 概要
Serverless Migration Station の Codelab シリーズ(セルフペース型のハンズオン チュートリアル)と関連動画は、Google Cloud サーバーレス デベロッパーが主にレガシー サービスからの移行を 1 つ以上の移行を通じてガイドし、アプリをモダナイズできるようにすることを目的としています。これにより、アプリのポータビリティが高まり、選択肢と柔軟性が増し、より広範な Cloud プロダクトと統合してアクセスできるようになり、より新しい言語リリースに簡単にアップグレードできるようになります。当初は初期の Cloud ユーザー、主に App Engine(スタンダード環境)のデベロッパーを対象としていますが、Cloud Functions や Cloud Run など、その他のサーバーレス プラットフォーム(該当する場合)まで幅広くカバーしています。
この Codelab では、Python 2 の App Engine デベロッパーに、App Engine Memcache から Cloud Memorystore(Redis 用)に移行する方法を紹介します。App Engine ndb
から Cloud NDB への暗黙的な移行もありますが、これは主にモジュール 2 の Codelab で説明しています。詳しい手順を確認できます
GCP コンソールの
- Cloud Memorystore インスタンスを設定する(Cloud コンソールまたは
gcloud
ツールから) - Cloud サーバーレス VPC アクセス コネクタを設定する(Cloud コンソールまたは
gcloud
ツールから) - App Engine Memcache から Cloud Memorystore に移行する
- サンプルアプリで Cloud Memorystore を使用してキャッシュを実装する
- App Engine
ndb
から Cloud NDB への移行
必要なもの
- 有効な請求先アカウントを持つ Google Cloud プロジェクト(無料の Codelab ではありません)
- 基本的な Python スキル
- 一般的な Linux コマンドに関する実践的な知識
- App Engine アプリの開発とデプロイに関する基本的な知識
- 動作中のモジュール 12 の App Engine アプリ(モジュール 12 の Codelab(推奨)を完了するか、リポジトリからモジュール 12 アプリをコピーします)
アンケート
このチュートリアルの利用方法をお選びください。
<ph type="x-smartling-placeholder">Python のご利用経験はどの程度ありますか?
Google Cloud サービスの使用経験はどの程度ありますか?
<ph type="x-smartling-placeholder">2. 背景情報
この Codelab では、サンプルアプリを App Engine Memcache(および NDB)から Cloud Memorystore(および Cloud NDB)に移行する方法について説明します。このプロセスでは、App Engine バンドル サービスの依存関係を置き換えて、アプリのポータビリティを高めます。App Engine を引き続き使用するか、前述のいずれかの代替手段に移行することを検討できます。
この移行は、このシリーズの他の移行と比べて手間がかかります。App Engine Memcache の推奨代替策は、フルマネージドのクラウドベースのキャッシュ サービスである Cloud Memorystore です。Memorystore は、一般的なオープンソースのキャッシュ エンジンである Redis と Memcached のペアをサポートしています。この移行モジュールは、Cloud Memorystore for Redis を使用します。詳細については、Memorystore と Redis の概要をご覧ください。
Memorystore には実行中のサーバーが必要であるため、Cloud VPC も必要です。具体的には、App Engine アプリがプライベート IP アドレスを使用して Memorystore インスタンスに接続できるように、サーバーレス VPC アクセス コネクタを作成する必要があります。この演習を終えると、アプリが更新され、アプリは以前と同じように動作しますが、Cloud Memorystore が App Engine の Memcache サービスに代わるキャッシュ サービスになるようになります。
このチュートリアルは、Python 2 のモジュール 12 サンプルアプリから始まり、Python 3 への追加のマイナー アップグレード(オプション)が続きます。Python 3 App Engine SDK を使用して Python 3 から App Engine バンドル サービスにアクセスすることにすでに慣れている場合は、Module 12 サンプルアプリの Python 3 バージョンから開始できます。Memorystore は App Engine のバンドル サービスではないため、これによって SDK の使用がなくなります。このチュートリアルでは、Python 3 App Engine SDK の使用方法について説明しません。
このチュートリアルでは、次の重要な手順について説明します。
- 設定/事前作業
- キャッシュ サービスを設定する
- 設定ファイルを更新する
- メイン アプリケーションを更新する
3. 設定/事前作業
Cloud プロジェクトを準備する
モジュール 12 の Codelab で使用したプロジェクトと同じプロジェクトを再利用することをおすすめします。あるいは、新しいプロジェクトを作成することも、別の既存のプロジェクトを再利用することもできます。このシリーズのすべての Codelab には「開始」という言葉があります。(開始時のベースライン コード)と "FINISH" の(移行されたアプリ)を選択します。問題が発生した場合に備え、FINISH コードが提供されているので、自社のソリューションと Google のソリューションを比較できます。問題が発生した場合には、いつでもロールバックして開始することができます。これらのチェックポイントは、移行の実施方法の学習が成功していることを確認するためのものです。
どの Cloud プロジェクトを使用する場合でも、有効な請求先アカウントがあることを確認してください。また、App Engine が有効になっていることを確認します。これらのチュートリアルを実施する場合は、一般的な費用への影響を確認し、理解するようにしてください。ただし、このシリーズの他の Codelab とは異なり、この Codelab では無料枠がない Cloud リソースを使用するため、この演習を完了するためにいくつかの費用が発生します。より具体的な費用情報と、使用量を抑えるための推奨事項(最後に、請求額を最小限に抑えるためのリソースのリリース手順など)が提供されます。
ベースラインのサンプルアプリを取得する
この Codelab では、最初に使用したモジュール 12 のベースライン コードに基づいて、移行を順を追って説明します。完了すると、いずれかの FINISH フォルダにあるコードとよく似た、機能するモジュール 13 アプリが表示されます。これらのリソースは次のとおりです。
- 開始: モジュール 12 Python 2(
mod12
)または Python 3(mod12b
)アプリ - 完了: モジュール 13 Python 2(
mod13a
)または Python 3(mod13b
)アプリ - 移行リポジトリ全体(ZIP のクローンを作成するかダウンロードします)
START フォルダには、次のファイルが含まれている必要があります。
$ ls README.md app.yaml main.py requirements.txt templates
Python 2 バージョンから始める場合は、appengine_config.py
ファイルもあります。モジュール 12 の Codelab を完了している場合は、lib
フォルダが存在する可能性があります。
モジュール 12 アプリを(再)デプロイする
残りの事前作業手順:
gcloud
コマンドライン ツールについて再度確認する(必要な場合)- モジュール 12 のコードを App Engine に(再)デプロイする(必要な場合)
Python 2 の場合は、次のコマンドを使用して、lib
フォルダを削除して再インストールする必要があります。
rm -rf ./lib; pip install -t lib -r requirements.txt
これで、全員(Python 2 と 3 のユーザー)が次のコマンドを使用して App Engine にコードをアップロードする必要があります。
gcloud app deploy
デプロイが正常に完了したら、アプリの外観と動作がモジュール 12 のアプリと同様に機能することを確認します。このモジュール 12 は、アクセスを追跡し、同じユーザーの 1 時間キャッシュ保存を行うウェブアプリです。
最近のアクセスがキャッシュされているため、ページを更新するとすぐに読み込まれます。
4. キャッシュ サービスを設定する
Cloud Memorystore はサーバーレスではありません。インスタンスは必須です。この例では Redis が動作していますMemcache とは異なり、Memorystore はスタンドアロンの Cloud プロダクトであり、無料枠はないため、続行する前に必ず Memorystore for Redis の料金情報をご確認ください。この演習の費用を最小限に抑えるために、最小限のリソース(ベーシック サービスティアと 1 GB の容量)を運用することをおすすめします。
Memorystore インスタンスは App Engine アプリ(インスタンス)とは異なるネットワーク上にあるため、App Engine が Memorystore リソースにアクセスできるようにサーバーレス VPC アクセス コネクタを作成する必要があります。VPC の費用を最小限に抑えるには、インスタンス タイプ(f1-micro
)とリクエストするインスタンスの最小数を選択します(最小 2 個、最大 3 個をおすすめします)。また、VPC の料金情報ページもご確認ください。
費用削減のためにこれらの推奨事項を繰り返し、必要な各リソースを作成する手順を説明します。さらに、Cloud コンソールで Memorystore リソースと VPC リソースを作成すると、各プロダクトの右上に料金計算ツールが表示され、毎月の費用を見積もることができます(下の図を参照)。オプションを変更すると、これらの値は自動的に調整されます。次のように表示されます。
どちらのリソースも必須であり、どちらを最初に作成しても構いません。最初に Memorystore インスタンスを作成すると、App Engine アプリは VPC コネクタなしではそのインスタンスにアクセスできません。同様に、先に VPC コネクタを作成した場合、App Engine アプリが通信する VPC ネットワークはありません。このチュートリアルでは、まず Memorystore インスタンスを作成し、次に VPC コネクタを作成します。
両方のリソースがオンラインになったら、関連情報を app.yaml
に追加して、アプリがキャッシュにアクセスできるようにします。公式ドキュメントで Python 2 または Python 3 のガイドもご覧ください。Cloud NDB の移行ページにあるデータ キャッシュ ガイド(Python 2 または Python 3)も参照してください。
Cloud Memorystore インスタンスを作成する
Cloud Memorystore には無料枠がないため、Codelab を完了するための割り当ては最小限にすることをおすすめします。次の設定を使用することで、費用を最小限に抑えることができます。
- 最下位のサービスティアとして [基本] を選択します(コンソールのデフォルト: [スタンダード]、
gcloud
のデフォルト: [ベーシック])。 - 最小容量として [1 GB] を選択します(コンソールのデフォルト: 16 GB、
gcloud
のデフォルト: 1 GB)。 - 通常、どのソフトウェアでも、最新バージョンには大量のリソースが必要になりますが、最も古いバージョンを選択するのはおすすめしません。現在の 2 番目の最新バージョンは Redis バージョン 5.0 です(コンソールのデフォルト: 6.x)
これらの設定を念頭に置いて、次のセクションでは Cloud コンソールからインスタンスを作成する手順を説明します。コマンドラインから行う場合は、先へ進んでください。
Cloud Console から
Cloud コンソールの Cloud Memorystore ページに移動します(お支払い情報の入力を求められる場合があります)。Memorystore をまだ有効にしていない場合は、有効にするよう求められます。
有効にすると(場合によっては課金とともに)、Memorystore ダッシュボードが表示されます。ここで、プロジェクトで作成されたすべてのインスタンスを確認できます。以下のプロジェクトには存在しないため、「No rows to display」と表示されます。Memorystore インスタンスを作成するには、上部にある [インスタンスを作成] をクリックします。
このページには、Memorystore インスタンスを作成するために必要な設定を入力するフォームがあります。
このチュートリアルとサンプルアプリの費用を抑えるには、前述の推奨事項に従ってください。設定が完了したら、[作成] をクリックします。作成プロセスには数分かかります。完了したら、インスタンスの IP アドレスとポート番号をコピーして、app.yaml
に追加します。
コマンドラインから
Cloud コンソールから Memorystore インスタンスを作成することは、視覚的にわかりやすいといえますが、コマンドラインのほうが好まれる場合もあります。次に進む前に、必ず gcloud
をインストールして初期化してください。
Cloud コンソールと同様に、Cloud Memorystore for Redis を有効にする必要があります。次の例のように、gcloud services enable redis.googleapis.com
コマンドを発行して、完了するまで待ちます。
$ gcloud services enable redis.googleapis.com Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
サービスがすでに有効になっている場合、このコマンドを実行しても副作用(悪影響)は発生しません。サービスを有効にして、Memorystore インスタンスを作成しましょう。このコマンドは以下のようになります。
gcloud redis instances create NAME --redis-version VERSION \ --region REGION --project PROJECT_ID
Memorystore インスタンスの名前を選択します。このラボでは「demo-ms
」を使用します。プロジェクト ID「my-project
」と一緒に名前として使用します。このサンプルアプリのリージョンは us-central1
(us-central
と同じ)ですが、レイテンシが懸念される場合は、より近いリージョンを使用できます。App Engine アプリと同じリージョンを選択する必要があります。任意の Redis バージョンを選択できますが、先ほど推奨されているバージョン 5 を使用しています。これらの設定で指定すると、コマンドが(および関連する出力とともに)表示されます。
$ gcloud redis instances create demo-ms --region us-central1 \ --redis-version redis_5_0 --project my-project Create request issued for: [demo-ms] Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done. Created instance [demo-ms].
Cloud コンソールのデフォルトとは異なり、gcloud
はデフォルトで最小限のリソースに設定されます。その結果、このコマンドではサービスティアもストレージ容量も必要ありませんでした。Memorystore インスタンスの作成には数分かかります。作成が完了したら、インスタンスの IP アドレスとポート番号をメモします。これらはまもなく app.yaml
に追加されます。
インスタンスが作成されたことを確認する
Cloud コンソールまたはコマンドラインから
インスタンスを作成したのが Cloud コンソールかコマンドラインかにかかわらず、gcloud redis instances list --region REGION
コマンドを使用すると、そのインスタンスが使用可能で、使用できる状態かどうかを確認できます。
以下に、リージョン us-central1
のインスタンスを確認するコマンドと、作成したインスタンスを示す出力結果を示します。
$ gcloud redis instances list --region us-central1 INSTANCE_NAME VERSION REGION TIER SIZE_GB HOST PORT NETWORK RESERVED_IP STATUS CREATE_TIME demo-ms REDIS_5_0 us-central1 BASIC 1 10.aa.bb.cc 6379 default 10.aa.bb.dd/29 READY 2022-01-28T09:24:45
インスタンス情報やアプリの構成を求められたら、RESERVED_IP
ではなく HOST
と PORT
を使用します。Cloud コンソールの Cloud Memorystore ダッシュボードにそのインスタンスが表示されます。
Compute Engine 仮想マシンから
Compute Engine 仮想マシン(VM)がある場合は、VM から Memorystore インスタンスに直接コマンドを送信して動作を確認することもできます。VM を使用すると、すでに使用しているリソースに関係なく、関連する費用が発生する可能性があります。
サーバーレス VPC アクセス コネクタを作成する
Cloud Memorystore と同様に、サーバーレス Cloud VPC コネクタは Cloud コンソールまたはコマンドラインで作成できます。同様に、Cloud VPC には無料枠がないため、Codelab を完了するために割り当てるリソースの量は最小限にすることをおすすめします。費用を最小限に抑えるには、以下の設定で実現できます。
- インスタンスの最大数として最小を選択します。3(コンソールと
gcloud
のデフォルト: 10) - 最も低コストのマシンタイプ
f1-micro
を選択します(コンソールのデフォルト:e2-micro
、gcloud
のデフォルトなし)
次のセクションでは、上記の Cloud VPC 設定を使用して Cloud コンソールからコネクタを作成する手順を説明します。コマンドラインから行う場合は、次のセクションに進んでください。
Cloud コンソールから
[クラウド ネットワーキング] の [サーバーレス VPC アクセス] に移動します。] ページをクリックします(お支払い情報の入力を求められる場合があります)。API をまだ有効にしていない場合は、有効にするよう求められます。
API を有効にすると(場合によっては課金も同時に)、作成されたすべての VPC コネクタを示すダッシュボードが表示されます。以下のスクリーンショットで使用されているプロジェクトには何もないため、[No rows to display] と表示されます。コンソールで、上部にある [コネクタを作成] をクリックします。
必要な設定でフォームに入力します。
独自のアプリケーションに適した設定を選択します。このチュートリアルと、必要最小限のサンプルアプリを使用するサンプルアプリでは、費用を最小限に抑えるのが合理的であるため、前述の推奨事項に従ってください。設定が完了したら、[作成] をクリックします。VPC コネクタの要求が完了するまでに数分かかります。
コマンドラインから
VPC コネクタを作成する前に、まずサーバーレス VPC アクセス API を有効にします。次のコマンドを実行すると、次のような出力が表示されます。
$ gcloud services enable vpcaccess.googleapis.com Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.
API を有効にすると、次のようなコマンドで VPC コネクタが作成されます。
gcloud compute networks vpc-access connectors create CONNECTOR_NAME \ --range 10.8.0.0/28 --region REGION --project PROJECT_ID
コネクタの名前と、未使用の /28
CIDR ブロックの開始 IP アドレスを選択します。このチュートリアルでは、次のことを前提としています。
- プロジェクト ID:
my-project
- VPC コネクタ名:
demo-vpc
- 最小インスタンス数: 2(デフォルト)、最大インスタンス数: 3
- インスタンスのタイプ:
f1-micro
- リージョン:
us-central1
- IPv4 CIDR ブロック:
10.8.0.0/28
(Cloud コンソールで推奨)
上記の前提を念頭に置いて次のコマンドを実行すると、次のような出力が表示されます。
$ gcloud compute networks vpc-access connectors create demo-vpc \ --max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \ --region us-central1 --project my-project Create request issued for: [demo-vpc] Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done. Created connector [demo-vpc].
上記のコマンドでは、最小インスタンス数 2 やネットワーク default
などのデフォルト値の指定が省略されています。VPC コネクタの作成が完了するまでに数分かかります。
コネクタが作成されたことを確認する
プロセスが完了したら、次の gcloud
コマンドを発行します。リージョンは us-central1
であると仮定して、作成されて使用できる状態であることを確認します。
$ gcloud compute networks vpc-access connectors list --region us-central1 CONNECTOR_ID REGION NETWORK IP_CIDR_RANGE SUBNET SUBNET_PROJECT MIN_THROUGHPUT MAX_THROUGHPUT STATE demo-vpc us-central1 default 10.8.0.0/28 200 300 READY
同様に、先ほど作成したコネクタがダッシュボードに表示されます。
Cloud プロジェクト ID、VPC コネクタ名、リージョンをメモします。
必要な追加の Cloud リソースをコマンドラインまたはコンソールで作成できたので、次に、それらのリソースを使用できるようにアプリケーション構成を更新します。
5. 構成ファイルを更新する
最初のステップは、構成ファイルに対して必要なすべての更新を行うことです。この Codelab の主な目的は Python 2 ユーザーの移行を支援することですが、その後に続く各セクションには、Python 3 へのさらなる移植に関する情報が記載されています。
requirements.txt
このセクションでは、Cloud Memorystore と Cloud NDB をサポートするパッケージを追加します。Cloud Memorystore for Redis の場合は、Cloud Memorystore クライアント ライブラリ自体は存在しないため、標準の Python 用 Redis クライアント(redis
)を使用するだけで十分です。redis
と google-cloud-ndb
の両方を requirements.txt
に追加し、モジュール 12 の flask
を結合します。
flask
redis
google-cloud-ndb
この requirements.txt
ファイルにはバージョン番号がありません。つまり、最新バージョンが選択されます。互換性の問題がある場合は、バージョン番号を指定して作業中のバージョンをロックします。
app.yaml
追加する新しいセクション
Python 2 App Engine ランタイムで Cloud NDB などの Cloud APIs を使用する場合、特定のサードパーティ パッケージ(grpcio
と setuptools
)が必要になります。Python 2 ユーザーは、このような組み込みライブラリを、app.yaml
の利用可能なバージョンとともにリストする必要があります。libraries
セクションがまだない場合は、次のように 1 つ作成して両方のライブラリを追加します。
libraries:
- name: grpcio
version: latest
- name: setuptools
version: latest
アプリを移行するときに、すでに libraries
セクションが含まれている場合があります。存在する場合で、grpcio
と setuptools
のいずれかがない場合は、既存の libraries
セクションに追加します。
次に、サンプルアプリで Cloud Memorystore インスタンスと VPC コネクタの情報が必要になるため、使用している Python ランタイムに関係なく、次の 2 つの新しいセクションを app.yaml
に追加します。
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
必要なアップデートについては以上です。更新された app.yaml
は次のようになります。
runtime: python27
threadsafe: yes
api_version: 1
handlers:
- url: /.*
script: main.app
libraries:
- name: grpcio
version: 1.0.0
- name: setuptools
version: 36.6.0
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
以下は「導入前と導入後」のapp.yaml
に適用する必要がある更新を示します。
*Python 3 の違い
このセクションは、Python 3 に移植する場合にのみ省略できます。そのためには、Python 2 の構成にいくつかの変更を加える必要があります。現時点でアップグレードしない場合は、このセクションをスキップしてください。
Python 3 ランタイムでは、threadsafe
も api_version
も使用されていないため、どちらの設定も削除します。最新の App Engine ランタイムでは、組み込みサードパーティ ライブラリと組み込みでないライブラリのコピーはサポートされていません。サードパーティ パッケージの唯一の要件は、パッケージを requirements.txt
にリストすることです。その結果、app.yaml
の libraries
セクション全体が削除される可能性があります。
次に、Python 3 ランタイムでは、独自のルーティングを行うウェブ フレームワークを使用する必要があります。そのため、モジュール 1 で webp2 から Flask に移行する方法をデベロッパーに説明しました。そのため、すべてのスクリプト ハンドラを auto
に変更する必要があります。このアプリは静的ファイルを提供しないため、「ポイントレス」です。ハンドラをリスト表示する(すべて auto
であるため)ため、handlers
セクション全体も削除できます。そのため、Python 3 用に調整した新しい app.yaml
の短縮形は、次のように短縮する必要があります。
runtime: python39
env_variables:
REDIS_HOST: 'YOUR_REDIS_HOST'
REDIS_PORT: 'YOUR_REDIS_PORT'
vpc_access_connector:
name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR
Python 3 に移植する際の app.yaml
の違いをまとめます。
threadsafe
とapi_version
の設定の削除libraries
セクションを削除handlers
セクションを削除(アプリが静的ファイルを提供する場合はscript
ハンドラのみ)
値を置換する
Memorystore と VPC コネクタの新しいセクションの値は、単なるプレースホルダです。大文字で表記された値(YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME
)は、以前にリソースを作成したときに保存した値に置き換えます。Memorystore インスタンスについては、(RESERVED_IP
ではなく)HOST
と PORT
を使用してください。インスタンス名が demo-ms
、REGION
が us-central1
であると仮定して、HOST
と PORT
を取得する簡単なコマンドライン方法を示します。
$ gcloud redis instances describe demo-ms --region us-central1 \ --format "value(host,port)" 10.251.161.51 6379
この例の Redis インスタンスの IP アドレスが 10.10.10.10
で、リージョン us-central1
にあるプロジェクト my-project
でポート 6379
を使用し、VPC コネクタ名 demo-vpc
がある場合、app.yaml
のこれらのセクションは次のようになります。
env_variables:
REDIS_HOST: '10.10.10.10'
REDIS_PORT: '6379'
vpc_access_connector:
name: projects/my-project/locations/us-central1/connectors/demo-vpc
appengine_config.py を作成または更新する
組み込みサードパーティ ライブラリのサポートを追加する
先ほど app.yaml
で行ったように、grpcio
ライブラリと setuptools
ライブラリの使用を追加します。組み込みサードパーティ ライブラリをサポートするように appengine_config.py
を変更します。App Engine ndb
から Cloud NDB に移行する際にモジュール 2 でも必要だったからです。厳密に必要な変更は、setuptools.pkg_resources
ワーキング セットに lib
フォルダを追加することです。
*Python 3 の違い
このセクションは、Python 3 に移植する場合にのみ省略できます。App Engine の第 2 世代で歓迎される変更点の一つは、(非組み込み)サードパーティ パッケージのコピー(ベンダリング)と app.yaml
での組み込みサードパーティ パッケージの参照が不要になることです。つまり、appengine_config.py
ファイル全体を削除できるようになります。
6. アプリケーション ファイルを更新する
アプリケーション ファイルは main.py
という 1 つしかないため、このセクションで行った変更はすべてそのファイルにのみ影響します。このアプリケーションを Cloud Memorystore に移行するために行う変更については、図で示しています。これは説明のみを目的としたものであり、詳細に分析するためのものではありません。作業はすべて、コードに加える変更によって行われます。
これらのセクションを上から順番に説明していきましょう。
インポートを更新する
モジュール 12 の main.py
のインポート セクションでは、Cloud NDB と Cloud Tasks を使用します。以下がインポートです。
変更前:
from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb
Memorystore に切り替えるには、環境変数を読み取る必要があります。つまり、Python os
モジュールと、Python Redis クライアントである redis
が必要です。Redis は Python オブジェクトをキャッシュに保存できないため、pickle
を使用して最新の訪問リストをマーシャリングし、それもインポートします。Memcache の利点の一つは、オブジェクトのシリアル化が自動的に行われるのに対し、Memorystore はもう少し「DIY」である点です。最後に、google.appengine.ext.ndb
を google.cloud.ndb
に置き換えて、App Engine ndb
から Cloud NDB にアップグレードします。これらの変更を行うと、インポートは次のようになります。
変更後:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
初期化の更新
モジュール 12 の初期化では、Flask アプリケーション オブジェクト app
をインスタンス化し、1 時間分のキャッシュ保存用の定数を設定します。
変更前:
app = Flask(__name__)
HOUR = 3600
Cloud APIs を使用するにはクライアントが必要であるため、Flask の直後に Cloud NDB クライアントをインスタンス化します。次に、app.yaml
で設定した環境変数から Memorystore インスタンスの IP アドレスとポート番号を取得します。この情報を使って、Redis クライアントをインスタンス化します。これらの更新後のコードは次のようになります。
変更後:
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
*Python 3 の移行
Python 3 バージョンの Module 12 アプリから始める場合は、このセクションは省略可能です。その場合、インポートと初期化に関連して必要な変更がいくつかあります。
まず、Memcache は App Engine のバンドル サービスであるため、Python 3 アプリで使用するには、WSGI アプリケーション(およびその他の必要な構成)をラップする App Engine SDK が必要になります。
変更前:
from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb
app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600
今回は Memcache のような App Engine バンドル サービスではなく Cloud Memorystore に移行するため、SDK の使用を削除する必要があります。memcache
と wrap_wsgi_app
の両方をインポートする行全体を削除するだけなので、処理は簡単です。wrap_wsgi_app()
を呼び出す行も削除します。これらの更新により、アプリのこの部分(実際にはアプリ全体)は Python 2 バージョンと同じになります。
変更後:
import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis
app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)
最後に、app.yaml
(app_engine_apis: true
行を削除)と requirements.txt
(appengine-python-standard
行を削除)から SDK の使用を削除します。
Cloud Memorystore(および Cloud NDB)に移行する
Cloud NDB のデータモデルは、App Engine の ndb
と互換性があるように設計されています。つまり、Visit
オブジェクトの定義は変わりません。モジュール 2 の Cloud NDB への移行を模倣して、store_visit()
と fetch_visits()
のすべての Datastore 呼び出しが拡張され、新しい with
ブロックに埋め込まれます(Cloud NDB コンテキスト マネージャーの使用が必要な場合)。変更前の呼び出しは次のとおりです。
変更前:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
return Visit.query().order(-Visit.timestamp).fetch(limit)
両方の関数に with ds_client.context()
ブロックを追加し、内部に Datastore の呼び出しを配置します(インデントします)。この場合、呼び出し自体を変更する必要はありません。
変更後:
def store_visit(remote_addr, user_agent):
'create new Visit entity in Datastore'
with ds_client.context():
Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()
def fetch_visits(limit):
'get most recent visits'
with ds_client.context():
return Visit.query().order(-Visit.timestamp).fetch(limit)
次に、キャッシュの変更を見てみましょう。モジュール 12 の main()
関数は次のとおりです。
変更前:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
visits = memcache.get('visits')
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
memcache.set('visits', visits, HOUR) # set() not add()
return render_template('index.html', visits=visits)
Redis には「set」呼び出すことができます。それぞれのクライアント ライブラリを入れ替えるだけですよね?ほぼ正確です。前述のように、Python リストを Redis でキャッシュに保存することはできません(最初にシリアル化する必要があるため、Memcache が自動的に処理します)。そのため、set()
呼び出しで「pickle」を実行します。アクセスを pickle.dumps()
の文字列に変換します。同様に、キャッシュから訪問を取得する場合は、get()
の直後に pickle.loads()
で選択を解除する必要があります。これらの変更を実装した後のメインハンドラは次のとおりです。
変更後:
@app.route('/')
def root():
'main application (GET) handler'
# check for (hour-)cached visits
ip_addr, usr_agt = request.remote_addr, request.user_agent
visitor = '{}: {}'.format(ip_addr, usr_agt)
rsp = REDIS.get('visits')
visits = pickle.loads(rsp) if rsp else None
# register visit & run DB query if cache empty or new visitor
if not visits or visits[0].visitor != visitor:
store_visit(ip_addr, usr_agt)
visits = list(fetch_visits(10))
REDIS.set('visits', pickle.dumps(visits), ex=HOUR)
return render_template('index.html', visits=visits)
これで、サンプルアプリでの Memcache の使用を Cloud Memorystore に変換する main.py
で必要な変更は完了です。HTML テンプレートと Python 3 への移植についてはどうですか?
HTML テンプレート ファイルを更新し、ポートを Python 3 に変更しますか?
サプライズ!このアプリケーションは Python 2 と Python 3 の両方で動作するように設計されているため、コードの変更も互換性ライブラリも必要ありません。main.py
が表示されます。mod13a
(2.x)と mod13b
(3.x)の「FINISH」で同一です。できます。バージョン番号の違い(使用されている場合)以外は、requirements.txt
についても同様です。ユーザー インターフェースは変更されていないため、templates/index.html
も更新されていません。
Python 3 App Engine でこのアプリを Python 3 で実行するために必要な作業はすべて、以前の構成で完了しています。不要なディレクティブを app.yaml
から削除し、appengine_config.py
フォルダと lib
フォルダは Python 3 では使用されていないため削除しました。
7. 概要/クリーンアップ
このセクションでは、この Codelab の締めくくりとして、アプリをデプロイし、意図したとおりに動作することを確認し、反映された出力を確認します。アプリの検証後、クリーンアップを行い、次のステップを検討します。
アプリケーションのデプロイと検証
最後のチェックは常にサンプルアプリのデプロイです。Python 2 の場合: 以下のコマンドで、lib
を削除して再インストールします。(システムに Python 2 と Python 3 の両方がインストールされている場合は、代わりに pip2
を明示的に実行する必要があります)。
rm -rf ./lib pip install -t lib -r requirements.txt
Python 2 と Python 3 のデベロッパーは、どちらも以下を使用してアプリをデプロイする必要があります。
gcloud app deploy
内部ですべてを再構築してまったく別のキャッシュ サービスにするだけなので、アプリ自体はモジュール 12 アプリとまったく同じように動作するはずです。
これで Codelab は終了です。更新したサンプルアプリを、モジュール 13 のフォルダ mod13a
(Python 2)または mod13b
(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 に固有のものです。詳細については、各プロダクトのドキュメントをご覧ください。
- Cloud Memorystore にはインスタンスが必要ですが、無料枠はありません。使用料金の詳細については、料金ページをご覧ください。
- Cloud サーバーレス VPC アクセス コネクタにはインスタンスが必要ですが、無料枠はありません。使用料金の詳細については、Cloud VPC 料金ページの該当セクションをご覧ください。
- Cloud Datastore(Datastore モードの Cloud Firestore)には無料枠があります。詳しくは料金ページをご覧ください。
このチュートリアルでは、次の 4 つの Cloud プロダクトを使用しました。
- App Engine
- Cloud Datastore
- Cloud Memorystore
- Cloud VPC
以下に、これらのリソースを解放し、課金を回避または最小限にするための手順を示します。
Memorystore インスタンスと VPC コネクタをシャットダウンする
これらは無料枠がないプロダクトであるため、現時点でご請求が発生しています。Cloud プロジェクトをシャットダウンしない場合(次のセクションを参照)、Memorystore インスタンスと VPC コネクタの両方を削除して課金を停止する必要があります。これらのリソースを作成したときと同様に、Cloud コンソールまたはコマンドラインから解放することもできます。
Cloud コンソールから
Memorystore インスタンスを削除するには、Memorystore ダッシュボードに戻り、インスタンス ID をクリックします。
インスタンスの詳細ページが表示されたら、[削除] をクリックします。確認します。
VPC コネクタを削除するには、そのダッシュボードに移動し、削除するコネクタの横にあるチェックボックスをオンにしてから [削除] をクリックします。確認します。
コマンドラインから
次の gcloud
コマンドのペアは、Memorystore インスタンスと VPC コネクタの両方をそれぞれ削除します。
gcloud redis instances delete INSTANCE --region REGION
gcloud compute networks vpc-access connectors delete CONNECTOR --region REGION
プロジェクト ID を gcloud config set project
で設定していない場合は、--project PROJECT_ID
の指定が必要になることがあります。Memorystore インスタンスの名前が demo-ms
で、demo-vpc
という VPC コネクタがあり、どちらもリージョン us-central1
にある場合、次のコマンドペアを発行して確認します。
$ gcloud redis instances delete demo-ms --region us-central1 You are about to delete instance [demo-ms] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-ms] Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done. Deleted instance [demo-ms]. $ $ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1 You are about to delete connector [demo-vpc] in [us-central1]. Any associated data will be lost. Do you want to continue (Y/n)? Delete request issued for: [demo-vpc] Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done. Deleted connector [demo-vpc].
各リクエストの実行には数分かかります。前述のように Cloud プロジェクト全体をシャットダウンする場合、これらの手順は省略可能ですが、シャットダウン プロセスが完了するまでは料金が発生します。
次のステップ
このチュートリアル以外にも、以前のバンドル サービスからの移行に重点を置いた他の移行モジュールを以下に示します。
- モジュール 2: App Engine
ndb
から Cloud NDB に移行する - モジュール 7 ~ 9: App Engine タスクキューの push タスクから Cloud Tasks への移行
- モジュール 12 ~ 13: App Engine Memcache から Cloud Memorystore への移行
- モジュール 15 ~ 16: App Engine Blobstore から Cloud Storage への移行
- モジュール 18 ~ 19: App Engine タスクキュー(pull タスク)から Cloud Pub/Sub への移行
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
には、検討すべき移行や関連する「順序」に関するガイダンスも用意されています。概要をまとめたものです
8. 参考情報
以下に、本モジュールや関連する移行モジュールと関連プロダクトについて詳しく学ぶデベロッパー向けの追加リソースを示します。これには、このコンテンツに関するフィードバックを提供する場所、コードへのリンク、役立つさまざまなドキュメントが含まれます。
Codelab の問題/フィードバック
この Codelab に問題が見つかった場合は、提出する前にまず問題を検索してください。新しい問題の検索と登録を行うためのリンク:
移行に関するリソース
以下の表に、モジュール 12(START)とモジュール 13(FINISH)のリポジトリ フォルダへのリンクを示します。これらは、すべての App Engine Codelab 移行用のリポジトリからもアクセスでき、ZIP ファイルのクローンを作成したりダウンロードしたりできます。
Codelab | Python 2 | Python 3 |
モジュール 13(この Codelab) |
オンライン リファレンス
このチュートリアルに関連する可能性のあるオンライン リソースは次のとおりです。
App Engine
- App Engine ドキュメント
- Python 2 App Engine(スタンダード環境)ランタイム
- App Engine の Python 2 組み込みライブラリで Python 2 を使用する
- Python 3 App Engine(スタンダード環境)ランタイム
- Python 2 と3 つの App Engine(スタンダード環境)ランタイム
- Python 2 から 3 への App Engine(スタンダード環境)の移行ガイド
- App Engine の料金と割り当てに関する情報
App Engine NDB と Cloud NDB
- App Engine NDB の概要
- App Engine NDB Datastore の使用量
- Google Cloud NDB のドキュメント
- Google Cloud NDB リポジトリ
- Cloud Datastore の料金情報
App Engine Memcache と Cloud Memorystore
- App Engine Memcache の概要
- Python 2 App Engine
memcache
リファレンス - Python 3 App Engine
memcache
リファレンス - App Engine
memcache
から Cloud Memorystore への移行ガイド - Cloud Memorystore のドキュメント
- Cloud Memorystore for Redis のドキュメント
- Cloud Memorystore for Redis の料金情報
- Cloud Memorystore でサポートされている Redis のバージョン
- Cloud Memorystore ホームページ
- Cloud コンソールで新しい Memorystore インスタンスを作成する
- Python Redis クライアントのホームページ
- Python Redis クライアント ライブラリのドキュメント
Cloud VPC
- Google Cloud VPC のドキュメント
- Google Cloud VPC ホームページ
- Cloud VPC の料金情報
- Cloud コンソールで新しいサーバーレス VPC アクセス コネクタを作成する
Cloud のその他の情報
- Google Cloud Platform での Python
- Google Cloud Python クライアント ライブラリ
- Google Cloud「Always Free」ティア
- Google Cloud SDK(
gcloud
コマンドライン ツール) - Google Cloud に関するすべてのドキュメント
ライセンス
この作業はクリエイティブ・コモンズの表示 2.0 汎用ライセンスにより使用許諾されています。