Eventarc と Workflows を使用してイベント ドリブンなオーケストレーションを構築する

1. はじめに

cb762f29e9183a3f.png 1c05e3d0c2bd2b45.png a03f943ca09ac4c.png

Eventarc を使用すると、Cloud Run サービスをさまざまなソースのイベントに簡単に接続できます。マイクロサービスが疎結合されて分散されるイベント ドリブン アーキテクチャを構築できる。イベントの取り込み、配信、セキュリティ、認証、エラー処理は自動的に行われます。

ワークフローは、定義した順序でサービスを実行するフルマネージドのオーケストレーション プラットフォームです。つまり、ワークフローです。これらのワークフローは、Cloud Run または Cloud Functions でホストされているサービス、Cloud Vision AI や BigQuery などの Google Cloud サービス、HTTP ベースの API を組み合わせることができます。

この Codelab では、イベント ドリブンなマイクロサービスのオーケストレーションを構築し、画像を処理します。Workflows を使用して 4 つの画像処理 Cloud Functions の順序、入力、出力をオーケストレートします。次に、オーケストレーションを有効にして、Eventarc と疎結合の方法で Cloud Storage イベントに応答できるようにします。

最終的に、画像を処理するための柔軟で構造化されたサーバーレス アーキテクチャになります。

e372ceed8c26c5fb.png

学習内容

  • Eventarc と Workflows の概要
  • Cloud Functions サービスのデプロイ方法
  • Workflows を使用してサービスをオーケストレートする方法
  • Eventarc を使用して Workflows が Cloud Storage イベントに応答する方法

2. 設定と要件

クレジットを利用する

cae48e4b2e19921d.png

表示されるダイアログで、[同意して続行] ボタンをクリックして利用規約に同意します。

27D87930a0daf2f8.png

利用規約に同意すると、右下に次のようなパネルを含む [料金概略] ページにリダイレクトされます。

2076ea7aa9bf3f65.png

最後に、最初のプロジェクトを作成するときに、プロジェクトに請求先アカウントを割り当てるためのダイアログが表示されます。無料クレジットに関連付けられた請求先アカウントを選択し、[作成] ボタンをクリックします。

dd3b0e795843296.png

これで要約ができました。請求先アカウントとプロジェクトが作成され、この 2 つのエンティティがリンクされました。今日の Codelab で行った作業は、すべて無料のクレジットで賄われています**。**

セルフペース型の環境設定

  1. Google Cloud Console にログインし、新しいプロジェクトを作成するか、既存のプロジェクトを再利用します。Gmail または Google Workspace アカウントをお持ちでない場合は、アカウントを作成する必要があります。

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • [プロジェクト名] は、このプロジェクトの参加者の表示名です。Google API で使用されていない文字列で、いつでも更新できます。
  • プロジェクト ID は、すべての Google Cloud プロジェクトにおいて一意でなければならず、変更できません(設定後は変更できません)。Cloud Console で一意の文字列が自動生成されます。通常は何も重要ではありません。ほとんどの Codelab では、プロジェクト ID を参照(通常は PROJECT_ID として識別)する必要があります。気に入らない場合は、ランダムな ID を新たに生成するか、ご自身の ID で以下を確認してください。利用可能。プロジェクトの作成後は「フリーズ」されます。
  • 第 3 の値として、一部の API が使用するプロジェクト番号があります。これら 3 つの値について詳しくは、ドキュメントをご覧ください。
  1. 次に、Cloud Console で課金を有効にして、Cloud リソースや API を使用する必要があります。このコードラボを実行しても、費用はほとんどかからないはずです。このチュートリアルで課金が発生しないようにリソースをシャットダウンするには、Codelab の最後にある「クリーンアップ」の手順を行います。Google Cloud の新規ユーザーは、300 米ドルの無料トライアル プログラムをご利用いただけます。

Cloud Shell の起動

Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では Cloud で実行するコマンドライン環境である Google Cloud Shell を使用します。

Google Cloud Console で、右上のツールバーにある Cloud Shell アイコンをクリックします。

55efc1aaa7a4d3ad.png

環境がプロビジョニングされて接続されるまで、わずか数分しかかかりません。完了すると、次のように表示されます。

7ffe5cbb04455448.png

この仮想マシンには、必要な開発ツールがすべて準備されています。永続的な 5 GB のホーム ディレクトリが Google Cloud 上で動作し、ネットワーク パフォーマンスと認証が大幅に強化されます。このラボの操作はすべてブラウザを使用して行えます。

gcloud を設定する

Cloud Shell で、プロジェクト ID とアプリケーションのデプロイ先リージョンを設定します。変数は PROJECT_ID 変数と REGION 変数として保存します。利用可能なリージョンについては、Cloud Functions のロケーションをご覧ください。

PROJECT_ID=[YOUR-PROJECT-ID]
REGION=[YOUR-REGION]
gcloud config set core/project $PROJECT_ID
gcloud config set functions/region $REGION

サービスを有効化する

必要なサービスをすべて有効にします。

gcloud services enable \
  artifactregistry.googleapis.com \
  cloudbuild.googleapis.com \
  cloudfunctions.googleapis.com \
  eventarc.googleapis.com \
  vision.googleapis.com \
  workflows.googleapis.com \
  workflowexecutions.googleapis.com

ソースコードを取得する

アプリケーションのソースコードは、eventarc-samples リポジトリの processing-pipelines フォルダにあります。

リポジトリのクローン作成:

git clone https://github.com/GoogleCloudPlatform/eventarc-samples.git

eventarc-samples/processing-pipelines フォルダに移動します。

cd eventarc-samples/processing-pipelines

3. アーキテクチャの概要

アプリケーションのアーキテクチャは次のとおりです。

6aa6fbc7721dd6b6.png

  1. 画像が Cloud Storage 作成イベントを生成する入力バケットに保存されます。
  2. Cloud Storage の作成イベントは、Cloud Storage トリガーを介して Eventarc によって読み取られ、CloudEvent として Workflows に渡されます。
  3. ワークフローの最初のステップでは、Cloud Function サービスであるフィルタが、Vision API を使用して画像が安全かどうかを判断します。イメージが安全な場合、Workflows は次の手順に進みます。
  4. ワークフローの 2 番目のステップである Labeler は、Cloud Functions の関数です。Vision API を使用して画像のラベルを抽出し、出力バケットに保存します。
  5. 3 番目のステップである Resizer は、Cloud Functions の別のサービスであり、ImageSharp を使用して画像のサイズを変更し、サイズ変更後の画像を出力バケットに保存します。
  6. 最後のステップであるもう 1 つの Cloud Function サービスである Watermarker は、ImageSharp を使用して Labeler からサイズ変更された画像にラベルの透かしを追加し、出力バケットに画像を保存します。

アプリケーションは Cloud Storage イベントによってトリガーされるため、イベント ドリブンです。画像の処理はワークフロー内で行われるため、オーケストレーションとみなされます。最終的には、イベント ドリブンのオーケストレーションによる、柔軟でありながら構造化されたサーバーレス アーキテクチャによる画像処理を実現します。

4.バケットの作成

ユーザーが画像をアップロードする入力バケットと、処理された画像を保存するための画像処理パイプラインの出力バケットを作成します。

Cloud Shell で次のコマンドを実行します。

BUCKET1=$PROJECT_ID-images-input
BUCKET2=$PROJECT_ID-images-output
gsutil mb -l $REGION gs://$BUCKET1
gsutil mb -l $REGION gs://$BUCKET2

5. フィルタ サービスをデプロイする

まず、最初のサービスをデプロイします。この Cloud Functions サービスは、バケットとファイルの情報を受け取り、画像が Vision API で安全かどうかを判断して結果を返します。

最上位の processing-pipelines フォルダ内で、サービスをデプロイします。

SERVICE_NAME=filter
gcloud functions deploy $SERVICE_NAME \
  --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 --format 'value(httpsTrigger.url)')

6. ラベラー サービスのデプロイ

2 番目の Cloud Functions サービスは、バケットとファイルの情報を受信し、Vision API で画像のラベルを抽出して、出力バケットにラベルを保存します。

最上位の processing-pipelines フォルダ内で、サービスをデプロイします。

SERVICE_NAME=labeler
gcloud functions deploy $SERVICE_NAME \
  --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 --format 'value(httpsTrigger.url)')

7. サイズ変更サービスをデプロイする

この Cloud Functions サービスでは、バケットとファイルの情報を受信し、ImageSharp を使用して画像のサイズを変更して、出力バケットに画像を保存します。

最上位の processing-pipelines フォルダ内で、サービスをデプロイします。

SERVICE_NAME=resizer
gcloud functions deploy $SERVICE_NAME \
  --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

関数がデプロイされたら、後で変数にサービス URL を設定します。

RESIZER_URL=$(gcloud functions describe $SERVICE_NAME --format 'value(httpsTrigger.url)')

8. ウォーターマーカー サービスをデプロイする

この Cloud Functions サービスはバケット、ファイル、ラベルの情報を受信し、ファイルを読み取り、ImageSharp を使用してラベルを透かしとして画像に追加し、画像を出力バケットに保存します。

最上位の processing-pipelines フォルダ内で、サービスをデプロイします。

SERVICE_NAME=watermarker
gcloud functions deploy $SERVICE_NAME \
  --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 --format 'value(httpsTrigger.url)')

この時点で、4 つの Cloud Functions の関数がすべてデプロイされて実行されています。

5d7d4061e04c91bb.png

9. ワークフローを定義してデプロイする

Workflows を使用して、フィルタ、ラベル付け、リサイザ、ウォーターマーカーの各サービスを統合します。Workflows は、定義した順序でこのサービスを順番に呼び出します。

定義

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

数秒後にコンソールにワークフローがデプロイされます。

92cf4e758bdc3dde.png

10. トリガーを作成

ワークフローがデプロイされたので、最後のステップは Eventarc トリガーを使用して Cloud Storage イベントに接続することです。

1 回限りの設定

トリガーには、デフォルトのコンピューティング サービス アカウントが使用されます。eventarc.eventReceiver ロールがあることを確認します。

PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com \
    --role roles/eventarc.eventReceiver

Cloud Storage サービス アカウントに pubsub.publisher ロールを付与します。これは、Eventarc の Cloud Storage トリガーで必要になります。

SERVICE_ACCOUNT="$(gsutil kms serviceaccount -p $PROJECT_NUMBER)"

gcloud projects add-iam-policy-binding $PROJECT_NUMBER \
    --member serviceAccount:$SERVICE_ACCOUNT \
    --role roles/pubsub.publisher

作成

トリガーを作成するには、次のコマンドを実行します。このトリガーは、入力 Cloud Storage バケットから新しいファイル作成イベントをフィルタリングし、以前に定義したワークフローに渡します。

TRIGGER_NAME=trigger-$WORKFLOW_NAME
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=$PROJECT_NUMBER-compute@developer.gserviceaccount.com

トリガーが作成され、Cloud Console の Eventarc セクションで確認できます。

14330c4fa2451bc0.png

11. パイプラインをテストする

画像処理パイプラインが Cloud Storage からイベントを受信する準備ができました。パイプラインをテストするには、画像を入力バケットにアップロードします。

gsutil cp beach.jpg gs://$BUCKET1

画像をアップロードするとすぐに、Workflows の実行がアクティブ状態になるはずです。

2016-0631

約 1 分後、実行が成功するはずです。ワークフローの入力と出力も確認できます。

229200C79D989C25.PNG

出力バケットのコンテンツを一覧表示すると、サイズ変更された画像、サイズ変更された透かしの画像、画像のラベルが表示されます。

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

再確認するには、サイズ変更後の透かし画像を開いて、その結果を確認します。

75f3c0019ca842ce.jpeg

12. 完了

これで Codelab は終了です。

学習した内容

  • Eventarc と Workflows の概要
  • Cloud Functions サービスのデプロイ方法
  • Workflows を使用してサービスをオーケストレートする方法
  • Eventarc を使用して Workflows が Cloud Storage イベントに応答する方法