マイクロサービスと非同期メッセージングを使用して画像処理をデプロイする

Last reviewed 2023-07-17 UTC

このドキュメントでは、マイクロサービスを Pub/Sub および GKE と統合するで説明されているリファレンス アーキテクチャの実装方法について説明します。このアーキテクチャは、コンテナと非同期メッセージングを使用して、長時間実行プロセスを処理するように設計されています。

このドキュメントでは、写真のサムネイルを生成する写真共有アプリのサンプルを使用します。Google Kubernetes Engine(GKE)を使用してアプリケーションをデプロイし、Pub/Sub を使用して長時間実行プロセスを非同期で呼び出します。また、Cloud Storage の Pub/Sub 通知を使用して、アプリケーションのコードを変更せずにサイドジョブを追加することもできます。

アプリケーションは Cloud Build によってコンテナ化され、Artifact Registry に保存されます。Cloud Vision を使用して不適切な画像を検出します。

アーキテクチャ

次の図は、リファレンス アーキテクチャを実装するフォトアルバム アプリケーションのサンプル設計を示しています。

フォトアルバム アプリケーションのアーキテクチャ。

図 1. コンテナと非同期メッセージングの使用に基づく画像処理のアーキテクチャ。

上の図はサムネイルの生成方法を示しています。

  1. クライアントがアプリケーションに画像をアップロードします。
  2. アプリケーションは、Cloud Storage に画像を保存します。
  3. サムネイルに対してリクエストが生成されます。
  4. サムネイル生成ツールでサムネイルが生成されます。
  5. フォトアルバム アプリケーションに正常なレスポンスが送信されます。
  6. 正常なレスポンスがクライアントに送信されます。サムネイルは Cloud Storage で確認できます。

次の図は、アプリケーションがサムネイル生成を別のサービスとして非同期で実装する方法を示しています。

サムネイル抽出プロセスのアーキテクチャ。

図 2. サムネイル抽出プロセスのアーキテクチャ。

Pub/Sub を使用してサービス リクエストをサムネイル生成サービスに送信します。この新しいアーキテクチャではサービスを非同期で呼び出すため、アプリケーションがクライアントにレスポンスを返した後に、サムネイルがバックグラウンドで作成されます。また、この設計では複数のジョブを並行して実行できるように、サムネイル生成サービスのスケールができます。

目標

  • GKE にサンプルのフォトアルバム アプリケーションをデプロイします。
  • アプリケーションから非同期のサービス呼び出しを行います。
  • Cloud Storage の Pub/Sub 通知を使用して、新しいファイルが Cloud Storage バケットにアップロードされたときにアプリケーションをトリガーします。
  • Pub/Sub を使用して、アプリケーションを変更することなく、より多くのタスクを実行できます。

料金

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

サンプル アプリケーションの構築の完了後は、作成したリソースを削除すれば、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  3. Google Cloud プロジェクトで課金が有効になっていることを確認します

  4. GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision API を有効にします。

    API を有効にする

  5. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  6. Google Cloud プロジェクトで課金が有効になっていることを確認します

  7. GKE, Cloud SQL, Cloud Build, Artifact Registry, and Cloud Vision API を有効にします。

    API を有効にする

  8. Google Cloud コンソールで、「Cloud Shell をアクティブにする」をクリックします。

    Cloud Shell をアクティブにする

    Google Cloud コンソールの下部で Cloud Shell セッションが開始し、コマンドライン プロンプトが表示されます。Cloud Shell はシェル環境です。Google Cloud CLI がすでにインストールされており、現在のプロジェクトの値もすでに設定されています。セッションが初期化されるまで数秒かかることがあります。

環境を設定する

このセクションでは、ドキュメント全体で使用されるデフォルトの設定値を割り当てます。Cloud Shell セッションを閉じると、これらの環境設定は失われます。

  1. Cloud Shell で、デフォルトの Google Cloud プロジェクトを設定します。

    gcloud config set project PROJECT_ID
    

    PROJECT_ID は、実際の Google Cloud プロジェクト ID に置き換えます。

  2. デフォルトの Compute Engine リージョンを設定します。

    gcloud config set compute/region REGION
    export REGION=REGION
    

    REGION は、近くのリージョンに置き換えます。詳細については、リージョンとゾーンをご覧ください。

  3. デフォルトの Compute Engine ゾーンを設定します。

    gcloud config set compute/zone ZONE
    export ZONE=ZONE
    

    ZONE は、近くのゾーンに置き換えます。

  4. サンプル アプリケーション ファイルをダウンロードし、現在のディレクトリを設定します。

    git clone https://github.com/GoogleCloudPlatform/gke-photoalbum-example
    cd gke-photoalbum-example
    

Cloud Storage バケットを作成し、デフォルトのサムネイル画像をアップロードする

  1. Cloud Shell で、元の画像とサムネイルを保存する Cloud Storage バケットを作成します。

    export PROJECT_ID=$(gcloud config get-value project)
    gsutil mb -c regional -l ${REGION} gs://${PROJECT_ID}-photostore
    
  2. デフォルトのサムネイル ファイルをアップロードします。

    gsutil cp ./application/photoalbum/images/default.png \
        gs://${PROJECT_ID}-photostore/thumbnails/default.png
    
    • アップロードされた画像は gs://PROJECT_ID-photostore/FILENAME の形式で保存されます。ここで、FILENAME は、アップロードする画像ファイルの名前を表します。
    • 生成されたサムネイルは gs://PROJECT_ID-photostore/thumbnails/FILENAME の形式で保存されます。
    • 元の画像と対応するサムネイルの FILENAME は同じですが、サムネイルは thumbnails バケットに保存されます。
    • サムネイルの作成中は、次の default.png プレースホルダ サムネイル画像がフォトアルバム アプリケーションに表示されます。

      デフォルトのプレースホルダのサムネイル画像。

  3. サムネイル ファイルを公開します。

    gsutil acl ch -u AllUsers:R \
        gs://${PROJECT_ID}-photostore/thumbnails/default.png
    

Cloud SQL インスタンスと MySQL データベースを作成する

  1. Cloud Shell で、Cloud SQL インスタンスを作成します。

    gcloud sql instances create photoalbum-db --region=${REGION} \
        --database-version=MYSQL_8_0
    
  2. 接続名を取得します。

    gcloud sql instances describe photoalbum-db \
        --format="value(connectionName)"
    

    後で使用するため、この名前をメモしておきます。

  3. MySQL ユーザー root@% のパスワードを設定します。

    gcloud sql users set-password root --host=% --instance=photoalbum-db \
        --password=PASSWORD
    

    PASSWORDroot@% ユーザーの安全なパスワードに置き換えます。

  4. Cloud SQL インスタンスに接続します。

    gcloud sql connect photoalbum-db --user=root --quiet
    

    プロンプトが表示されたら、前の手順で設定したパスワードを入力します。

  5. photo_db という名前のデータベースを作成します。ここで、ユーザーは appuser で、パスワードは pas4appuser です。

    create database photo_db;
    create user 'appuser'@'%' identified by 'pas4appuser';
    grant all on photo_db.* to 'appuser'@'%' with grant option;
    flush privileges;
    
  6. 結果を確認して MySQL を終了します。

    show databases;
    select user from mysql.user;
    exit
    

    出力で、photo_db データベースと appuser ユーザーが作成されたことを確認します。

    mysql> show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | mysql              |
    | performance_schema |
    | photo_db           |
    | sys                |
    +--------------------+
    5 rows in set (0.16 sec)
    
    mysql> \t
    Outfile disabled.
    mysql> select user from mysql.user;
    +-------------------+
    | user              |
    +-------------------+
    | appuser           |
    | cloudsqlreplica   |
    | cloudsqlsuperuser |
    | root              |
    | cloudsqlexport    |
    | cloudsqlimport    |
    | cloudsqloneshot   |
    | root              |
    | cloudsqlexport    |
    | cloudsqlimport    |
    | cloudsqloneshot   |
    | root              |
    | cloudsqlapplier   |
    | cloudsqlimport    |
    | mysql.infoschema  |
    | mysql.session     |
    | mysql.sys         |
    | root              |
    +-------------------+
    18 rows in set (0.16 sec)
    
    mysql> exit
    Bye
    

Pub/Sub トピックとサブスクリプションを作成する

  1. Cloud Shell で、thumbnail-service という Pub/Sub トピックを作成します。

    gcloud pubsub topics create thumbnail-service
    

    フォトアルバム アプリケーションは、thumbnail-service トピックでメッセージを公開して、サムネイル生成サービスにリクエストを送信します。

  2. thumbnail-workers という Pub/Sub サブスクリプションを作成します。

    gcloud pubsub subscriptions create --topic thumbnail-service thumbnail-workers
    

    サムネイル生成サービスは、thumbnail-workers サブスクリプションからリクエストを受け取ります。

GKE クラスタを作成する

  1. Cloud Shell で、API を呼び出す権限を持つ GKE クラスタを作成します。

    gcloud container clusters create "photoalbum-cluster" \
        --scopes "https://www.googleapis.com/auth/cloud-platform" \
        --num-nodes "5"
    
  2. 後の手順で kubectl コマンドを使用してクラスタを管理できるように、アクセス認証情報を構成します。

    gcloud container clusters get-credentials photoalbum-cluster
    
  3. ノードのリストを表示します。

    kubectl get nodes
    

    出力で、STATUS 値が Ready のノードが 5 つあることを確認します。

    NAME                                                STATUS   ROLES    AGE     VERSION
    gke-photoalbum-cluster-default-pool-d637570a-2pfh   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-3rm4   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-f7l4   Ready    <none>   2m55s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-qb2z   Ready    <none>   2m53s   v1.24.10-gke.2300
    gke-photoalbum-cluster-default-pool-d637570a-rvnp   Ready    <none>   2m54s   v1.24.10-gke.2300
    

Artifact Registry リポジトリを作成する

  • Cloud Shell で、コンテナ イメージを保存するリポジトリを作成します。

    gcloud artifacts repositories create photoalbum-repo \
        --repository-format=docker \
        --location=us-central1 \
        --description="Docker repository"
    

アプリケーションの画像をビルドする

  1. テキスト エディタで application/photoalbum/src/auth_decorator.py ファイルを開き、ユーザー名とパスワードを更新します。

    USERNAME = 'username'
    PASSWORD = 'passw0rd'
    
  2. Cloud Shell で、Cloud Build サービスを使用してフォトアルバム アプリケーションの画像をビルドします。

    gcloud builds submit ./application/photoalbum -t \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app
    
  3. Cloud Build サービスを使用して、thumbnail-worker サムネイル生成サービスの画像をビルドします。

    gcloud builds submit ./application/thumbnail -t \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker
    

フォトアルバム アプリケーションをデプロイする

  1. Cloud Shell で、フォトアルバムとサムネイル生成ツールの Kubernetes Deployment マニフェストを実際の環境に応じた値で更新します。

    connection_name=$(gcloud sql instances describe photoalbum-db \
        --format "value(connectionName)")
    
    digest_photoalbum=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/photoalbum-app:latest --format \
        "value(image_summary.digest)")
    
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_photoalbum}/" \
        config/photoalbum-deployment.yaml
    
    digest_thumbnail=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/thumbnail-worker:latest --format \
        "value(image_summary.digest)")
    
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_thumbnail}/" \
            config/thumbnail-deployment.yaml
    
  2. Deployment リソースを作成して、フォトアルバム アプリケーションとサムネイル生成サービスを起動します。

    kubectl create -f config/photoalbum-deployment.yaml
    kubectl create -f config/thumbnail-deployment.yaml
    
  3. アプリケーションに外部 IP アドレスを割り当てる Service リソースを作成します。

    kubectl create -f config/photoalbum-service.yaml
    
  4. Pod の結果を確認します。

    kubectl get pods
    

    出力で、photoalbum-app Pod と thumbail-worker Pod がそれぞれ 3 つあり、その STATUS 値が Running であることを確認します。

    NAME                                READY     STATUS    RESTARTS   AGE
    photoalbum-app-555f7cbdb7-cp8nw     2/2       Running   0          2m
    photoalbum-app-555f7cbdb7-ftlc6     2/2       Running   0          2m
    photoalbum-app-555f7cbdb7-xsr4b     2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-728k5   2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-hqxqr   2/2       Running   0          2m
    thumbnail-worker-86bd95cd68-xnxhc   2/2       Running   0          2m
    

    thumbnail-worker Pod は、thumbnail-workers サブスクリプションからのサムネイル生成リクエストをサブスクライブします。詳細については、ソースコードでの callback 関数の使用方法をご覧ください。

  5. Service の結果を確認します。

    kubectl get services
    

    出力で、photoalbum-service Service の EXTERNAL-IP 列に外部 IP アドレスがあることを確認します。Service がすべて実行されるまで数分かかることがあります。

    NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP       PORT(S)        AGE
    kubernetes           ClusterIP      10.23.240.1     <none>            443/TCP        20m
    photoalbum-service   LoadBalancer   10.23.253.241   146.148.111.115   80:32657/TCP   2m
    

    後で使用するために、外部 IP アドレスはメモしておきます。この例では 146.148.111.115 です。

フォトアルバム アプリケーションをテストする

  1. デプロイされたアプリケーションにウェブブラウザでアクセスするには、次の URL に移動して、前の手順で設定したユーザー名とパスワードを入力します。

    http://EXTERNAL_IP
    

    EXTERNAL_IP は、前の手順でコピーした IP アドレスに置き換えます。

  2. 画像ファイルをアップロードするには、[アップロード] をクリックします。

    Service が個別のサムネイルを生成するまでの間に表示されるプレースホルダのサムネイル。

    サムネイル プレースホルダが画面に表示されます。

    バックグラウンドで、サムネイル生成サービスがアップロードされた画像のサムネイルを作成します。生成されたサムネイルを表示するには、[Refresh] をクリックします。Cloud Vision API が、検出した画像ラベルを追加します。

    画像ラベルが関連付けられているサムネイル。

    元の画像を表示するには、サムネイルをクリックします。

不適切な画像の検出機能を追加する

次の図は、Cloud Storage の Pub/Sub 通知を使用して、不適切なコンテンツを検出するサービスをトリガーする方法を示しています。不適切なコンテンツを含む新しいファイルが Cloud Storage バケットに保存されると、この機能が画像をぼかします。

不適切なコンテンツ機能のアーキテクチャ。

上の図のように、サービスは Vision API のセーフサーチ検出機能を使用して、画像内の不適切なコンテンツを検出します。

フォト アプリケーションは、サムネイル生成ツールと画像チェッカーを非同期でトリガーします。したがって、特定の順序で実行される保証はありません。画像にぼかしを入れる前にサムネイル生成が行われると、しばらく間、不適切なサムネイルが表示されることがあります。ただし、画像チェッカーは最終的に、不適切な画像と不適切なサムネイルの両方にぼかしを入れます。

Pub/Sub トピック、サブスクリプション、通知を作成する

  1. Cloud Shell で、safeimage-service という Pub/Sub トピックを作成します。

    gcloud pubsub topics create safeimage-service
    
  2. safeimage-workers という Pub/Sub サブスクリプションを作成します。

    gcloud pubsub subscriptions create --topic safeimage-service \
        safeimage-workers
    
  3. Pub/Sub 通知を構成して、新しいファイルが Cloud Storage バケットにアップロードされたときに safeimage-service トピックにメッセージが送信されるようにします。

    gsutil notification create -t safeimage-service -f json \
        gs://${PROJECT_ID}-photostore
    

ワーカー イメージをビルドし、デプロイする

  1. Cloud Shell で、Cloud Build を使用して safeimage-workers サブスクリプションのコンテナ イメージをビルドします。

    gcloud builds submit ./application/safeimage \
        -t us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker
    
  2. セーフイメージ サービスの Kubernetes Deployment マニフェストを、実際の Google Cloud プロジェクト ID、Cloud SQL 接続名、コンテナ イメージのダイジェストで更新します。

    digest_safeimage=$(gcloud container images describe \
        us-central1-docker.pkg.dev/${PROJECT_ID}/photoalbum-repo/safeimage-worker:latest --format \
        "value(image_summary.digest)")
    sed -i.bak -e "s/\[PROJECT_ID\]/${PROJECT_ID}/" \
        -e "s/\[CONNECTION_NAME\]/${connection_name}/" \
        -e "s/\[DIGEST\]/${digest_safeimage}/" \
        config/safeimage-deployment.yaml
    

Deployment リソースを作成する

  1. safeimage-service トピックをデプロイするため、safeimage-deployment という Deployment リソースを作成します。

    kubectl create -f config/safeimage-deployment.yaml
    
  2. 結果を確認します。

    kubectl get pods
    

    出力で、STATUS 値が Runningsafeimage-worker Pod が 3 つあることを確認します。

    NAME                                READY     STATUS    RESTARTS   AGE
    photoalbum-app-555f7cbdb7-cp8nw     2/2       Running   0          30m
    photoalbum-app-555f7cbdb7-ftlc6     2/2       Running   0          30m
    photoalbum-app-555f7cbdb7-xsr4b     2/2       Running   8          30m
    safeimage-worker-7dc8c84f54-6sqzs   1/1       Running   0          2m
    safeimage-worker-7dc8c84f54-9bskw   1/1       Running   0          2m
    safeimage-worker-7dc8c84f54-b7gtp   1/1       Running   0          2m
    thumbnail-worker-86bd95cd68-9wrpv   2/2       Running   0          30m
    thumbnail-worker-86bd95cd68-kbhsn   2/2       Running   2          30m
    thumbnail-worker-86bd95cd68-n4rj7   2/2       Running   0          30m
    

    safeimage-worker Pod は、safeimage-workers サブスクリプションから不適切な画像の検出リクエストをサブスクライブします。詳細については、ソースコードでの callback 関数の使用方法をご覧ください。

不適切な画像の検出機能をテストする

このセクションでは、テスト画像をアップロードし、セーフサーチ検出不適切な画像が機能によってぼかし処理されることを確認します。テスト画像は、ゾンビ姿の少女の画像です(Pixaby CC0 ライセンス取得済み)。

  1. テスト画像をダウンロードします
  2. 画像をアップロードするには、http://EXTERNAL_IP に移動して [Upload] をクリックします。
  3. [Refresh] をクリックします。ぼかし処理が施されたサムネイルがアプリケーションに表示されます。

    ぼかし処理が施されたサムネイル。

    アップロードした画像にもぼかし処理が施されていることを確認するには、サムネイルをクリックします。

クリーンアップ

サンプル アプリケーション用に作成した Google Cloud リソースを保持しない場合は、今後料金が発生しないように削除できます。プロジェクトを完全に削除するか、クラスタ リソースを削除してからクラスタを削除できます。

プロジェクトを削除する

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

個々のリソースを削除する

プロジェクトを削除する代わりに、作成した個々のリソースを削除できます。

  1. GKE からリソースを削除します。

    kubectl delete -f config/safeimage-deployment.yaml
    kubectl delete -f config/photoalbum-service.yaml
    kubectl delete -f config/thumbnail-deployment.yaml
    kubectl delete -f config/photoalbum-deployment.yaml
    
  2. GKE からクラスタを削除します。

    gcloud container clusters delete photoalbum-cluster --quiet
    
  3. Artifact Registry からリポジトリを削除します。

    gcloud artifacts repositories delete photoalbum-repo --location us-central1 --quiet
    
  4. Pub/Sub からサブスクリプションとトピックを削除します。

    gcloud pubsub subscriptions delete safeimage-workers
    gcloud pubsub topics delete safeimage-service
    gcloud pubsub subscriptions delete thumbnail-workers
    gcloud pubsub topics delete thumbnail-service
    
  5. Cloud SQL インスタンスを削除します。

    gcloud sql instances delete photoalbum-db --quiet
    
  6. Cloud Storage バケットを削除します。

    gsutil rm -r gs://${PROJECT_ID}-photostore
    gsutil rm -r gs://${PROJECT_ID}_cloudbuild
    
  7. ファイルを削除します。

    cd ..
    rm -rf gke-photoalbum-example
    

次のステップ