見出し画像

AWS_Step Functionsのステップ間で値を受け渡す(ECS) #493

こちらでまとめた内容の応用編です。

値の受け渡しにおいて、StepFunctionsでECSタスクを起動して、受け取った値をコンテナ内で使う方法を整理します。

StepFunctionsの設定

まず、ECS上のサービスを呼び出すStep Functionsの設定を確認します。ここでは、ECS上のAPIを呼び出すために、Step FunctionsがLambdaではなく、ECSのタスクを実行する設定を使用します。

{
  "StartAt": "RunEcsTask",
  "States": {
    "RunEcsTask": {
      "Type": "Task",
      "Resource": "arn:aws:states:::ecs:runTask.sync",  // ECSを実行する
      "Parameters": {
        "Cluster": "my-ecs-cluster",
        "TaskDefinition": "my-task-definition",
        "Overrides": {
          "ContainerOverrides": [
            {
              "Name": "my-container",
              "Command": ["my-golang-app"],
              "Environment": [
                {
                  "Name": "INPUT_DATA",
                  "Value.$": "$"  // ステップの全データを環境変数で渡す
                }
              ]
            }
          ]
        },
        "LaunchType": "FARGATE"
      },
      "End": true
    }
  }
}

ポイントは、受け取ったデータをコンテナの環境変数(Environment)として設定している点です。ContainerOverridesでコンテナの設定を上書きできるので、ここで環境変数として任意の値をセットできます。後はアプリケーションコードで環境変数をよしなに処理できる、ということになります。

上記の設定についてもう少し解説します。

Overridesとは

これはECSタスク全体に対して上書きする設定です。タスク定義に指定されているパラメータ(環境変数、コマンド、リソースの制限など)を上書きして、新しい値を指定することができます。

コンテナごとに上書きしたい内容が異なるケースもあるので、この中で制御します。

ContainerOverridesとは

これはECSタスク内で実行される特定のコンテナの設定を上書きします。ECSタスクには複数のコンテナが含まれる場合がありますが、ここでは特定のコンテナに対してのみ環境変数やコマンドを指定できます。

上記の例では「my-container」というコンテナの「Command」と「Environment」が上書きされています。

  • Command: デフォルトのコンテナコマンドを上書きし、my-golang-appというバイナリを実行します。

  • Environment: INPUT_DATA という環境変数を設定し、その値をStep Functionsの入力データから動的に取得します(Value.$ によりStep Functionsの入力から値を渡す)。

ECS上のGolangアプリケーション

例として、アプリケーション側でこの受け渡された環境変数を使うコードを書いてみます。言語は何でもいいですが、ここではGolangで記述します。

INPUT_DATAには以下の形式で値が入っているとします。

{
  "message": "Hello from FirstLambda",
  "statusCode": 200
}
package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
)

type InputData struct {
	Message    string `json:"message"`
	StatusCode int    `json:"statusCode"`
}

func main() {
	// Step Functionsから渡された環境変数 "INPUT_DATA" を取得
	inputDataEnv := os.Getenv("INPUT_DATA")
	if inputDataEnv == "" {
		log.Fatal("No input data received")
	}

	// JSONデータを構造体にマッピング
	var inputData InputData
	err := json.Unmarshal([]byte(inputDataEnv), &inputData)
	if err != nil {
		log.Fatalf("Error parsing input data: %v", err)
	}

	// データを処理
	fmt.Printf("Received Message: %s\n", inputData.Message)
	fmt.Printf("Received Status Code: %d\n", inputData.StatusCode)

	// 処理結果を出力 (Step Functionsに戻す場合はS3やDynamoDBに書き込むなど)
	output := map[string]interface{}{
		"resultMessage": fmt.Sprintf("Processed: %s", inputData.Message),
		"statusCode":    inputData.StatusCode,
	}

	// 結果をJSON形式で出力
	outputJSON, err := json.Marshal(output)
	if err != nil {
		log.Fatalf("Error generating output data: %v", err)
	}

	// ここでStep Functionsの次のステップに渡せるように結果を保存
	fmt.Println(string(outputJSON))  // CloudWatch Logsなどに結果を保存
}

Golangのjson.Unmarshalは同じ文字列であれば、大文字小文字の区別なくJSON <-> 構造体を上手に置換してくれます。

これで、StepFunctionsから渡された値をECS上のアプリケーションで使うことができそうです。

ここまでお読みいただきありがとうございました!!

いいなと思ったら応援しよう!