TerraformでECS FargateのApache起動をコード化してみた

TerraformでECS Fargate構築をコード化するよ!
2021.10.31

こんにちは!コンサル部のinomaso(@inomasosan)です。

以前書いた以下のブログは、AWSマネージメントコンソールによるECS構築でした。

今回は手軽にリソースを作成・破壊するためにTerraformでコード化してみました。

環境

今回実行した環境は以下の通りです。

  • macOS BigSur 11.6
  • Terraform 1.0.7
  • AWSプロバイダー 3.63.0
  • Docker Desktop 4.1.1

フォルダ構成

% tree
.
├── aws_ecs.tf
├── aws_sg_ecs-service.tf
├── aws_vpc.tf
├── container_definitions.json
├── provider.tf
└── version.tf

Terraformコード

基本的にAWSマネージメントコンソールで作成した時と同様のパラメータを設定しております。

プロバイダー設定

Terraformで使用するプロバイダー及びリージョンを指定します。

provider.tf

provider "aws" {
  ##東京リージョン
  region  = "ap-northeast-1"
}

バージョン設定

Terraform本体のバージョンを固定します。

version.tf

terraform {
  ## バージョンを固定
  required_version = "1.0.7"
}

VPC

Terraform RegistryのModuleを使用してVPCを作成します。

aws_vpc.tf

# Terraform Registry
# AWS VPC Terraform module
module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.10.0"

  name = "my-vpc"
  cidr                 = "10.0.0.0/16"
  enable_dns_hostnames = true
  enable_dns_support   = true

  azs             = ["ap-northeast-1a", "ap-northeast-1c"]
  public_subnets  = ["10.0.11.0/24", "10.0.12.0/24"]

  #デフォルトセキュリティグループのルール削除
  manage_default_security_group  = true
  default_security_group_ingress = []
  default_security_group_egress  = []
}

ECS関連

ECSのタスク定義、サービス、クラスター作成します。

aws_ecs.tf

# タスク定義
resource "aws_ecs_task_definition" "task" {
  family                   = "httpd-task"
  #0.25vCPU
  cpu                      = "256"
  #0.5GB
  memory                   = "512"
  network_mode             = "awsvpc"
  requires_compatibilities = ["FARGATE"]
  container_definitions    = file("./container_definitions.json")
}

# クラスター
resource "aws_ecs_cluster" "cluster" {
  name = "httpd-cluster"
}

# サービス
resource "aws_ecs_service" "service" {
  name                              = "httpd-service"
  cluster                           = aws_ecs_cluster.cluster.arn
  task_definition                   = aws_ecs_task_definition.task.arn
  desired_count                     = 1
  launch_type                       = "FARGATE"
  platform_version                  = "1.4.0"

  network_configuration {
    assign_public_ip = true
    security_groups  = [aws_security_group.service.id]
    subnets = module.vpc.public_subnets
  }

  ## デプロイ毎にタスク定義が更新されるため、リソース初回作成時を除き変更を無視
  lifecycle {
    ignore_changes = [task_definition]
  }
}


サービスで使用するセキュリティグループを作成します。
Apache用にHTTPポートを全許可しています。

aws_sg_ecs-task.tf

resource "aws_security_group" "service" {
  name        = "httpd-sg"
  description = "httpd-sg"
  vpc_id      = module.vpc.vpc_id
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
  
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "httpd-sg"
  }
}


Apache用のコンテナ定義となります。

container_definitions.json

[
  {
    "name": "httpd-container",
    "image": "httpd:latest",
    "essential": true,
    "memory": 128,
    "portMappings": [
      {
        "protocol": "tcp",
        "containerPort": 80
      }
    ]
  }
]

Apacheアクセス確認

タスクのパブリックIPはTerraformのステートファイルに含まれていなかったので、AWSマネージメントコンソールより確認します。

Chrome等のWebブラウザにて、パブリックIPでアクセスし、It works!と表示されることを確認できました。

まとめ

一度コード化してしまえば、リソースを手軽に作成・破壊できるので検証も捗りますね。

この記事が、どなたかのお役に立てば幸いです。それでは!