はじめての Cloud Workflows
本記事は Google Cloud Japan Advent Calendar 2022 の 「今から始める Google Cloud 編」 の23日目の記事です(だいぶ遅くなってしまいましたが…)。
本記事は、サーバーレスのワークフローサービスである「Cloud Workflows」についての入門記事です。Cloud Workflows を触ったことがない方、またはサービス名自体を初めて聞いた方などを対象に Cloud Workflows の概要と使い方をご紹介します。
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 の概要について、もう少し知りたい方は以下も参照してください。
料金
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 の全体感を把握しましょう。
まず Cloud Workflows のコンソールを開きましょう。Google Cloud コンソールを開き、検索窓で「Workflows」と入力し、検索結果にある「ワークフロー」を選びます。
Google Cloud コンソールでの Cloud Workflows へのアクセス
使用している Google Cloud プロジェクトで Cloud Workflows を使ったことがない場合は、まず 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
という変数 (後述) に格納しています。next
に readWikipedia
を指定しているので getCurrentTime
と setFromCallResult
はスキップされます。
- checkSearchTermInInput:
switch:
- condition: ${"searchTerm" in input}
assign:
- searchTerm: ${input.searchTerm}
next: readWikipedia
- getCurrentTime: <-- スキップ
- setFromCallResult: <-- スキップ
- readWikipedia:
assign
- 変数定義
- <ステップ名>
assign:
- <変数名>: <値>
ワークフロー内で変数を定義することができます。定義した変数は他のステップから参照することができます。
上述している Switch 文を改めて見てみると input.searchTerm
を searchTerm
として変数にしていることが分かります。
- 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 の場合は url
や header
など、Google Cloud サービスの場合は projectId
、といった具合です。HTTP リクエストで指定できる項目は、次のドキュメントを参照してください。
レスポンスデータは 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 を使う上で特に参考になるドキュメントをまとめました。ぜひご活用ください。
Discussion