0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Firebase Cloud Functions から Google Cloud Run functions への移行

Last updated at Posted at 2024-10-03

はじめに

GitHub Copilot Extensions というものが最近パブリックベータになったようで、コード開発支援ツールである GitHub Copilot の VSCode 拡張から、外部サービスとシームレスに連携できるような機能が利用可能となった。自分も Copilot のライトユーザーとして、何か試してみたいと思い、GitHub Marketplace で利用可能な拡張を物色していたところ、Sentry Copilot Extension を見つけた。「今稼働している Firebase Cloud Functions を Sentry で監視するようにしてエラー発生させてそれを VSCode から可視化できたら面白いかも」と思ったものの、本拡張が Firebase Cloud Functions に対応していないらしく、はたまた困ってしまったが、Google Cloud Run functions はサポートしているようで、いっちょ変えたれ、と思って本件に至る。

ユースケース

Pubsub からメッセージを受け取って発動する Functions を Firebase Cloud Functions(第 1 世代) から Google Cloud Run functions(第 2 世代) に書き換える。

前提

環境

node -v
# v18.18.0

gcloud -v
#Google Cloud SDK 494.0.0
#bq 2.1.8
#core 2024.09.20
#gcloud-crc32c 1.0.0
#gsutil 5.30

条件

  • Pub/Sub トピックはあらかじめ作成されているとする(my-topic

やったこと

環境準備

詳しくは本家を参照

アプリ改修

functions のメイン?コンポーネントを変更する

- import * as functions from 'firebase-functions';
+ import * as functions from '@google-cloud/functions-framework';

もちろん、その前に install は必要だ

npm i --save @google-cloud/functions-framework

次に、エントリーポイント関数を書き換える。

Firebase Cloud Functions(第 1 世代) の場合、以下のようなコードであった:

import * as functions from 'firebase-functions';

exports.myFunction = functions
  .runWith({ timeoutSeconds: 540, failurePolicy: true, memory: '1GB' })
  .region('asia-northeast1')
  .pubsub.topic("my-topic")
  .onPublish(async (message, context) => {
    // decode message
    const decoded = Buffer.from(message.data, 'base64');
    ...
  })

特徴として、後段の関数デプロイ時の設定値をプログラム内に書き込むことである。
タイムアウト (timeoutSeconds)、関数に割り当てるメモリ (memory)、リージョン (region())、対象 pubsub トピック (pubsub.topic()) などを指定できる。

これを、新しくしたのがこちら:

import * as functions from '@google-cloud/functions-framework';

interface PubSubData {
  subscription: string;
  message: {
    messageId: string;
    publishTime: string;
    data: string;
    attributes?: { [key: string]: string };
  };
}

functions
  .cloudEvent<PubSubData>('myFunction', async (cloudEvent) => {
    // access encoded event data
    const data = cloudEvent.data?.message.data;
    // decode event data
    const decoded = Buffer.from(data, 'base64');
    // ...
  })

Firebase の場合のような指定項目はなく、シンプルになった。
が、これは後続のデプロイコマンドで指定することになる。

参考:

deploy

  • Firebase Cloud Functions(第 1 世代) の場合
firebase deploy --only functions
  • Google Cloud Run functions(第 2 世代) の場合
gcloud functions deploy <FUNCTION_NAME> --runtime <RUNTIME> --trigger-topic=<TOPIC_NAME> --region=<REGION> --memory=<memory> --timeout=<timeout_in_second>

#e.g.
# gcloud functions deploy myFunction --runtime nodejs18 --trigger-topic=my-topic --region=asia-northeast1 --memory=1GB --timeout=540

エントリーポイント関数が簡潔だった分、そっくりそのままデプロイコマンドに跳ね返ってきた形となる。

参考:

遭遇したエラー

secret manager 周りでエラー

本アプリでは、Secret Manager を 利用しており、API 経由で情報を取得してきているのだが、API アクセス時に以下のようなエラーが発生した:

Error: 7 PERMISSION_DENIED: Permission 'secretmanager.versions.access' denied for resource ...

対応は、こちら を参照した。

やるべきことは、以下のデプロイコマンド実行時のメッセージに対し:

gcloud functions deploy slackNotification-g2 --runtime nodejs18 --trigger-topic=notification-pubsub-topic2 --region=asia-northeast1 --memory=1GB
Preparing function...done.                                                                    ...     
  service: projects/xxxxx/locations/asia-northeast1/services/myFunction
  serviceAccountEmail: xxxxxxxxxxx@developer.gserviceaccount.com
  ...

serviceAccountEmail のアカウント xxxxxxxxxxx@developer.gserviceaccount.com のサービスアカウントに対して、IAM ページでロール(Secret Manager Secret Accessor)を追加する。

  • IAM と管理 > IAM に遷移し、編集アイコンクリック

スクリーンショット 2024-10-03 0.07.49.png

  • 「別のロールを追加」クリック

スクリーンショット 2024-10-03 0.10.52.png

  • Secret Manager Secret Accessor のロールを付与

スクリーンショット 2024-10-03 0.12.46.png

Google Sheets API でエラー

本アプリでは、Google Sheets への書き込みを API 経由で行っており、API コール時に以下のようなエラーが発生した:

The caller does not have permission

対応は、こちら を参照した。

書き込みたい Sheets ページで、共有 クリック > サービスアカウントを追加する必要がある。このサービスアカウントは前述の Secret Manager Secret Accessor ロールを追加したアカウントと同じものである。

  • 共有クリック
  • サービスアカウントを追加

Secret Manager おより Google Sheets での両エラーは、思い返してみると最初本アプリを Firebase で作った時のも同じエラーが出た記憶がある。つまり、Google Cloud Run functions だから起こったのではなく、サービスアカウントが変更になったから、その分同じ権限を付与する必要があったということと考えられる。

移行完了

サービスアカウントのニアミスさえ気をつければ、移行作業は小一時間で終わりそうなものであった。
一応、両方の Functions を触ってみての感想としては、Firebase の方が好みであることもわかった。
理由は、デプロイ設定値をプログラム中に宣言的に記述できるからである。
デプロイにまつわる設定値の管理上、ソースコードに入れられた方が取り扱いがしやすいだろう(デプロイコマンドをシェルスクリプトに書いて、それを管理するという方法もあるが、取り回しが一段下がる気がする)

こうして、当初の目的を達成すべくようやくスタート地点につけた。
Sentry Copilot Extension については引き続き作業を継続し、成果が出たら共有したい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?