mlog

備忘録とかメモとか

【GCP】Cloud Pub/SubとCloud Runを連携してみる

Image from Gyazo

今回は Cloud Pub / Sub と Cloud Run を連携する方法 を解説していきたいと思います!

以下の公式チュートリアルを参考に、Cloud Pub / Sub と Cloud Run の連携を試していきたいと思います。

目次

簡単な流れ

本記事では、以下のような流れで解説を進めていきます。

  1. 使用する変数を解説
  2. Pub / Sub トピックを作成
  3. 使用するコードを解説
  4. Cloud Run へコンテナをデプロイ
  5. Pub / Sub サブスクリプションを作成
  6. 動作確認
  7. 後始末
  8. まとめ

それでは、早速、Cloud Pub / Sub と Cloud Run を連携する方法を解説していきたいと思います!

使用する変数を解説

以下は解説中で利用する変数リストです。本記事をトレースする場合に活用してください。

PROJECT_ID=[プロジェクトID]
PROJECT_NUMBER=[プロジェクト番号]
REGION=[リージョン]
CLUSTER_NAME=[クラスター名]
SERVICE_NAME=pubsub-tutorial
TOPIC_NAME=test-run-topic
SUBSCRIPTION_NAME=test-run-subscription 

※ コマンド実行時に適宜設定でも問題ありません。

以下、各変数の簡単な内容の解説です。

  • PROJECT_ID : 本記事のトレースする場合に使用するプロジェクトのID
  • PROJECT_NUMBER : 本記事のトレースする場合に使用するプロジェクトのプロジェクト番号
  • REGION : 本記事のトレースする場合に使用するプロジェクトのリージョン。既にデフォルト設定済みの場合は設定不要
  • CLUSTER_NAME : 本記事のトレースする場合に使用するクラスタの名前。既にデフォルト設定済みの場合は設定不要
  • SERVICE_NAME : Cloud Run にデプロイするサービスの名前
  • TOPIC_NAME : 作成・使用する Cloud Pub / Sub のトピック名
  • SUBSCRIPTION_NAME : 作成・使用する Cloud Pub / Sub サブスクリプション名

SERVICE_NAMETOPIC_NAMESUBSCRIPTION_NAMEについては、仮の文字列を記載していますが、変更しても問題ありません。

本記事での解説では、上記の文字列の名称を使用して、解説を進めていきます。

デフォルト設定

デフォルトのプロジェクトやリージョンを設定していない場合は、以下のコマンドで設定してください。

gcloud config set project $PROJECT_ID
gcloud config set run/region $REGION
gcloud config set run/cluster $CLUSTER_NAME
gcloud config set run/cluster_location $REGION

Pub/Sub トピックを作成する

起動トリガーとなる Pub / Sub トピック を作成します。

gcloud pubsub topics create $TOPIC_NAME

ここで作成したトピックにメッセージが送られると、Cloud Run に設置するサンプルサービスが起動します。

Cloud Run へのサンプルサービスのデプロイについては、この後、解説していきます。

サンプルコードを取得

Cloud Run のサンプルコードは、以下のリポジトリに含まれるコードを利用します。

以下のコマンドでサンプルリポジトリをクローンしてください。

git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git

コードの内容

nodejs-docs-samples/run/pubsubにあるコードを使用します。

Cloud Run にデプロイされる主なコードは以下の3つです。

  • nodejs-docs-samples/run/pubsub/Dockerfile
  • nodejs-docs-samples/run/pubsub/index.js
  • nodejs-docs-samples/run/pubsub/app.js

以下、簡単にファイルの中身を見ていきます。

Dockerfile

nodejs-docs-samples/run/pubsub/Dockerfileの中身は以下の通りです。

FROM node:10-slim

WORKDIR /usr/src/app

COPY package*.json ./
RUN npm install --production
COPY . .

CMD [ "npm", "start" ]

Cloud Run にデプロイされるNodeコンテナです。

主なコードの3つには含めていませんが、コピーされるpackage.jsonscripts.startフィールドはnode index.jsとなっています。

コンテナの起動時に、このあと解説するnodejs-docs-samples/run/pubsub/index.jsファイルが実行されます。

index.js

nodejs-docs-samples/run/pubsub/index.jsの中身は以下の通りです。

const app = require('./app.js');
const PORT = process.env.PORT || 8080;

app.listen(PORT, () =>
  console.log(`nodejs-pubsub-tutorial listening on port ${PORT}`)
);

ウェブサーバのスタート部分。

ルーティングや Pub / Sub メッセージの処理部分は、app.jsの方に分割されています。

app.jsについては、次の項目で解説します。

app.js

nodejs-docs-samples/run/pubsub/app.jsの中身は以下の通り。

const express = require('express');
const bodyParser = require('body-parser');
const app = express();

app.use(bodyParser.json());

app.post('/', (req, res) => {
  if (!req.body) {
    const msg = 'no Pub/Sub message received';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }
  if (!req.body.message) {
    const msg = 'invalid Pub/Sub message format';
    console.error(`error: ${msg}`);
    res.status(400).send(`Bad Request: ${msg}`);
    return;
  }

  const pubSubMessage = req.body.message;
  const name = pubSubMessage.data
    ? Buffer.from(pubSubMessage.data, 'base64').toString().trim()
    : 'World';

  console.log(`Hello ${name}!`);
  res.status(204).send();
});

module.exports = app;

app.jsでは主に ルーティングと Pub / Sub メッセージの処理 が記述されています。

req.body.messageが設定されていない場合は、不正なリクエストとみなしてエラーメッセージが返されます。

req.body.messageが設定されている場合は、メッセージの内容を使って、コンソールにHello ○○!と出力されます。

デプロイ

続いて、紹介したコードを元に、コンテナイメージをビルド・デプロイします。

cd nodejs-docs-samples/run/pubsub/
gcloud builds submit --tag gcr.io/$PROJECT_ID/pubsub
gcloud run deploy $SERVICE_NAME --image gcr.io/$PROJECT_ID/pubsub

gcloud builds submit ...コマンドでは、コードの内容で解説したDockerfileを元にコンテナイメージがビルドされ、Container Resistry へアップロードされます。

ビルドは Cloud Build を使用して行われます。

gcloud run deploy ... コマンドでは、アップロードされたコンテナイメージを Cloud Run にデプロイしています。

Cloud Run にデプロイする際の、未承認を許可するかどうかの質問には n(いいえ)と答えてください。

Pub / Sub と Cloud Run の連携設定

Cloud Pub / Sub と Cloud Run を連携するための権限設定をしていきます。

gcloud projects add-iam-policy-binding $PROJECT_ID \
    --member=serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com \
    --role=roles/iam.serviceAccountTokenCreator
gcloud iam service-accounts create cloud-run-pubsub-invoker \
    --display-name "Cloud Run Pub/Sub Invoker"
gcloud run services add-iam-policy-binding $SERVICE_NAME \
    --member=serviceAccount:cloud-run-pubsub-invoker@${PROJECT_ID}.iam.gserviceaccount.com \
    --role=roles/run.invoker

まず、gcloud projects add-iam-policy-binding ...コマンドで、プロジェクトで Pub / Sub 認証トークンを作成できるようにしています。

続いて、gcloud iam service-accounts create ...コマンドの部分で、_Cloud Run に作成したサービス(ここではpubsub-tutorial)を起動するためのサービスアカウントを作成 しています。

最後のgcloud run services add-iam-policy-binding ...コマンドでは、作成したサービスアカウントにpubsub-tutorial サービスを起動する権限を付与 しています。

参考ページ

Pub / Sub サブスクリプション作成

Pub/Sub トピックを作成するで作成したトピックを購読するサブスクリプションを作成します。

END_POINT=[Cloud Run サービスの URL ]
gcloud pubsub subscriptions create $SUBSCRIPTION_NAME --topic $TOPIC_NAME \
    --push-endpoint=${END_POINT} \
    --push-auth-service-account=cloud-run-pubsub-invoker@${PROJECT_ID}.iam.gserviceaccount.com

ここで、--push-endpointオプションでプッシュ先を指定 しています。

END_POINT変数には作成した Cloud Run サービス pubsub-tutorial のURLを設定してください。

URLはpubsub-tutorial のページで確認できます。

pubsub-tutorial のページの上部に表示される https://xxxx.run.app のような形式のURLを設定してください。

また、--push-auth-service-accountオプションの部分で、先ほど作成した pubsub-tutorial サービスの起動権限持ったサービスアカウントが Pub / Sub サブスクリプションを紐づけられています。

これにより、作成した Pub/Sub サブスクリプションに pubsub-tutorial サービスの起動権限が間接的に付与されています。

動作確認

実際に、作成した Pub / Sub トピックにメッセージを公開して、pubsub-tutorial サービスがちゃんと起動するか確認します。

gcloud pubsub topics publish $TOPIC_NAME --message "Runner"

Google Cloud Consoleを開いて、pubsub-tutorial サービスのページを開いてください。

サービスページに「ログ」タブがあると思うので、クリックしてログを表示させてください。

「Hello Runner!」と表示されていれば、成功です!

ログが表示されるまでに時間がかかる事があります。 すぐに表視されない場合は、少し開けてから再度確認してみてください。

後始末

使用した Cloud Run サービスや Pub / Sub トピックス、サブスクリプションを削除します。

gcloud run services delete $SERVICE_NAME
gcloud pubsub subscriptions delete $SUBSCRIPTION_NAME
gcloud pubsub topics delete $TOPIC_NAME

プロジェクトを削除する場合や、gcloudのデフォルト設定を削除する場合は、以下のページを参考にしてください。

Cloud Run チュートリアルで Pub/Sub を使用する #クリーンアップ

まとめ

以上、「 Cloud Pub / Sub と Cloud Run を連携する方法」について簡単にまとめてみました!

サービスアカウントの設定が少し面倒ですが、その辺に慣れてしまえば、それほど手間もかからなそうです。

今後、メッセージングサービスが必要になる事があったら、使ってみたいと思います。