この Codelab について
1. はじめに
Workflows を使用して、一連のサーバーレス タスクを定義した順序でつなぐサーバーレス ワークフローを作成できます。Google Cloud の API の機能、Cloud Functions や Cloud Run などのサーバーレス プロダクトを組み合わせ、外部 API を呼び出して柔軟なサーバーレス アプリケーションを作成できます。
ワークフローでは、インフラストラクチャの管理が不要であり、需要に合わせてシームレスにスケールします(ゼロへのスケールダウンなど)。料金モデルは従量課金制で、料金は実行時間に対してのみ発生します。
この Codelab では、さまざまな Google Cloud サービスと外部 HTTP API を Workflows で接続する方法について説明します。具体的には、2 つのパブリック Cloud Functions サービス、1 つのプライベート Cloud Run サービス、外部パブリック HTTP API をワークフローに接続します。
学習内容
- ワークフローの基本。
- 公開 Cloud Functions をワークフローに接続する方法。
- プライベート Cloud Run サービスを Workflows に接続する方法。
- 外部 HTTP API を Workflows に接続する方法。
2. 設定と要件
セルフペース型の環境設定
- Cloud Console にログインし、新しいプロジェクトを作成するか、既存のプロジェクトを再利用します(Gmail アカウントまたは G Suite アカウントをお持ちでない場合は、アカウントを作成する必要があります)。
プロジェクト ID を忘れないようにしてください。プロジェクト ID はすべての Google Cloud プロジェクトを通じて一意の名前にする必要があります(上記の名前はすでに使用されているので使用できません)。以降、このコードラボでは PROJECT_ID
と呼びます。
- 次に、Google Cloud リソースを使用するために、Cloud Console で課金を有効にする必要があります。
このコードラボを実行しても、費用はほとんどかからないはずです。このチュートリアル以外で請求が発生しないように、リソースのシャットダウン方法を説明する「クリーンアップ」セクションの手順に従うようにしてください。Google Cloud の新規ユーザーは $300 の無料トライアル プログラムをご利用いただけます。
Cloud Shell の起動
Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。
GCP Console で右上のツールバーにある Cloud Shell アイコンをクリックします。
プロビジョニングと環境への接続にはそれほど時間はかかりません。完了すると、次のように表示されます。
この仮想マシンには、必要な開発ツールがすべて用意されています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働します。そのため、ネットワークのパフォーマンスと認証機能が大幅に向上しています。このラボでの作業はすべて、ブラウザから実行できます。
3. ワークフローの概要
基本
ワークフローは、Workflows の YAML ベースの構文を使用して記述された一連のステップで構成されます。これがワークフローの定義です。Workflows YAML 構文の詳細については、構文リファレンスのページをご覧ください。
ワークフローを作成するとデプロイされ、ワークフローを実行する準備が整います。実行とは、ワークフローの定義に含まれるロジックを 1 回だけ実行することです。すべてのワークフローの実行は独立しており、このプロダクトは多数の同時実行をサポートしています。
サービスを有効にする
この Codelab では、Cloud Functions と Cloud Run サービスを Workflows に接続します。また、サービスのビルド中に Cloud Build と Cloud Storage を使用します。
必要なサービスをすべて有効にします。
gcloud services enable \ cloudfunctions.googleapis.com \ run.googleapis.com \ workflows.googleapis.com \ cloudbuild.googleapis.com \ storage.googleapis.com
次のステップでは、2 つの Cloud Functions をワークフローで接続します。
4. 最初の Cloud Functions 関数をデプロイする
最初の関数は Python の乱数生成ツールです。
関数コード用のディレクトリを作成して移動します。
mkdir ~/randomgen cd ~/randomgen
ディレクトリに、次の内容の main.py
ファイルを作成します。
import random, json from flask import jsonify def randomgen(request): randomNum = random.randint(1,100) output = {"random":randomNum} return jsonify(output)
この関数は HTTP リクエストを受信すると、1 ~ 100 の間の乱数を生成し、JSON 形式で呼び出し元に返します。
この関数は HTTP 処理に Flask に依存しているため、Flask を依存関係として追加する必要があります。Python における依存関係は pip で管理され、requirements.txt
というメタデータ ファイルで表現されます。
同じディレクトリに、次の内容の requirements.txt
ファイルを作成します。
flask>=1.0.2
HTTP トリガーを使用して関数をデプロイし、未認証のリクエストを許可するには、次のコマンドを使用します。
gcloud functions deploy randomgen \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
関数がデプロイされると、コンソールに表示される url
プロパティまたは gcloud functions describe
コマンドで表示される関数の URL を確認できます。
次の curl
コマンドを使用して、関数の URL にアクセスすることもできます。
curl $(gcloud functions describe randomgen --format='value(url)')
関数はワークフローの準備が整いました。
5. 2 番目の Cloud Functions 関数をデプロイする
2 つ目の関数は乗数です。受信した入力に 2 を掛けます。
関数コード用のディレクトリを作成して移動します。
mkdir ~/multiply cd ~/multiply
ディレクトリに、次の内容の main.py
ファイルを作成します。
import random, json from flask import jsonify def multiply(request): request_json = request.get_json() output = {"multiplied":2*request_json['input']} return jsonify(output)
この関数は HTTP リクエストを受信すると、JSON 本文から input
を抽出し、2 を乗算して、JSON 形式で呼び出し元に返します。
同じディレクトリに、次の内容の同じ requirements.txt
ファイルを作成します。
flask>=1.0.2
HTTP トリガーを使用して関数をデプロイし、未認証のリクエストを許可するには、次のコマンドを使用します。
gcloud functions deploy multiply \ --runtime python312 \ --trigger-http \ --allow-unauthenticated
関数がデプロイされたら、次の curl
コマンドを使用して関数の URL にアクセスすることもできます。
curl $(gcloud functions describe multiply --format='value(url)') \ -X POST \ -H "content-type: application/json" \ -d '{"input": 5}'
関数はワークフローの準備が整いました。
6. 2 つの Cloud Functions を接続する
最初のワークフローで、2 つの関数を接続します。
次の内容の workflow.yaml
ファイルを作成します。
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - returnResult: return: ${multiplyResult}
このワークフローでは、最初の関数から乱数を取得し、2 番目の関数に渡します。結果は乗算された乱数です。
最初のワークフローをデプロイします。
gcloud workflows deploy workflow --source=workflow.yaml
最初のワークフローを実行します。
gcloud workflows execute workflow
ワークフローが実行されたら、前の手順で指定した実行 ID を渡して結果を確認できます。
gcloud workflows executions describe <your-execution-id> --workflow workflow
出力には result
と state
が含まれます。
result: '{"body":{"multiplied":108},"code":200 ... } ... state: SUCCEEDED
7. 外部 HTTP API を接続する
次に、ワークフローで外部サービスとして math.js を接続します。
math.js では、次のように数式を評価できます。
curl https://api.mathjs.org/v4/?'expr=log(56)'
今回は、Cloud コンソールを使用してワークフローを更新します。Google Cloud コンソールで Workflows
を見つけます。
ワークフローを見つけて、[Definition
] タブをクリックします。
ワークフロー定義を編集して、math.js
の呼び出しを追加します。
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - returnResult: return: ${logResult}
これで、ワークフローは乗算関数の出力を math.js
のログ関数呼び出しにフィードします。
UI に沿ってワークフローを編集してデプロイします。デプロイしたら、Execute
をクリックしてワークフローを実行します。実行の詳細が表示されます。
ログ関数の出力で、ステータス コード 200
と body
を確認します。
外部サービスをワークフローに統合しました。
8. Cloud Run サービスをデプロイする
最後のパートでは、限定公開の Cloud Run サービスの呼び出しでワークフローを完成させます。つまり、Cloud Run サービスを呼び出すには、ワークフローを認証する必要があります。
Cloud Run サービスは、渡された数値の math.floor
を返します。
サービスコードのディレクトリを作成して移動します。
mkdir ~/floor cd ~/floor
ディレクトリに、次の内容の app.py
ファイルを作成します。
import json import logging import os import math from flask import Flask, request app = Flask(__name__) @app.route('/', methods=['POST']) def handle_post(): content = json.loads(request.data) input = float(content['input']) return f"{math.floor(input)}", 200 if __name__ != '__main__': # Redirect Flask logs to Gunicorn logs gunicorn_logger = logging.getLogger('gunicorn.error') app.logger.handlers = gunicorn_logger.handlers app.logger.setLevel(gunicorn_logger.level) app.logger.info('Service started...') else: app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))
Cloud Run ではコンテナがデプロイされるため、Dockerfile
が必要であり、コンテナは 0.0.0.0
と PORT
の環境変数にバインドする必要があります。そのため、上記のコードが使用されます。
この関数は HTTP リクエストを受信すると、JSON 本文から input
を抽出し、math.floor を呼び出して結果を呼び出し元に返します。
同じディレクトリに、次の Dockerfile
を作成します。
# Use an official lightweight Python image. # https://hub.docker.com/_/python FROM python:3.7-slim # Install production dependencies. RUN pip install Flask gunicorn # Copy local code to the container image. WORKDIR /app COPY . . # Run the web service on container startup. Here we use the gunicorn # webserver, with one worker process and 8 threads. # For environments with multiple CPU cores, increase the number of workers # to be equal to the cores available. CMD exec gunicorn --bind 0.0.0.0:8080 --workers 1 --threads 8 app:app
コンテナを構築します。
export SERVICE_NAME=floor gcloud builds submit --tag gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME}
コンテナがビルドされたら、Cloud Run にデプロイします。no-allow-unauthenticated
フラグに注目してください。これにより、サービスは認証された呼び出しのみを受け入れます。
gcloud run deploy ${SERVICE_NAME} \ --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \ --platform managed \ --no-allow-unauthenticated
デプロイが完了すると、サービスはワークフローの準備が整います。
9. Cloud Run サービスを接続する
プライベート Cloud Run サービスを呼び出すように Workflows を構成する前に、Workflows が使用するサービス アカウントを作成する必要があります。
export SERVICE_ACCOUNT=workflows-sa gcloud iam service-accounts create ${SERVICE_ACCOUNT}
サービス アカウントに run.invoker
ロールを付与します。これにより、サービス アカウントは認証済みの Cloud Run サービスを呼び出せるようになります。
gcloud projects add-iam-policy-binding ${GOOGLE_CLOUD_PROJECT} \ --member "serviceAccount:${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com" \ --role "roles/run.invoker"
workflow.yaml
のワークフロー定義を更新して、Cloud Run サービスを含めます。auth
フィールドも含めて、ワークフローが Cloud Run サービスへの呼び出しで認証トークンを渡すことを確認します。
- randomgenFunction: call: http.get args: url: https://<region>-<project-id>.cloudfunctions.net/randomgen result: randomgenResult - multiplyFunction: call: http.post args: url: https://<region>-<project-id>.cloudfunctions.net/multiply body: input: ${randomgenResult.body.random} result: multiplyResult - logFunction: call: http.get args: url: https://api.mathjs.org/v4/ query: expr: ${"log(" + string(multiplyResult.body.multiplied) + ")"} result: logResult - floorFunction: call: http.post args: url: https://floor-<random-hash>.run.app auth: type: OIDC body: input: ${logResult.body} result: floorResult - returnResult: return: ${floorResult}
ワークフローを更新します。今回は、service-account を渡します。
gcloud workflows deploy workflow \ --source=workflow.yaml \ --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
ワークフローを実行します。
gcloud workflows execute workflow
数秒後に、ワークフローの実行結果を確認できます。
gcloud workflows executions describe <your-execution-id> --workflow workflow
出力には整数の result
と state
が含まれます。
result: '{"body":"5","code":200 ... } ... state: SUCCEEDED
10. お疲れさまでした
以上で、この Codelab は完了です。
学習した内容
- ワークフローの基本。
- 公開 Cloud Functions をワークフローに接続する方法。
- プライベート Cloud Run サービスを Workflows に接続する方法。
- 外部 HTTP API を Workflows に接続する方法。