Google Workflows で Cloud Functions をスケジュール実行してみた

2021.12.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!エノカワです。

本エントリは クラスメソッド Google Cloud Advent Calendar 2021 の 13日目 の記事です。

さて、前回のエントリではCloud Functions と Amazon SES を連携させてメール送信を試してみました。

コンソールからCloud Functions の関数を実行して、Amazon SES 経由でメールを送信するというシンプルな構成でした。

実際の運用では、定期的に実行するバッチ処理の完了通知にメール送信の仕組みが利用されるのではないでしょうか。
例えば、サーバーレスでワークフローを定義できる Google Cloud の Workflows というサービスと組み合わせて利用するとか、、、

ということで、今回はGoogle Workflows で Cloud Functions をスケジュール実行してみました。(強引)

概要

構成図はこんな感じです。

前回のエントリで構築した構成を拡張した形です。

Workflows で Cloud Functions のメール送信関数を実行するワークフローを定義し、
Cloud Scheduler で 定期的に Workflows を実行するジョブを作成します。

Workflows

サービスアカウント作成

Workflows が使用するサービス アカウントを作成します。

以下のコマンドを実行します。

export SERVICE_ACCOUNT=workflows-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT}

前回のエントリで作成した Cloud Functions は呼び出しに認証を必須としました。

サービスアカウントが認証済みの Cloud Functions を呼び出すことができるようにするには、
サービス アカウントにCloud Functions 起動元cloudfunctions.invoker)のロールを付与する必要があります。

以下のコマンドを実行します。

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
    --role "roles/cloudfunctions.invoker"

コンソールから作成したサービスアカウントを確認します。

Cloud Functions 起動元のロールが付与されていますね。

ワークフロー定義

YMALファイルでワークフローを定義します。
以下の内容でsend_email_batch.yamlというファイルを作成しました。

- send_email:
    call: http.post
    args:
        url: {Cloud Functions メール送信関数のURL}
        body:
            subject: "Workflows のリクエストにお応えして"
            message: "Cloud Functions から来ました。"
        auth:
            type: OIDC
    result: response
- return_value:
    return: ${response}

2ステップの処理を順次実行するワークフローです。

  • send_email
    • 前回のエントリで作成した Cloud Functions のメール送信関数を呼び出し
  • return_value
    • メール送信関数の結果を返す

Workflows から Cloud Functions の呼び出しはHTTP リクエストを介して行われます。
また、前回のエントリで作成した Cloud Functions のエンドポイント(URL)はHTTPSが必須になっています。

HTTPS エンドポイントに制限された Cloud Functions にリクエストを送信するときは、
OIDCを使用して認証する必要があるため、authフィールドのtypeOIDCを指定します。

デプロイ

以下のコマンドでデプロイします。

gcloud workflows deploy send_email_batch \
  --source=send_email_batch.yaml \
  --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com

コンソールから作成した Workflows を確認します。

send_email_batchの Workflows が作成されていますね。

クリックすると詳細が確認できます。
「ソース」タブではコードを可視化したものを見ることができます。

テスト実行

Workflows 詳細画面からテスト実行することができます。

画面左下の「実行」ボタンを押すと、、、

Workflows のリクエストにお応えして
Cloud Functions から来ました!

Cloud Scheduler

サービスアカウント作成

Cloud Scheduler が使用するサービス アカウントを作成します。

以下のコマンドを実行します。

export SERVICE_ACCOUNT_CS=cloudscheduler-sa
gcloud iam service-accounts create ${SERVICE_ACCOUNT_CS}

サービス アカウントにWorkflows 起動元workflows.invoker)のロールを付与します。

以下のコマンドを実行します。

gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \
    --member "serviceAccount:${SERVICE_ACCOUNT_CS}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \
    --role "roles/workflows.invoker"

コンソールから作成したサービスアカウントを確認します。

Workflows 起動元のロールが付与されていますね

ジョブ作成

以下のコマンドで Workflows を実行する Cloud Scheduler のジョブを作成します。

gcloud scheduler jobs create http exec_workflow_every_10minutes \
  --schedule="*/10 * * * *" \
  --uri="https://workflowexecutions.googleapis.com/v1/projects/${GOOGLE_CLOUD_PROJECT}/locations/us-central1/workflows/send_email_batch/executions" \
  --time-zone="Asia/Tokyo" \
  --oauth-service-account-email="${SERVICE_ACCOUNT_CS}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com"

コンソールから作成したジョブを確認します。

10分おきに Workflows を実行するジョブが作成されていますね。

ちなみに Workflows 詳細画面の「トリガー」タブでもジョブを確認することができました。

スケジュール実行

しばらく経ったので、スケジュール実行されたか確認してみましょう。

Workflows 詳細画面の「実行数」タブを表示します。

10分おきに起動されていますね!
Cloud Scheduler のジョブが正常に実行されたようです。

受信トレイにも10分おきにメールが届いていました!

コンソールから作成

今回はコマンドを中心にワークフローとジョブの作成を行いましたが、
コンソールからでも簡単に作成を行うことができます。

Workflows 画面上部の「+作成」ボタンをクリックします。

構成の画面が表示されますので、ワークフロー名や使用するサービスアカウントを入力します。

ちなみに「新しいトリガーを追加」から「スケジューラ」をクリックすると、、、

スケジュールを定義する画面が表示されます。
ここで Cloud Scheduler のジョブ作成を行うことができるんですね。

次の画面でワークフローの定義(YAMLファイルの中身)を入力して、
「デプロイ」ボタンをクリックすると完成です。

まとめ

以上、Google Workflows で Cloud Functions をスケジュール実行してみました。

ドキュメントを参照しつつ、コマンドをいくつか実行するだけで短時間で実現することができました。
途中、Cloud Functions 呼び出しの認証周りでエラーに遭遇する場面がありましたので、
以下の点に留意が必要です。

  • サービス アカウント
    Cloud Functions 起動元cloudfunctions.invoker)のロールを付与する
  • ワークフロー定義
    authフィールドのtypeOIDCを指定する

Workflows では、Cloud Functions や BigQuery などGoogleの各種サービス以外にも
HTTPリクエストによる外部サービスとの連携も可能なので活用できるシーンは多いのではないでしょうか。

明日 12/14 は 新井成一 さんです。よろしくお願いします!

参考