1. はじめに
Eventarc を使用すると、さまざまなソースのイベントと Cloud Run サービスを簡単に接続できます。マイクロサービスが疎結合かつ分散されたイベント ドリブン アーキテクチャを構築できます。イベントの取り込み、配信、セキュリティ、認可、エラー処理を自動的に行います。
Workflows はフルマネージドのオーケストレーション プラットフォームで、定義した順序(ワークフロー)でサービスを実行します。これらのワークフローでは、Cloud Run や Cloud Functions でホストされているサービス、Cloud Vision AI や BigQuery などの Google Cloud サービス、任意の HTTP ベースの API を組み合わせることができます。
この Codelab では、画像を処理するマイクロサービスのイベント ドリブン オーケストレーションを構築します。Workflows を使用して、4 つの画像処理 Cloud Functions の順序、入力、出力をオーケストレートします。その後、オーケストレーションと、Eventarc との疎結合で Cloud Storage イベントに応答できるようにします。
最終的には、画像を処理するための柔軟かつ構造化されたサーバーレス アーキテクチャが完成します。
学習内容
- Eventarc と Workflows の概要
- Cloud Functions サービスをデプロイする方法
- Workflows を使用してサービスをオーケストレートする方法
- Eventarc を使用して Workflows が Cloud Storage イベントに応答する方法
2. 設定と要件
セルフペース型の環境設定
- Google Cloud Console にログインして、プロジェクトを新規作成するか、既存のプロジェクトを再利用します。Gmail アカウントも Google Workspace アカウントもまだお持ちでない場合は、アカウントを作成してください。
- プロジェクト名は、このプロジェクトの参加者に表示される名称です。Google API では使用されない文字列です。この値はいつでも更新できます。
- プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、不変です(設定後は変更できません)。Cloud コンソールでは一意の文字列が自動生成されます。通常、それが何であるかは関係ありません。ほとんどの Codelab では、プロジェクト ID を参照する必要があります(通常は
PROJECT_ID
として識別されます)。生成された ID が気に入らない場合は、別のランダムな ID を生成できます。または、ご自身でお試しになることもできます。このステップを終えた後は変更できず、プロジェクト期間中は維持されます。 - なお、3 つ目の値は、一部の API で使用される [プロジェクト番号] です。これら 3 つの値について詳しくは、こちらのドキュメントをご覧ください。
- 次に、Cloud のリソースや API を使用するために、Cloud コンソールで課金を有効にする必要があります。この Codelab の操作をすべて行って、費用が生じたとしても、少額です。このチュートリアルの終了後に課金が発生しないようにリソースをシャットダウンするには、作成したリソースを削除するか、プロジェクト全体を削除します。Google Cloud の新規ユーザーは、300 米ドル分の無料トライアル プログラムをご利用いただけます。
Cloud Shell の起動
Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
Google Cloud Console で、右上のツールバーにある Cloud Shell アイコンをクリックします。
プロビジョニングと環境への接続にはそれほど時間はかかりません。完了すると、次のように表示されます。
この仮想マシンには、必要な開発ツールがすべて用意されています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働します。そのため、ネットワークのパフォーマンスと認証機能が大幅に向上しています。この Codelab での作業はすべて、ブラウザ内から実行できます。インストールは不要です。
gcloud を設定する
Cloud Shell で、プロジェクト ID とアプリケーションのデプロイ先のリージョンを設定します。これらの情報は、PROJECT_ID
変数と REGION
変数として保存します。使用可能なリージョンについては、Cloud Functions のロケーションをご覧ください。
PROJECT_ID=your-project-id gcloud config set project $PROJECT_ID
ソースコードを取得する
アプリケーションのソースコードは、eventarc-samples リポジトリの processing-pipelines
フォルダにあります。
リポジトリのクローンを作成します。
git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git
eventarc-samples/processing-pipelines
フォルダに移動します。
cd eventarc-samples/processing-pipelines
3. アーキテクチャの概要
アプリケーションのアーキテクチャは次のとおりです。
- 画像が入力バケットに保存され、Cloud Storage create イベントが生成されます。
- Cloud Storage の作成イベントは、Cloud Storage トリガーを介して Eventarc によって読み取られ、CloudEvent として Workflows に渡されます。
- ワークフローの最初のステップでは、Cloud Functions の関数サービスの Filter が Vision API を使用して画像が安全かどうかを判断します。イメージが安全な場合、Workflows は次のステップに進みます。
- ワークフローの 2 番目のステップでは、Labeler(Cloud Functions の関数サービス)が Vision API で画像のラベルを抽出し、出力バケットに保存します。
- 3 番目のステップである Resizer(別の Cloud Functions 関数サービス)が ImageSharp を使用して画像のサイズを変更し、サイズ変更した画像を出力バケットに保存します。
- 最後のステップでは、別の Cloud Function サービスである Watermarker が、ImageSharp を使用してサイズ変更した画像にラベラーからのラベルの透かしを追加し、画像を出力バケットに保存します。
このアプリケーションは Cloud Storage イベントによってトリガーされるため、イベント ドリブンです。画像の処理はワークフロー内で行われるため、これはオーケストレーションです。結局のところ、柔軟で構造化されたサーバーレス アーキテクチャによる画像処理のためのイベント ドリブンなオーケストレーションです。
4. バケットを作成する
ユーザーが画像をアップロードする入力バケットと、画像処理パイプラインで処理された画像を保存する出力バケットを作成します。
Cloud Shell で次のコマンドを実行します。
REGION=us-central1 BUCKET1=$PROJECT_ID-images-input BUCKET2=$PROJECT_ID-images-output gsutil mb -l $REGION gs://$BUCKET1 gsutil mb -l $REGION gs://$BUCKET2
5. フィルタ サービスをデプロイする
まず、1 つ目のサービスをデプロイします。この Cloud Functions サービスはバケットとファイルの情報を受け取り、画像が Vision API で安全かどうかを判断して結果を返します。
まず、Cloud Functions gen2 と Vision API に必要なサービスを有効にします。
gcloud services enable \ artifactregistry.googleapis.com \ cloudbuild.googleapis.com \ cloudfunctions.googleapis.com \ run.googleapis.com \ vision.googleapis.com
最上位の processing-pipelines
フォルダ内で、サービスをデプロイします。
SERVICE_NAME=filter gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --entry-point Filter.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v3/filter/csharp
関数をデプロイしたら、サービス URL を変数に設定します。これは後で必要になります。
FILTER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
6. ラベラー サービスをデプロイする
2 つ目の Cloud Functions サービスはバケットとファイルの情報を受け取り、Vision API で画像のラベルを抽出して出力バケットに保存します。
最上位の processing-pipelines
フォルダ内で、サービスをデプロイします。
SERVICE_NAME=labeler gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Labeler.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/labeler/csharp
関数をデプロイしたら、サービス URL を変数に設定します。これは後で必要になります。
LABELER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
7. サイズ変更サービスをデプロイする
この Cloud Functions サービスは、バケットとファイルの情報を受け取り、ImageSharp を使用して画像のサイズを変更し、出力バケットに画像を保存します。
最上位の processing-pipelines
フォルダ内で、サービスをデプロイします。
SERVICE_NAME=resizer gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Resizer.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/resizer/csharp \ --timeout=120s
timeout
の値が 2 分になっているため、リサイザ関数の処理時間が長くなります。
関数をデプロイしたら、サービス URL を変数に設定します。これは後で必要になります。
RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
8. 透かしサービスをデプロイする
この Cloud Functions サービスは、バケット、ファイル、ラベルの情報を受け取り、ファイルを読み取り、ImageSharp を使用してラベルを透かしとして画像に追加し、画像を出力バケットに保存します。
最上位の processing-pipelines
フォルダ内で、サービスをデプロイします。
SERVICE_NAME=watermarker gcloud functions deploy $SERVICE_NAME \ --gen2 \ --allow-unauthenticated \ --runtime dotnet3 \ --trigger-http \ --region=$REGION \ --set-env-vars BUCKET=$BUCKET2 \ --entry-point Watermarker.Function \ --set-build-env-vars GOOGLE_BUILDABLE=image-v2/watermarker/csharp
関数をデプロイしたら、サービス URL を変数に設定します。これは後で必要になります。
WATERMARKER_URL=$(gcloud functions describe $SERVICE_NAME --region=$REGION --gen2 --format 'value(serviceConfig.uri)')
この時点で、4 つの Cloud Functions の関数がすべてデプロイされ、実行されているはずです。
9. ワークフローの定義とデプロイ
Workflows を使用すると、フィルタ、ラベル付け、サイズ変更、透かしのサービスを 1 つのワークフローにまとめることができます。Workflows は、定義したパラメータを使用して、これらのサービスの呼び出しをオーケストレートします。
まず、Workflows に必要なサービスを有効にします。
gcloud services enable \ workflows.googleapis.com \ workflowexecutions.googleapis.com
定義
Workflows は、パラメータとして CloudEvent を受け取ります。トリガーを作成すると、Eventarc から取得されます。最初の 2 つのステップでは、Workflows がイベントをログに記録し、そのイベントからバケットとファイルの情報を抽出します。
main: params: [event] steps: - log_event: call: sys.log args: text: ${event} severity: INFO - extract_bucket_and_file: assign: - bucket: ${event.data.bucket} - file: ${event.data.name}
filter
ステップで、Workflows は前にデプロイしたフィルタ サービスを呼び出します。次に、ファイルの安全性をログに記録してチェックします。
- filter: call: http.post args: url: FILTER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: filterResponse - log_safety: call: sys.log args: text: ${filterResponse.body.safe} severity: INFO - check_safety: switch: - condition: ${filterResponse.body.safe == true} next: label next: end
label
ステップで、Workflows はラベラー サービスを呼び出し、レスポンスをキャプチャします(上位 3 つのラベル)。
- label: call: http.post args: url: LABELER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: labelResponse
resize
ステップで、Workflows はサイズ変更サービス サービスを呼び出し、レスポンス(サイズ変更された画像のバケットとファイル)をキャプチャします。
- resize: call: http.post args: url: RESIZER_URL # TODO: Replace auth: type: OIDC body: bucket: ${bucket} file: ${file} result: resizeResponse
watermark
ステップで、Workflows はサイズ変更された画像とラベルを使用して透かしサービスを呼び出し、結果(サイズ変更され透かしを入れた画像)をキャプチャします。
- watermark: call: http.post args: url: WATERMARKER_URL # TODO: Replace auth: type: OIDC body: bucket: ${resizeResponse.body.bucket} file: ${resizeResponse.body.file} labels: ${labelResponse.body.labels} result: watermarkResponse
final
ステップで、Workflows はラベラー、サイズ変更ツール、ウォーターマーク サービスから HTTP ステータス コードを返します。
- final: return: label: ${labelResponse.code} resize: ${resizeResponse.code} watermark: ${watermarkResponse.code}
デプロイ
ワークフローをデプロイする前に、手動または sed
を使用して、サービス URL がデプロイされた関数の URL に置き換えられていることを確認します。
最上位の processing-pipelines
フォルダ内で、workflows.yaml
ファイルが保存されている image-v3
フォルダに移動します。
cd image-v3/
sed
を実行して、プレースホルダの URL を、デプロイされたサービスの実際の URL に置き換えます。
sed -i -e "s|FILTER_URL|${FILTER_URL}|" workflow.yaml sed -i -e "s|LABELER_URL|${LABELER_URL}|" workflow.yaml sed -i -e "s|RESIZER_URL|${RESIZER_URL}|" workflow.yaml sed -i -e "s|WATERMARKER_URL|${WATERMARKER_URL}|" workflow.yaml
ワークフローをデプロイします。
WORKFLOW_NAME=image-processing gcloud workflows deploy $WORKFLOW_NAME \ --source=workflow.yaml \ --location=$REGION
数秒後に、ワークフローがコンソールにデプロイされていることを確認します。
10. トリガーを作成
ワークフローがデプロイされたので、最後のステップとして、Eventarc トリガーを使用してワークフローを Cloud Storage イベントに接続します。
1 回限りの設定
まず、Eventarc に必要なサービスを有効にします。
gcloud services enable \ eventarc.googleapis.com
Eventarc トリガーで使用するサービス アカウントを作成します。
SERVICE_ACCOUNT=eventarc-trigger-imageproc-sa gcloud iam service-accounts create $SERVICE_ACCOUNT \ --display-name="Eventarc trigger image processing service account"
サービス アカウントを使用して Eventarc から Workflows を呼び出せるように、workflows.invoker
ロールを付与します。
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/workflows.invoker \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
eventarc.eventReceiver
ロールを付与すると、サービス アカウントを
Cloud Storage トリガー:
gcloud projects add-iam-policy-binding $PROJECT_ID \ --role roles/eventarc.eventReceiver \ --member serviceAccount:$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
Cloud Storage サービス アカウントに pubsub.publisher
ロールを付与します。これは、Eventarc の Cloud Storage トリガーに必要です。
STORAGE_SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_ID)" gcloud projects add-iam-policy-binding $PROJECT_ID \ --member serviceAccount:$STORAGE_SERVICE_ACCOUNT \ --role roles/pubsub.publisher
作成
次のコマンドを実行してトリガーを作成します。このトリガーは、入力 Cloud Storage バケットからの新しいファイル作成イベントをフィルタし、前に定義したワークフローに渡します。
TRIGGER_NAME=trigger-image-processing gcloud eventarc triggers create $TRIGGER_NAME \ --location=$REGION \ --destination-workflow=$WORKFLOW_NAME \ --destination-workflow-location=$REGION \ --event-filters="type=google.cloud.storage.object.v1.finalized" \ --event-filters="bucket=$BUCKET1" \ --service-account=$SERVICE_ACCOUNT@$PROJECT_ID.iam.gserviceaccount.com
トリガーが作成され、準備ができたことは、Cloud コンソールの [Eventarc] セクションで確認できます。
11. パイプラインをテストする
画像処理パイプラインで、Cloud Storage からイベントを受信する準備が整いました。パイプラインをテストするために、入力バケットに画像をアップロードします。
gsutil cp beach.jpg gs://$BUCKET1
写真をアップロードするとすぐに、Workflows の実行がアクティブな状態であることが表示されます。
1 分ほど待つと、実行が成功したことがわかります。ワークフローの入力と出力も確認できます。
出力バケットの内容を一覧表示すると、サイズ変更された画像、サイズ変更され透かしが入った画像、画像のラベルが表示されます。
gsutil ls gs://$BUCKET2 gs://$PROJECT_ID-images-output/beach-400x400-watermark.jpeg gs://$PROJECT_ID-images-output/beach-400x400.png gs://$PROJECT_ID-images-output/beach-labels.txt
再確認するには、サイズを変更した透かしを入れた画像を開いて結果を確認します。
12. 完了
お疲れさまでした。これでこの Codelab は終了です。
学習した内容
- Eventarc と Workflows の概要
- Cloud Functions サービスをデプロイする方法
- Workflows を使用してサービスをオーケストレートする方法
- Eventarc を使用して Workflows が Cloud Storage イベントに応答する方法