NECネッツエスアイ

TerraformでAWS Data Pipelineを作成するのが大変だった話

更新日付:2022年6月29日

皆さま、はじめまして、DXビジネス推進本部 運用開発グループの木村です。TerraformでAWS Data Pipelineを作成するのが思っていたより大変だったので、作成する際に自分が感じたことと最終的にどうやって作成したのか共有したいと思います。

Terraformとは

TerraformはHashicorp社により開発されたIaCツールの一種です。Terraformではインフラの構成をコードで宣言することで、手動で操作することなくインフラ構成を自動で管理できます。インフラの構築、更新、破棄、いずれもTerraformではコードにより宣言して実行することができます。

TerraformでData Pipelineを作成しようと思った経緯

TerraformでData Pipelineを作成しようと思ったのは、DynamoDBのデータをS3にアーカイブするためです。DynamoDBからS3へのデータエクスポート方法を色々調べた結果、今回はData Pipelineで実施するのが良さそうという結論になり、DynamoDBやS3といったAWSリソースは全てTerraformで管理していたため、Data PipelineもTerraformで管理することになりました。

TerraformでData Pipelineを作成

Data Pipelineのtfファイル作成

まず、Data Pipeline関係のTerraformリソースは以下の2種類になります。

aws_datapipeline_pipelineでは特に設定する値は無いので、aws_datapipeline_pipeline_definitionの方でDynamoDBのデータをS3にエクスポートするための設定を記載していくのですが…公式のサンプル見てもkeyとstring_valueの項目に色々と設定値が書かれているだけで、全然使い方が分かりませんでした。

公式のサンプル
resource "aws_datapipeline_pipeline" "default" {
  name = "tf-pipeline-default"
}

resource "aws_datapipeline_pipeline_definition" "example" {
  pipeline_id = aws_datapipeline_pipeline.default.id
  pipeline_object {
    id   = "Default"
    name = "Default"
    field {
      key          = "workerGroup"
      string_value = "workerGroup"
    }
  }
  pipeline_object {
    id   = "Schedule"
    name = "Schedule"
    field {
      key          = "startDateTime"
      string_value = "2012-12-12T00:00:00"
    }
    field {
      key          = "type"
      string_value = "Schedule"
    }
    field {
      key          = "period"
      string_value = "1 hour"
    }
    field {
      key          = "endDateTime"
      string_value = "2012-12-21T18:00:00"
    }
  }
  pipeline_object {
    id   = "SayHello"
    name = "SayHello"
    field {
      key          = "type"
      string_value = "ShellCommandActivity"
    }
    field {
      key          = "command"
      string_value = "echo hello"
    }
    field {
      key          = "parent"
      string_value = "Default"
    }
    field {
      key          = "schedule"
      string_value = "Schedule"
    }
  }
}

Data Pipelineの公式ドキュメントにPipeline Object Referenceがあり、ここに記載されている値をkeyとかに設定すれば良いらしいのですが…はっきり言ってかなり面倒ですし、かなり大変だと思います。というわけで自分はひとまずAWSマネジメントコンソールで作成してから、terraform importコマンド等で後からTerraform管理対象にすることにしました。

【参考】DynamoDB、S3、IAMのtfファイル

参考までにDynamoDB、S3、Data Pipeline用のIAMのtfファイルも記載しておきます。

dynamodb.tf
resource "aws_dynamodb_table" "dynamodb_sample" {
  name         = "dynamodb_sample"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "PartitionKey"
  range_key    = "RowKey"

  attribute {
    name = "PartitionKey"
    type = "S"
  }

  attribute {
    name = "RowKey"
    type = "S"
  }
}
s3.tf
resource "aws_s3_bucket" "sample_bucket" {
  bucket        = "sample_bucket"
  force_destroy = true
}

resource "aws_s3_bucket_public_access_block" "sample_bucket_public_access_block" {
  bucket = aws_s3_bucket.sample_bucket.id

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
iam.tf

resource "aws_iam_role" "sample_datapipeline_role" {
    name               = "sample_datapipeline_role"
    assume_role_policy = <<EOF
  {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "datapipeline.amazonaws.com",
                      "elasticmapreduce.amazonaws.com"
                  ]
              },
              "Action": "sts:AssumeRole"
          }
      ]
  }
  EOF
  }
  
  resource "aws_iam_role_policy_attachment" "sample_datapipeline_policy_attachment" {
    policy_arn = "arn:aws:iam::aws:policy/service-role/AWSDataPipelineRole"
    role       = aws_iam_role.sample_datapipeline_role.name
  }
  
  resource "aws_iam_role" "sample_datapipeline_role_for_ec2" {
    name               = "sample_datapipeline_role_for_ec2"
    assume_role_policy = <<EOF
  {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Principal": {
                  "Service": "ec2.amazonaws.com"
              },
              "Action": "sts:AssumeRole"
          }
      ]
  }
  EOF
  }
  
  resource "aws_iam_role_policy_attachment" "sample_datapipeline_role_for_ec2_policy_attachment" {
    policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforDataPipelineRole"
    role       = aws_iam_role.sample_datapipeline_role_for_ec2.name
  }
  
  resource "aws_iam_instance_profile" "sample_datapipeline_instance_profile" {
    name = aws_iam_role.sample_datapipeline_role_for_ec2.name
    role = aws_iam_role.sample_datapipeline_role_for_ec2.name
  }

諦めてAWSマネジメントコンソールから作成する

AWSマネジメントコンソールでData Pipelineの作成

マネジメントコンソールでCreate new pipelineをクリックし、Export DynamoDB table to S3 Data Pipeline テンプレートを選択すれば、後は表示通りにDynamoDBテーブル名やS3バケット名、Schedule、使用するIAMロール等を入力するだけで簡単に作成できます。

入力が完了したらActivateをクリックしてData Pipelineを作成し、S3にエクスポートされることが確認できたら完了です。

マネジメントコンソールで作成したData PipelineをTerraform管理にする

マネジメントコンソールで作成したData Pipelineをtfstateに反映するためにterraform importを実行し、次にterraform state showを実行して表示されたコードをtfファイルに記載していきます。まずはterraform importを実行するために、Data Pipeline用のtfファイルを作成します。

datapipeline.tf
resource "aws_datapipeline_pipeline" "sample_datapipeline" {

}

resource "aws_datapipeline_pipeline_definition" "sample_datapipeline_definition" {

}

terraform import

以下のterraform importコマンドを実行してtfstateに反映します。

$ terraform import aws_datapipeline_pipeline.sample_datapipeline <Pipeline ID>
$ terraform import aws_datapipeline_pipeline_definition.sample_datapipeline_definition <Pipeline ID>

terraform state show

以下のterraform state showコマンドを実行することで、マネジメントコンソールで作成したData Pipelineがtfファイルだとどんなコードになるか確認できます。後は表示されたコードをdatapipeline.tfにコピーすれば、マネジメントコンソールで作成したData PipelineをTerraformの管理下におくことができます。

$ terraform state show aws_datapipeline_pipeline.sample_datapipeline
# aws_datapipeline_pipeline.sample_datapipeline:
resource "aws_datapipeline_pipeline" "sample_datapipeline" {
    id       = "df-03319771VET6AXN3W3N7"
    name     = "iot_datapipeline_dynamodb_export_to_s3_dev"
    tags     = {}
    tags_all = {}
}

$ terraform state show aws_datapipeline_pipeline_definition.sample_datapipeline_definition
# aws_datapipeline_pipeline_definition.sample_datapipeline_definition:
resource "aws_datapipeline_pipeline_definition" "sample_datapipeline_definition" {
...(200行くらいあるので省略)
}

DynamoDBやS3名をTerraformリソースに修正

terraform state showコマンドで表示されるコードはDynamoDBテーブル名やS3バケット名などがベタ書きされているので、aws_dynamodb_table.dynamodb_sample.nameやaws_s3_bucket.sample_bucket.idなどに置換しておくと良いです。

まとめ

Data PipelineをTerraformで作成するのはかなり大変だと思うので、どうしてもTerraformで管理したいときには、一度マネジメントコンソールで作成してからterraformのコマンドを利用してtfファイルを作成してしまうのがおすすめです。一度コードにしてしまえば、出力先のS3を変更したり、Scheduleを変更する程度であればtfファイルを編集し、Terraformで簡単に更新することができます。

関連記事

TOP