🚶‍♂️

はじめての Cloud Workflows

2022/12/31に公開

本記事は Google Cloud Japan Advent Calendar 2022 の 「今から始める Google Cloud 編」 の23日目の記事です(だいぶ遅くなってしまいましたが…)。

本記事は、サーバーレスのワークフローサービスである「Cloud Workflows」についての入門記事です。Cloud Workflows を触ったことがない方、またはサービス名自体を初めて聞いた方などを対象に Cloud Workflows の概要と使い方をご紹介します。

https://cloud.google.com/workflows?hl=ja

Cloud Workflows とは

Google Cloud の各サービス (Cloud Storage、BigQuery、Cloud Functions など) や API を組み合わせて、一連のワークフローやパイプラインを構築することができるサービスです。

一連のワークフローとは「複数のサービスをつなぎ合わせて、一連の処理を実行する」ということです。例えば「Cloud Storage に置かれた画像ファイルを Vision API で解析し、情報を BigQuery に書き込む」などのような処理です。各サービスをコンポーネントとして扱い、それらをつなぎ合わせ、ユースケースを実現します。

こういったワークフローは Cloud Workflows を使わなくても作れますが、Cloud Workflows を使って構築することで ワークフローを実行する上で必要なあれこれがフルマネージドで提供されます。 具体的には次のような機能です。

  • ワークフロー自体の可視化
  • リクエストとレスポンスのデータ変換
  • 各サービスの認証
  • モニタリング
  • 再試行ポリシーの指定
  • 非同期処理の待ち合わせ

またワークフローの定義自体は YAML または JSON で記述するため Cloud Workflows を使うだけで必然とワークフローの定義をソースコード化 できます。手作業で構築する場合は細かい制御の情報などは別途保存・更新する必要があるため、そういった手間が必要なくなる点もメリットの一つです。

Cloud Workflows の概要について、もう少し知りたい方は以下も参照してください。

https://cloud.google.com/workflows/docs/overview?hl=ja

料金

Cloud Workflows には無償枠が設定されているため、少し試す程度であればもちろん無料で使えますし、月に 2,000 回程度実行されるワークフローであれば無償枠の範囲 に収まります。

Cloud Workflows はサーバーレスで実行され、呼び出し回数と呼び出しステップ回数で従量課金されます。なおステップとは、1つのワークフローの中の手順を指します。

内部ステップ 月額
最初の 5,000 ステップ 無料
5,001 ステップ ~ $0.01 / 5,000 ステップ
外部 HTTP 呼び出し 月額
最初の 2,000 回 無料
2,001 回 ~ $0.025 / 1,000 回

※ 2022年12月時点

Cloud Workflows を使ってみる - API の組み合わせ

前置きはこのくらいにして、早速 Cloud Workflows を使ってみましょう。前提として課金が有効になっている Google Cloud プロジェクトの準備はできていることとします。

クイックスタートでは「今日の曜日情報を API (Cloud Functions でデプロイされているもの) から取得し、その曜日に関する情報を Wikipedia API から取得する」というワークフローをデプロイする手順が紹介されています。こちらをまず動かして Cloud Workflows の全体感を把握しましょう。

https://cloud.google.com/workflows/docs/create-workflow-console?hl=ja#yaml

まず Cloud Workflows のコンソールを開きましょう。Google Cloud コンソールを開き、検索窓で「Workflows」と入力し、検索結果にある「ワークフロー」を選びます。

Google Cloud コンソールでの Cloud Workflows へのアクセス
Google Cloud コンソールでの Cloud Workflows へのアクセス

使用している Google Cloud プロジェクトで Cloud Workflows を使ったことがない場合は、まず Workflows API を有効化する必要があります。

Workflows API の有効化
Workflows API の有効化

[作成] を選び、ワークフローの作成チュートリアルを始めます。

ワークフローの作成
ワークフローの作成

ワークフローの作成画面が表示されます。ワークフローの作成に必要な設定を埋めていきます。

ワークフローの設定
ワークフローの設定

次のように設定します。

設定項目 設定値
ワークフロー名 myFirstWorkflow
ワークフローの説明 省略
リージョン asia-northeast1 (東京)
サービスアカウント 作成する (後述します)
ラベル 省略
トリガー 省略

[サービスアカウント] は、ワークフローが Google Cloud の各サービスを実行する時に、API を実行するアカウントとして使われます。このチュートリアルでは Google Cloud のサービスは呼び出さないためサービスアカウントを使った認証は必要としませんが、必須項目となっているため設定しなければいけません。ここでは [作成] をクリックし、サービスアカウントの作成を行います。

新しいサービスアカウントの作成
新しいサービスアカウントの作成

新しいタブが開き、サービスアカウントの作成画面が表示されます。

サービスアカウントの作成画面
サービスアカウントの作成画面

次のように設定します。

設定項目 設定値
サービスアカウント名 workflow-sa
サービスアカウント ID サービスアカウント名より自動設定
サービスアカウントの説明 省略

[このサービス アカウントにプロジェクトへのアクセスを許可する] と [ユーザーにこのサービス アカウントへのアクセスを許可] は、ここでは使わないため省略し [完了] をクリックします。

サービスアカウントの作成が完了したらタブを閉じ、ワークフロー作成画面に戻ります。先ほど開いたサービスアカウントの一覧の [更新] をクリックすると、新しく作成したサービスアカウントが表示されます。サービスアカウントを選択し [次へ] をクリックします。

サービスアカウントの選択
サービスアカウントの選択

次に、ワークフローの定義を行います。ワークフローは YAML または JSON で定義する必要があり、コンソール上ではエディタを使って記述できます。また、記述した内容がインタラクティブに可視化されます。

ワークフローの定義の編集画面
ワークフローの編集定義画面

あらかじめ記述されている定義は、このクイックスタートで実施したい内容になっています。どのような定義になっているかは後で確認するとして、まずはこのまま [デプロイ] をクリックしてみましょう。デプロイが完了すると、作成したワークフローの詳細画面に遷移します。

作成したワークフローの詳細画面
作成したワークフローの詳細画面

入力値の設定ができますが、まずはそのまま [実行] をクリックし、作成したワークフローを実行してみます。

ワークフローの実行画面
ワークフローの実行画面

実行結果の確認画面では、入力値と出力値の確認、実行時間、ログなどが確認できます。入力値が未入力の場合は現在の曜日の結果が出力されます。水曜日に実行した場合は、水曜日に関する Wikipedia のページが出力されます。

ワークフロー実行結果確認①
ワークフロー実行結果確認①

[
  "Wednesday",
  "Wednesday (TV series)",
  "Wednesday Addams",
  "Wednesday 13",
  "Wednesday Night Wars",
  "Wednesday Campanella",
  "Wednesday Night Rivalry",
  "Wednesday Campanella discography",
  "Wednesdayite",
  "Wednesday Martin"
]

次に [再実行] をクリックし、今度は入力値を設定して実行してみましょう。次の入力値に設定します。

{ "searchTerm": "Sunday" }

結果が出力されました。今度は日曜日に関する Wikipedia のページが出力されます。

ワークフロー実行結果確認②
ワークフロー実行結果確認②

[
  "Sunday",
  "Sunday in the Park with George",
  "Sunday shopping",
  "Sunday Bloody Sunday",
  "Sunday school",
  "Sunday league football in England",
  "Sunday Times Golden Globe Race",
  "Sunday All Stars",
  "Sunday Silence",
  "Sunday Times Fast Track 100"
]

以上でチュートリアルは終了です。お疲れ様でした!

ワークフローの定義を見てみる

ワークフローの定義の中では、どのような処理を定義していたのか見ていきましょう。まず全体としては入力値の有無で処理が変わっており、入力値が無い場合は Cloud Functions で作られている API から現在の曜日情報を取得するステップが挟まっています。

ワークフローの全体フロー
ワークフローの全体フロー

ワークフロー定義のソースコードは次のようになっています。上から順番に見ていきましょう。

main:
    params: [input]
    steps:
    - checkSearchTermInInput:
        switch:
            - condition: ${"searchTerm" in input}
              assign:
                - searchTerm: ${input.searchTerm}
              next: readWikipedia
    - getCurrentTime:
        call: http.get
        args:
            url: https://us-central1-workflowsample.cloudfunctions.net/datetime
        result: currentDateTime
    - setFromCallResult:
        assign:
            - searchTerm: ${currentDateTime.body.dayOfTheWeek}
    - readWikipedia:
        call: http.get
        args:
            url: https://en.wikipedia.org/w/api.php
            query:
                action: opensearch
                search: ${searchTerm}
        result: wikiResult
    - returnOutput:
        return: ${wikiResult.body[1]}

main - Main ブロック

main:
  params: [<引数の名前>]
  steps:
  - ...

main はワークフローを開始するメインのブロックを意味します。必須ではありませんが、引数 (入力値) を受け取りたい場合は main が必要になるため、このワークフローでは main を使用しています。params には入力値 (引数) の名前を指定します。main ブロック
で使う場合は一つだけ受け付けることができます。

また、1つのワークフロー内にサブワークフローを定義することができ、サブワークフローを使う場合はメインとサブを区別するために main が必要になります。

ステップ

- <ステップ名>
  <ステップの設定>
  ...
- <ステップ名>
  <ステップの設定>
  ...

API や Google Cloud サービスの呼び出しなど、ワークフロー内での一つ一つの処理をステップと呼びます。ステップ名でリストを作ることで、上から順番に処理が実行されます。各アイテムには設定値を持たせ、API 呼び出しの場合はエンドポイントやリクエストパラメータの指定などを設定します。また main ブロックの中では steps の中に各ステップを定義します。

サンプルコードの main.steps のステップ名だけ抜き出してみると、各処理がステップで定義されていることが分かります。

main:
    params: [input]
    steps:
    - checkSearchTermInInput:
    - getCurrentTime:
    - setFromCallResult:
    - readWikipedia:
    - returnOutput:

switch - Switch 文

- <ステップ名>:
  switch:
  - condition: <条件>
    <条件下で実行するステップ>
    next: <次に実行するステップ>

Switch 文や For 文などのステップを定義することができます。

condition は複数記述することができ、条件を指定し、その条件に合致した際に次に実行するステップを next で指定します。この機能を使うと、特定の条件下で後続のステップをスキップすることができます。

また condition の中には、その条件に合致した際に実行する処理や設定を直接定義することもできます。これはオプショナルです。変数の定義やステップの実行、API の呼び出しなどを定義できます。

サンプルコードでは input の中に searchTerm がキーの属性が含まれているかチェックし、含まれている場合は値を searchTerm という変数 (後述) に格納しています。nextreadWikipedia を指定しているので getCurrentTimesetFromCallResult はスキップされます。

- checkSearchTermInInput:
  switch:
    - condition: ${"searchTerm" in input}
      assign:
      - searchTerm: ${input.searchTerm}
      next: readWikipedia
- getCurrentTime:    <-- スキップ
- setFromCallResult: <-- スキップ
- readWikipedia:

assign - 変数定義

- <ステップ名>
  assign:
  - <変数名>: <値>

ワークフロー内で変数を定義することができます。定義した変数は他のステップから参照することができます。

上述している Switch 文を改めて見てみると input.searchTermsearchTerm として変数にしていることが分かります。

- checkSearchTermInInput:
  switch:
    - condition: ${"searchTerm" in input}
      assign:
      - searchTerm: ${input.searchTerm}
      next: readWikipedia

変数を定義したあとは ${<変数名>} で参照できるようになります。searchTerm であれば ${searchTerm} で参照できます。

call - API ・コネクター・サブワークフローの呼び出し

- <ステップ名>
  call: <呼び出す種類>
  args:
    <設定項目>: <設定値>
    ...
  result:
    <出力結果の変数名>

API (HTTP リクエスト) や Google Cloud サービス (コネクター)、またはサブワークフローを呼び出します。HTTP メソッドが GET の API を呼び出す場合は、call には http.get を指定します(POST の場合は http.post を指定)。

args は呼び出し先の種類によって指定できる項目が異なります。API の場合は urlheader など、Google Cloud サービスの場合は projectId、といった具合です。HTTP リクエストで指定できる項目は、次のドキュメントを参照してください。

https://cloud.google.com/workflows/docs/http-requests?hl=ja

レスポンスデータは result で指定した名前の変数に格納されます。例えばレスポンスボディは <変数名>.body で参照できます。

サンプルコードでは、Google Cloud からサンプル用に提供している Cloud Functions で作られた日付取得 API を呼び出しています。

- getCurrentTime:
  call: http.get
  args:
    url: https://us-central1-workflowsample.cloudfunctions.net/datetime
  result: currentDateTime

ちなみにこの API は普通に呼び出すと次のようなレスポンスが得られるものです。

$ curl https://us-central1-workflowsample.cloudfunctions.net/datetime
{"dayOfTheWeek":"Thursday"}

レスポンスデータは currentDateTime に格納しています。次のステップの setFromCallResult では、曜日を直接参照できるようレスポンスボディ内の dayOfTheWeek の値を searchTerm という変数に格納しています。

- setFromCallResult:
  assign:
  - searchTerm: ${currentDateTime.body.dayOfTheWeek}

readWikipedia ステップも同様に Wikipedia API を call を使って呼び出しています。

- readWikipedia:
  call: http.get
  args:
    url: https://en.wikipedia.org/w/api.php
    query:
      action: opensearch
      search: ${searchTerm}
  result: wikiResult

return - 出力

- <ステップ名>
  return: ${<出力する変数名>}

一連のワークフローは最後に end または return で終了させます。ワークフローの処理結果を出力したい場合は return を使います。

- returnOutput:
  return: ${wikiResult.body[1]}

まとめ

本記事では Cloud Workflows を触ったことがない方を対象に、Cloud Workflows の基本的な使い方をご紹介しました。Public な API を使ったシンプルなワークフローを取り上げましたが、Google Cloud サービス (コネクターと呼びます) 同士を繋ぎ合わせたパイプラインを作ることができ、Cloud Workflows の醍醐味とも言える機能です。コネクターの使い方については、別記事で近々ご紹介したいと思います。

本記事が Cloud Workflows を触り始めるための一助となれば幸いです。

リンク集

Cloud Workflows を使う上で特に参考になるドキュメントをまとめました。ぜひご活用ください。

Google Cloud Japan

Discussion