Workflows を使用したサービスの接続

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

目標

このチュートリアルでは、一度に 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 環境に制約を適用すると、このドキュメントの一部の手順が正しく機能しない場合があります。その場合、パブリック IP アドレスやサービス アカウント キーを作成するようなタスクを完了できない場合があります。制約に関するエラーを返すリクエストを行う場合は、制約がある Google Cloud 環境でアプリケーションを開発する方法をご覧ください。

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

    プロジェクト セレクタに移動

  3. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  4. Cloud Build, Cloud Functions, Cloud Run, Cloud Storage, Container Registry, Workflows API を有効にします。

    API を有効にする

  5. Cloud SDK をインストールして初期化します。
  6. Google Cloud Console の [プロジェクト セレクタ] ページで、Google Cloud プロジェクトを選択または作成します。

    プロジェクト セレクタに移動

  7. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトに対して課金が有効になっていることを確認する方法を学習する

  8. Cloud Build, Cloud Functions, Cloud Run, Cloud Storage, Container Registry, Workflows API を有効にします。

    API を有効にする

  9. Cloud SDK をインストールして初期化します。
  10. gcloud コンポーネントを更新します。
    gcloud components update
  11. 自分のアカウントでログインします。
    gcloud auth login
  12. Workflows が使用するサービス アカウントを作成します。

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

  13. サービス アカウントが認証済みの Cloud Run サービスを呼び出すことができるようにするには、Workflows サービス アカウントに run.invoker ロールを付与します。

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

  14. このチュートリアルで使用するデフォルトのロケーションを設定します。
    gcloud config set project PROJECT_ID
    export REGION=REGION
    gcloud config set run/region ${REGION}
    gcloud config set workflows/location ${REGION}
    

    次のように置き換えます。

    • PROJECT_ID は、Google Cloud プロジェクト ID に置き換えます。
    • REGION は、選択したサポート対象の Workflows のロケーションに置き換えます。

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

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

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

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

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

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

    gcloud functions deploy randomgen \
    --runtime python37 \
    --trigger-http \
    --allow-unauthenticated
    

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

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

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

    curl $(gcloud functions describe randomgen --format='value(httpsTrigger.url)')
    

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

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

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

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

    mkdir ~/multiply
    cd ~/multiply
    
  2. 次の Python コードを含むテキスト ファイルを 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)
  3. HTTP 処理用の Flask への依存関係をサポートするには、pip パッケージ マネージャー用のテキスト ファイルを作成します。ファイル名を requirements.txt にして、以下を追加します。

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

    gcloud functions deploy multiply \
    --runtime python37 \
    --trigger-http \
    --allow-unauthenticated
    

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

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

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

    curl $(gcloud functions describe multiply --format='value(httpsTrigger.url)') \
    -X POST \
    -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: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
            body:
                input: ${randomgen_result.body.random}
        result: multiply_result
    - return_result:
        return: ${multiply_result}
    

    これにより、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 サービスを接続する

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

  1. Google Cloud Console で [ワークフロー] ページを開きます。
    [ワークフロー] ページに移動

  2. 更新するワークフローの名前を選択します。

  3. ワークフローのソースを編集するには、[編集] をクリックし、[次へ] をクリックします。

  4. ワークフロー エディタのソースコードを次の内容で置き換えます。

    - randomgen_function:
        call: http.get
        args:
            url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
            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}
    

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

  5. [デプロイ] をクリックします。

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. コンテナ イメージをビルドします。

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

    gcloud run deploy ${SERVICE_NAME} \
    --image gcr.io/${GOOGLE_CLOUD_PROJECT}/${SERVICE_NAME} \
    --platform managed \
    --no-allow-unauthenticated
    

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

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

  1. Google Cloud Console で [ワークフロー] ページを開きます。
    [ワークフロー] ページに移動

  2. 更新するワークフローの名前を選択します。

  3. ワークフローのソースを編集するには、[編集] をクリックし、[次へ] をクリックします。

  4. ワークフロー エディタのソースコードを次の内容で置き換えます。

    - randomgen_function:
        call: http.get
        args:
            url: https://REGION-PROJECT_ID.cloudfunctions.net/randomgen
        result: randomgen_result
    - multiply_function:
        call: http.post
        args:
            url: https://REGION-PROJECT_ID.cloudfunctions.net/multiply
            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
    - return_result:
        return: ${floor_result}
    

    CLOUD_RUN_SERVICE_URL は、Cloud Run サービス URL に置き換えます。

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

  5. [デプロイ] をクリックします。

最終ワークフローを実行する

  1. ワークフローを更新し、サービス アカウントを渡します。

    cd ~
    gcloud workflows deploy workflow \
    --source=workflow.yaml \
    --service-account=${SERVICE_ACCOUNT}@${GOOGLE_CLOUD_PROJECT}.iam.gserviceaccount.com
    
  2. ワークフローを実行します。

    gcloud workflows run WORKFLOW_NAME
    

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

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

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

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

クリーンアップ

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

プロジェクトの削除

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

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

  1. Cloud Console で [リソースの管理] ページに移動します。

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

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

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

  1. このチュートリアルでデプロイした Cloud Run サービスを削除します。

    gcloud run services delete SERVICE_NAME

    SERVICE_NAME は、選択したサービス名です。

    Cloud Run サービスは Google Cloud Console から削除することもできます。

  2. チュートリアルを設定したときに追加した gcloud のデフォルト構成を削除します。

     gcloud config unset run/region
     gcloud config unset workflows/location
     gcloud config unset project
    

  3. このチュートリアルで作成したワークフローを削除します。

    gcloud workflows delete WORKFLOW_NAME
    
  4. gcr.io/PROJECT_ID/SERVICE_NAME という名前のコンテナ イメージを Container Registry から削除します

次のステップ