Workflows のチュートリアル(第 2 世代)


このチュートリアルでは、Workflows を使用して一連のサービスをリンクする方法について説明します。Cloud Functions(第 2 世代)、外部 REST API、プライベート Cloud Run サービスを使用して 2 つのパブリック HTTP サービスを接続すると、柔軟でサーバーレスなアプリケーションを作成できます。

目標

このチュートリアルでは、Google Cloud CLI を使用して単一のワークフローを作成します。ここでは、一度に 1 つのサービスに接続します。

  1. 2 つの Cloud Functions サービスをデプロイします。最初の関数で乱数を生成し、2 番目の関数で渡された数値を乗算します。
  2. Workflows を使用して 2 つの HTTP 関数を接続します。ワークフローを実行し、結果を返して外部 API に渡します。
  3. Workflows を使用して、指定された数値の log を返す外部 HTTP API を接続します。ワークフローを実行し、結果を返して Cloud Run サービスに渡します。
  4. 認証されたアクセスのみを許可する Cloud Run サービスをデプロイします。サービスは、指定された数値の math.floor を返します。
  5. Workflows を使用して Cloud Run サービスに接続し、ワークフロー全体を実行して最終結果を返します。

次の図は、プロセスの概要と、最終的なワークフローを可視化したものを示しています。

Workflows の可視化

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

始める前に

組織で定義されているセキュリティの制約により、次の手順を完了できない場合があります。トラブルシューティング情報については、制約のある Google Cloud 環境でアプリケーションを開発するをご覧ください。

  1. Google Cloud アカウントにログインします。Google Cloud を初めて使用する場合は、アカウントを作成して、実際のシナリオでの Google プロダクトのパフォーマンスを評価してください。新規のお客様には、ワークロードの実行、テスト、デプロイができる無料クレジット $300 分を差し上げます。
  2. Google Cloud CLI をインストールします。
  3. gcloud CLI を初期化するには:

    gcloud init
  4. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  5. Google Cloud プロジェクトで課金が有効になっていることを確認します

  6. Artifact Registry, Cloud Build, Cloud Functions, Cloud Run, Cloud Storage, and Workflows API を有効にします。

    gcloud services enable artifactregistry.googleapis.comcloudbuild.googleapis.comcloudfunctions.googleapis.comrun.googleapis.comstorage.googleapis.comworkflows.googleapis.com
  7. Google Cloud CLI をインストールします。
  8. gcloud CLI を初期化するには:

    gcloud init
  9. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  10. Google Cloud プロジェクトで課金が有効になっていることを確認します

  11. Artifact Registry, Cloud Build, Cloud Functions, Cloud Run, Cloud Storage, and Workflows API を有効にします。

    gcloud services enable artifactregistry.googleapis.comcloudbuild.googleapis.comcloudfunctions.googleapis.comrun.googleapis.comstorage.googleapis.comworkflows.googleapis.com
  12. Google Cloud CLI のコンポーネントを更新します。
    gcloud components update
  13. Cloud Shell 内でコマンドを実行している場合は、gcloud CLI ですでに認証されています。それ以外の場合は、ご自分のアカウントでログインします。
    gcloud auth login
  14. このチュートリアルで使用するデフォルトのロケーションを設定します。
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set functions/region ${REGION}
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}
    

    REGION は、サポートされている任意の Workflows のロケーションに置き換えます。

  15. プロジェクト作成者には、オーナーロールroles/owner)が付与されます。デフォルトでは、この Identity and Access Management(IAM)ロールには、ほとんどの Google Cloud リソースへの完全アクセス権に必要な権限が含まれており、この手順は省略できます。

    プロジェクト作成者でない場合は、プロジェクトで適切なプリンシパルに必要な権限を付与する必要があります。プリンシパルは Google アカウント(エンドユーザーの場合)やサービス アカウント(アプリケーションとコンピューティング ワークロードの場合)になることもあります。詳細については、イベントの宛先のロールと権限のページをご覧ください。

    必要な権限

    チュートリアルを完了するために必要な権限を取得するには、プロジェクトに対して次の IAM ロールを付与するよう管理者に依頼してください。

    ロールの付与の詳細については、アクセスの管理をご覧ください。

    必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

最初の Cloud Functions サービスをデプロイする

HTTP リクエストを受信すると、この HTTP 関数は 1~100 の間の乱数を生成し、その数値を JSON 形式で返します。

  1. randomgen という名前のディレクトリを作成し、そのディレクトリに移動します。

    mkdir ~/randomgen
    cd ~/randomgen
    
  2. 次の Python コードを含むテキスト ファイルを main.py という名前で作成します。

    import functions_framework
    import random
    from flask import jsonify
    
    @functions_framework.http
    def randomgen(request):
        randomNum = random.randint(1, 100)
        output = {"random": randomNum}
        return jsonify(output)
  3. HTTP 処理用の Flask への依存関係をサポートするには、pip パッケージ マネージャー用のテキスト ファイルを作成します。ファイル名を requirements.txt にして、以下を追加します。

    flask>=1.0.2
    functions-framework==3.0.0
  4. Workflows が使用するサービス アカウントを作成します。

    export SERVICE_ACCOUNT=workflows-sa
    gcloud iam service-accounts create ${SERVICE_ACCOUNT}
    
  5. サービス アカウントが認証済みの Cloud Run サービスを呼び出すことができるようにするには、Workflows サービス アカウントに run.invoker ロールを付与します。

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member "serviceAccount:${SERVICE_ACCOUNT}@PROJECT_ID.iam.gserviceaccount.com" \
        --role "roles/run.invoker"
    
  6. HTTP トリガーを使用して関数をデプロイし、未認証アクセスを許可します。

    gcloud functions deploy randomgen-function \
        --gen2 \
        --runtime python310 \
        --entry-point=randomgen \
        --trigger-http \
        --allow-unauthenticated

    関数のデプロイには数分かかる場合があります。また、Google Cloud コンソールで Cloud Functions インターフェースを使用して関数をデプロイできます。

  7. randomgen 関数がデプロイされたら、httpsTrigger.url プロパティを確認できます。

    gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)"
  8. URL を保存します。これは、後半の演習でワークフローのソースファイルに追加する必要があります。

  9. 次の curl コマンドを使用して、この関数を試すことができます。

    curl $(gcloud functions describe randomgen-function \
        --gen2 \
        --format="value(serviceConfig.uri)")

    数値がランダムに生成され、返されます。

2 つ目の Cloud Functions サービスをデプロイする

HTTP リクエストを受信すると、この HTTP 関数は JSON 本文から input を抽出し、2 を乗算して、結果を JSON 形式で返します。

  1. ホーム ディレクトリに戻ります。

    cd ~
    
  2. multiply という名前のディレクトリを作成し、そのディレクトリに移動します。

    mkdir ~/multiply
    cd ~/multiply
    
  3. 次の Python コードを含むテキスト ファイルを main.py という名前で作成します。

    import functions_framework
    from flask import jsonify
    
    @functions_framework.http
    def multiply(request):
        request_json = request.get_json()
        output = {"multiplied": 2 * request_json['input']}
        return jsonify(output)
  4. HTTP 処理用の Flask への依存関係をサポートするには、pip パッケージ マネージャー用のテキスト ファイルを作成します。ファイル名を requirements.txt にして、以下を追加します。

    flask>=1.0.2
    functions-framework==3.0.0
  5. HTTP トリガーを使用して関数をデプロイし、未認証アクセスを許可します。

    gcloud functions deploy multiply-function \
        --gen2 \
        --runtime python310 \
        --entry-point=multiply \
        --trigger-http \
        --allow-unauthenticated

    関数のデプロイには数分かかる場合があります。また、Google Cloud コンソールで Cloud Functions インターフェースを使用して関数をデプロイできます。

  6. multiply 関数がデプロイされたら、httpsTrigger.url プロパティを確認できます。

    gcloud functions describe multiply-function \
        --gen2\
        --format="value(serviceConfig.uri)"
  7. URL を保存します。これは、後半の演習でワークフローのソースファイルに追加する必要があります。

  8. 次の curl コマンドを使用して、この関数を試すことができます。

    curl -X POST MULTIPLY_FUNCTION_URL \
        -H "Authorization: Bearer $(gcloud auth print-identity-token)" \
        -H "Content-Type: application/json" \
        -d '{"input": 5}'
    

    数値 10 が返されます。

ワークフローで 2 つの Cloud Functions サービスを接続する

ワークフローは、ワークフロー構文で記述された一連のステップで構成され、YAML 形式または JSON 形式のいずれでも記述できます。これがワークフローの定義です。詳細な説明については、構文リファレンスのページをご覧ください。

  1. ホーム ディレクトリに戻ります。

    cd ~
    
  2. 次の内容を含むテキスト ファイルを workflow.yaml という名前で作成します。

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - return_result:
        return: ${multiply_result}
    
    • RANDOMGEN_FUNCTION_URL は、randomgen 関数の URL に置き換えます。
    • MULTIPLY_FUNCTION_URL は、multiply 関数の URL に置き換えます。

    このソースファイルにより、2 つの HTTP 関数がリンクされ、最終結果が返されます。

  3. ワークフローを作成したら、デプロイして実行の準備ができます。

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml

    WORKFLOW_NAME は、ワークフローの名前に置き換えます。

  4. ワークフローを実行します。

    gcloud workflows run WORKFLOW_NAME
    

    実行とは、ワークフローの定義に含まれるロジックを 1 回だけ実行することです。すべてのワークフローの実行は独立しており、Workflows の迅速なスケーリングにより、多数の同時実行が可能になります。

    ワークフローの実行後、出力は次のようになります。

    result: '{"body":{"multiplied":120},"code":200,"headers":{"Alt-Svc":"h3-29=\":443\";
    ...
    startTime: '2021-05-05T14:17:39.135251700Z'
    state: SUCCEEDED
    ...
    

ワークフローでパブリック REST サービスを接続する

既存のワークフローを更新し、数式を評価できるパブリック REST API(math.js)を接続します。例: curl https://api.mathjs.org/v4/?'expr=log(56)'

ワークフローをデプロイしたため、Google Cloud コンソールの [ワークフロー] ページからワークフローを編集することもできます。

  1. ワークフローのソースファイルを編集し、次の内容で置き換えます。

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - log_function:
        call: http.get
        args:
            url: https://api.mathjs.org/v4/
            query:
                expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
        result: log_result
    - return_result:
        return: ${log_result}
    
    • RANDOMGEN_FUNCTION_URL は、randomgen 関数の URL に置き換えます。
    • MULTIPLY_FUNCTION_URL は、multiply 関数の URL に置き換えます。

    これにより、外部 REST サービスが Cloud Functions サービスにリンクされ、最終結果が返されます。

  2. 変更されたワークフローをデプロイします。

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml

Cloud Run サービスをデプロイする

HTTP リクエストを受信後に JSON 本文から input を抽出してその math.floor を計算し、結果を返す Cloud Run サービスをデプロイします。

  1. floor という名前のディレクトリを作成し、そのディレクトリに移動します。

    mkdir ~/floor
    cd ~/floor
    
  2. 次の Python コードを含むテキスト ファイルを 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)))

  3. 同じディレクトリに、次の内容の 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

  4. Docker コンテナ イメージを保存できる Artifact Registry 標準リポジトリを作成します。

    gcloud artifacts repositories create REPOSITORY \
        --repository-format=docker \
        --location=${REGION}

    REPOSITORY は、リポジトリの一意の名前で置き換えます。

  5. コンテナ イメージをビルドします。

    export SERVICE_NAME=floor
    gcloud builds submit --tag ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}
    
  6. コンテナ イメージを Cloud Run にデプロイし、認証された呼び出しのみが受け入れられるようにします。

    gcloud run deploy ${SERVICE_NAME} \
        --image ${REGION}-docker.pkg.dev/PROJECT_ID/REPOSITORY/${SERVICE_NAME}:latest \
        --platform managed \
        --no-allow-unauthenticated

サービス URL が表示されたら、デプロイは完了しています。ワークフロー定義を更新するときに、この URL を指定する必要があります。

ワークフローで Cloud Run サービスを接続する

既存のワークフローを更新して、Cloud Run サービスの URL を指定します。

  1. ワークフローのソースファイルを編集し、次の内容で置き換えます。

    - randomgen_function:
        call: http.get
        args:
            url: RANDOMGEN_FUNCTION_URL
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: MULTIPLY_FUNCTION_URL
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - log_function:
        call: http.get
        args:
            url: https://api.mathjs.org/v4/
            query:
                expr: ${"log(" + string(multiply_result.body.multiplied) + ")"}
        result: log_result
    - floor_function:
        call: http.post
        args:
            url: CLOUD_RUN_SERVICE_URL
            auth:
                type: OIDC
            body:
                input: ${log_result.body}
        result: floor_result
    - create_output_map:
        assign:
          - outputMap:
              randomResult: ${randomgen_result}
              multiplyResult: ${multiply_result}
              logResult: ${log_result}
              floorResult: ${floor_result}
    - return_output:
        return: ${outputMap}
    
    • RANDOMGEN_FUNCTION_URL は、randomgen 関数の URL に置き換えます。
    • MULTIPLY_FUNCTION_URL は、multiply 関数の URL に置き換えます。
    • CLOUD_RUN_SERVICE_URL は、Cloud Run サービス URL に置き換えます。

    これにより、ワークフローで Cloud Run サービスが接続されます。auth キーを使用すると、Cloud Run サービスの呼び出しで認証トークンが渡されます。詳細については、ワークフローから認証済みリクエストを行うをご覧ください。

  2. 変更されたワークフローをデプロイします。

    gcloud workflows deploy WORKFLOW_NAME \
        --source=workflow.yaml
  3. 最終ワークフローを実行します。

    gcloud workflows run WORKFLOW_NAME

    出力は次のようになります。

    result: '{"Floor":{"body":"4","code":200
      ...
      "Log":{"body":"4.02535169073515","code":200
      ...
      "Multiply":{"body":{"multiplied":56},"code":200
      ...
      "Random":{"body":{"random":28},"code":200
      ...
    startTime: '2023-11-13T21:22:56.782669001Z'
    state: SUCCEEDED
    

これで完了です。一連のサービスを接続するワークフローのデプロイと実行が完了しました。

式、条件付きジャンプ、Base64 エンコード / デコード、サブワークフローなどを使用して複雑なワークフローを作成するには、Workflows 構文リファレンス標準ライブラリの概要をご覧ください。

クリーンアップ

このチュートリアル用に新規プロジェクトを作成した場合は、そのプロジェクトを削除します。既存のプロジェクトを使用し、このチュートリアルで変更を加えずに残す場合は、チュートリアル用に作成したリソースを削除します

プロジェクトの削除

課金をなくす最も簡単な方法は、チュートリアル用に作成したプロジェクトを削除することです。

プロジェクトを削除するには:

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

チュートリアル リソースの削除

次のステップ