Terraform v0.8.6でAWS Step Functionsに対応します

Terraform

はじめに

こんにちは、中山です。

次期Terraformのリリースバージョンであるv0.8.6でAWS Step Functions用リソースが取り込まれました。今回導入されたリソースは以下の2つです。

リソース名 用途
aws_sfn_activity Activityの作成
aws_sfn_state_machine State Machineの作成

早速使ってみたので本エントリでまとめたいと思います。サンプルとなるコードをGitHubに作成しました。ご自由にお使いください。内容はLambda関数の作成とStep FunctionsからそのLambda関数を呼び出しているだけのシンプルなものです。

執筆時点(2017/02/03)ではまだv0.8.6はリリースされていないため、自分でTerraformのバイナリをコンパイルしておいてください。このPRが取り込まれたコミットハッシュ値は「4da1451971125397b8d9d166b33ef1e3b55fd456」です。

AWS Step Functions関連リソースの引数

新規に導入されたStep Functions関連リソースで設定可能な各種引数は以下の通りです。

  • aws_sfn_activity
設定 必須の有無
name Activity名 Yes
  • aws_sfn_state_machine
設定 必須の有無
name State Machine名 Yes
definition State Languageで記述したState Machineの定義 Yes
role_arn State Machineに関連付けるIAM Role Yes

使ってみる

早速使ってみましょう。上記リポジトリを元にStep Functionsと関連する内容について解説させていただきます。

  • iam.tf
data "aws_iam_policy_document" "lambda" {
  statement {
    sid     = "LambdaAssumeRolePolicy"
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals = {
      type        = "Service"
      identifiers = ["lambda.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "lambda" {
  name               = "${var.env}-lambda-role"
  assume_role_policy = "${data.aws_iam_policy_document.lambda.json}"
}

resource "aws_iam_policy_attachment" "lambda" {
  name       = "LambdaBasicExecRole"
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
  roles      = ["${aws_iam_role.lambda.name}"]
}

data "aws_iam_policy_document" "sfn" {
  statement {
    sid     = "SFNAssumeRolePolicy"
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals = {
      type        = "Service"
      identifiers = ["states.${var.region}.amazonaws.com"]
    }
  }
}

resource "aws_iam_role" "sfn" {
  name               = "${var.env}-sfn-role"
  assume_role_policy = "${data.aws_iam_policy_document.sfn.json}"
}

resource "aws_iam_policy_attachment" "sfn" {
  name       = "AWSLambdaRole"
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaRole"
  roles      = ["${aws_iam_role.sfn.name}"]
}

Step FunctionsとLambda関数用のIAM Roleを作成しています。あまり特筆すべきところもないのですが、Step FunctionsのAssumeRoleではリージョンを含める必要があるという点は注意してください。Step FunctionsにはLambda関数をInvokeする権限を付与しています。ちょうどマネージドポリシーでいい感じのもの( AWSLambdaRole )があったため、 aws_iam_policy_attachment リソースを利用して、Step FunctionsのIAM Roleに付与しています。内容は以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Action": [
            "lambda:InvokeFunction"
        ],
        "Resource": ["*"]
    }]
}
  • lambda.tf
resource "aws_lambda_function" "lambda" {
  filename         = "${path.module}/src/lambda.zip"
  source_code_hash = "${base64sha256(file("${path.module}/src/lambda.zip"))}"
  function_name    = "${var.env}-lambda"
  role             = "${aws_iam_role.lambda.arn}"
  handler          = "handler.hello"
  runtime          = "python2.7"
}

Lambda関数自体は src ディレクトリ以下に設置しています。aws_lambda_functionリソースのドキュメントにも記載されていますが、 source_code_hash 引数を利用するとLambda関数のアップデートに対応してくれるので便利です。

  • sfn.tf
resource "aws_sfn_state_machine" "sfn" {
  name     = "${var.env}-sfn"
  role_arn = "${aws_iam_role.sfn.arn}"

  definition = <<EOT
{
  "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda Function",
  "StartAt": "HelloWorld",
  "States": {
    "HelloWorld": {
      "Type": "Task",
      "Resource": "${aws_lambda_function.lambda.arn}",
      "End": true
    }
  }
}
EOT
}

State Machineを定義しています。DefinitionのTaskで作成したLambda関数のARNを指定しています。変数としてARNを指定できるのはなかなか便利ですね。

動作確認

いつも通り plan / apply 実施後、AWS CLIを利用してStep Functionsの動作を確認してみます。

  • State Machineが作成されたことを確認
$ aws stepfunctions list-state-machines
{
    "stateMachines": [
        {
            "creationDate": 1486127930.723,
            "stateMachineArn": "arn:aws:states:ap-northeast-1:************:stateMachine:tf-sfn-demo-sfn",
            "name": "tf-sfn-demo-sfn"
        }
    ]
}
  • State MachineのDefinitionが意図したものになっていることを確認
$ aws stepfunctions describe-state-machine \
  --state-machine-arn "$(aws stepfunctions list-state-machines \
    --query 'stateMachines[?name==`tf-sfn-demo-sfn`].stateMachineArn' \
    --output text)"
{
    "status": "ACTIVE",
    "definition": "{\n  \"Comment\": \"A Hello World example of the Amazon States Language using an AWS Lambda Function\",\n  \"StartAt\": \"HelloWorld\",\n  \"States\": {\n    \"HelloWorld\": {\n      \"Type\": \"Task\",\n      \"Resource\": \"arn:aws:lambda:ap-northeast-1:************:function:tf-sfn-demo-lambda\",\n      \"End\": true\n    }\n  }\n}\n",
    "name": "tf-sfn-demo-sfn",
    "roleArn": "arn:aws:iam::************:role/tf-sfn-demo-sfn-role",
    "stateMachineArn": "arn:aws:states:ap-northeast-1:************:stateMachine:tf-sfn-demo-sfn",
    "creationDate": 1486127930.723
}
  • State Machineの実行
$ aws stepfunctions start-execution \
  --state-machine-arn "$(aws stepfunctions list-state-machines \
    --query 'stateMachines[?name==`tf-sfn-demo-sfn`].stateMachineArn' \
    --output text)" \
  --input "$(jo hoge=fuga)"
{
    "startDate": 1486128383.711,
    "executionArn": "arn:aws:states:ap-northeast-1:************:execution:tf-sfn-demo-sfn:19f38408-ae17-4b34-a1fc-f6d43d78f161"
}
  • 実行結果が意図したものになっていることを確認
$ aws stepfunctions describe-execution \
  --execution-arn arn:aws:states:ap-northeast-1:************:execution:tf-sfn-demo-sfn:19f38408-ae17-4b34-a1fc-f6d43d78f161
{
    "status": "SUCCEEDED",
    "startDate": 1486128383.711,
    "name": "19f38408-ae17-4b34-a1fc-f6d43d78f161",
    "executionArn": "arn:aws:states:ap-northeast-1:************:execution:tf-sfn-demo-sfn:19f38408-ae17-4b34-a1fc-f6d43d78f161",
    "stateMachineArn": "arn:aws:states:ap-northeast-1:************:stateMachine:tf-sfn-demo-sfn",
    "stopDate": 1486128384.934,
    "output": "\"Invoked with this event: {u'hoge': u'fuga'}\"",
    "input": "{\"hoge\":\"fuga\"}"
}

まとめ

いかがだったでしょうか。

Terraform v0.8.6で導入されるStep Functionsについてご紹介しました。State Machineの作成用途であれば便利に使えそうです。今後のアップデートに注目していきたいと思います。

本エントリがみなさんの参考になれば幸いに思います。