4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Terraform】ECS自動デプロイ - Terraform編 -

Posted at

参考文献

ツリー図

.
├── acm.tf
├── alb.tf
├── backend.tf
├── ecs.tf
├── files
│   └── task-definitions
│       └── container.json
├── rds.tf
├── security_group.tf
├── terraform.tfvars
├── variables.tf
├── vpc.tf
├── vpc_gateway.tf
├── vpc_routetable.tf
└── vpc_subnet.tf

Terraform / AWS CLIコマンド

◆ AWS CLIコマンド
/// ECS
$ aws ecs list-task-definitions --region ap-northeast-1
$ aws ecs list-clusters
$ aws ecs register-task-definition --family sample-service  --cli-input-json file://container.json

/// RDS
$ mysql -h sample-rds.XXXXXX.XXXXXX.rds.amazonaws.com -P 3306 -u XXXX -p
◆ EC2インストール
$ sudo yum install git
$ yum list installed | grep mariadb
$ sudo yum remove mariadb-libs
$ sudo yum-config-manager --disable mysql57-community
$ sudo yum-config-manager --enable mysql80-community
$ sudo yum install -y mysql-community-client
$ mysql --version

各tfファイル

◆ ecs.tf
ecs.tf
# ====================
# Cluster
# ====================
resource "aws_ecs_cluster" "sample-cluster" {
  name = "sample-cluster"
}

# ====================
# CloudWatch logs
# ====================
resource "aws_cloudwatch_log_group" "sample-log-group" {
  name = "sample-log-group"
  tags = {}
}

# ====================
# task_definition
# ====================
resource "aws_ecs_task_definition" "sample-task-definition" {
  //family:複数のタスク定義をまとめる際に使用
  family                   = "sample-service"
  requires_compatibilities = ["FARGATE"]
  network_mode             = "awsvpc"
  task_role_arn            = "arn:aws:iam::${var.aws_account_id}:role/ecsTaskExecutionRole"
  execution_role_arn       = "arn:aws:iam::${var.aws_account_id}:role/ecsTaskExecutionRole"
  cpu                      = 1024
  memory                   = 2048
  container_definitions    = file("files/task-definitions/container.json")
}

# ====================
# Service
# ====================
resource "aws_ecs_service" "sample-service" {
  cluster                            = aws_ecs_cluster.sample-cluster.id
  launch_type                        = "FARGATE"
  deployment_minimum_healthy_percent = 100
  deployment_maximum_percent         = 200
  name                               = "sample-service"
  task_definition                    = aws_ecs_task_definition.sample-task-definition.arn
  //desired_count:タスク数
  desired_count = 1

  /// autoscalingで動的に変化する値を無視する ///
  lifecycle {
    ignore_changes = [desired_count, task_definition]
  }

  load_balancer {
    target_group_arn = aws_alb_target_group.sample-target-group.arn
    container_name   = "sample-container"
    container_port   = 80
  }

  network_configuration {
    subnets          = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
    security_groups  = [aws_security_group.sample-security-group-app.id, aws_security_group.sample-security-group-rds.id]
    assign_public_ip = "true"
  }
}
◆ container.json
files/container.json
[
    {
        "image": "XXXXXX.dkr.ecr.XXXXXX.amazonaws.com/sample_dev:latest",
        "logConfiguration": {
            "logDriver": "awslogs",
            "options": {
                "awslogs-group": "sample-log-group",
                "awslogs-region": "ap-northeast-1",
                "awslogs-stream-prefix": "ecs"
            }
        },
        "cpu": 512,
        "memory": 1024,
        "mountPoints": [],
        "environment": [],
        "networkMode": "awsvpc",
        "name": "sample-container",
        "essential": true,
        "portMappings": [
            {
                "hostPort": 80,
                "containerPort": 80,
                "protocol": "tcp"
            }
        ],
        "command": [
            "/usr/bin/supervisord"
        ]
    }
]
◆ alb.tf
alb.tf
# ====================
# ALB
# ====================
resource "aws_alb" "sample-alb" {
  name                       = "sample-alb"
  security_groups            = [aws_security_group.sample-security-group-alb.id]
  subnets                    = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
  internal                   = false
  enable_deletion_protection = false
}

# ====================
# Target Group
# ====================
resource "aws_alb_target_group" "sample-target-group" {
  name        = "sample-target-group"
  depends_on  = [aws_alb.sample-alb]
  port        = 80
  protocol    = "HTTP"
  vpc_id      = aws_vpc.sample-vpc.id
  target_type = "ip"

  health_check {
    protocol            = "HTTP"
    path                = "/ping"
    port                = 80
    unhealthy_threshold = 5
    timeout             = 5
    interval            = 10
    matcher             = 200
  }
}

# ====================
# ALB Listener HTTP
# ====================
resource "aws_alb_listener" "sample-alb-http" {
  load_balancer_arn = aws_alb.sample-alb.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    target_group_arn = aws_alb_target_group.sample-target-group.arn
    type             = "forward"
  }
}

# ====================
# ALB Listener HTTPS
# ====================
resource "aws_alb_listener" "sample-alb-https" {
  load_balancer_arn = aws_alb.sample-alb.arn
  port              = "443"
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2015-05"
  certificate_arn   = aws_acm_certificate.sample-acm.arn

  default_action {
    target_group_arn = aws_alb_target_group.sample-target-group.arn
    type             = "forward"
  }
}

# ====================
# listener_rule
# ====================
resource "aws_alb_listener_rule" "sample-listener-rule" {
  depends_on   = [aws_alb_target_group.sample-target-group]
  listener_arn = aws_alb_listener.sample-alb-http.arn
  priority     = 100

  action {
    type             = "forward"
    target_group_arn = aws_alb_target_group.sample-target-group.arn
  }
  condition {
    path_pattern {
      values = ["*"]
    }
  }
}
◆ acm.tf
acm.tf
# ====================
# ACM
# ====================
resource "aws_acm_certificate" "sample-acm" {
  domain_name               = "sample.com"
  subject_alternative_names = ["*.sample.com"]
  validation_method         = "DNS"

  lifecycle {
    create_before_destroy = true
  }
}
◆ rds.tf
rds.tf
# ====================
# db_subnet_group
# ====================
resource "aws_db_subnet_group" "sample-rds-subnet-group" {
  name        = "sample-rds-subnet-group"
  description = "sample-rds-subnet-group"
  subnet_ids  = [aws_subnet.sample-subnet-1.id, aws_subnet.sample-subnet-2.id]
}

# ====================
# db_instance
# ====================
resource "aws_db_instance" "sample-rds" {
  identifier             = "sample-rds"
  allocated_storage      = 20
  storage_type           = "gp2"
  engine                 = "mysql"
  engine_version         = "5.7"
  instance_class         = "db.t2.micro"
  username               = "test"
  password               = "XXXXXX"
  parameter_group_name   = "default.mysql5.7"
  port                   = "3306"
  vpc_security_group_ids = [aws_security_group.sample-security-group-rds.id]
  db_subnet_group_name   = "${aws_db_subnet_group.sample-rds-subnet-group.name}"
  skip_final_snapshot    = true
}
◆ security_group.tf
security_group.tf
# ====================
# Security Group (app)
# ====================
resource "aws_security_group" "sample-security-group-app" {
  vpc_id = aws_vpc.sample-vpc.id
  name   = "sample-security-group-app"

  ingress {
    from_port       = 80
    to_port         = 80
    protocol        = "tcp"
    cidr_blocks     = ["X.X.X.X/16"]
    security_groups = [aws_security_group.sample-security-group-alb.id]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "sample-security-group-app"
  }
}



# ====================
# Security Group(ALB)
# ====================
resource "aws_security_group" "sample-security-group-alb" {
  name        = "sample-security-group-alb"
  description = "sample-security-group-alb"
  vpc_id      = aws_vpc.sample-vpc.id

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 443
    to_port     = 443
    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 = "sample-security-group-alb"
  }
}

# ====================
# Security Group (RDS)
# ====================
resource "aws_security_group" "sample-security-group-rds" {
  name        = "sample-security-group-rds"
  description = "sample-security-group-rds"
  vpc_id      = aws_vpc.sample-vpc.id
  ingress {
    from_port       = 3306
    to_port         = 3306
    protocol        = "tcp"
    security_groups = [aws_security_group.sample-security-group-app.id]
  }
  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["X.X.X.X/16"]
    description = "sample-security-group-rds"
  }
  ingress {
    from_port   = 3306
    to_port     = 3306
    protocol    = "tcp"
    cidr_blocks = ["X.X.X.X/28"]
    description = "sample-security-group-rds"
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name = "sample-security-group-rds"
  }
}
◆ vpc.tf
vpc.tf
# ====================
# VPC
# ====================
resource "aws_vpc" "sample-vpc" {
  cidr_block = "X.X.X.X/16"

  tags = {
    Name = "sample-vpc"
  }
}
◆ vpc_subnet.tf
vpc_subnet.tf
# ====================
# Subnet
# ====================
resource "aws_subnet" "sample-subnet-1" {
  cidr_block        = "X.X.X.X/24"
  availability_zone = "ap-northeast-1a"
  vpc_id            = aws_vpc.sample-vpc.id

  tags = {
    Name = "sample-subnet-1"
  }
}

resource "aws_subnet" "sample-subnet-2" {
  cidr_block        = "X.X.X.X/24"
  availability_zone = "ap-northeast-1c"
  vpc_id            = aws_vpc.sample-vpc.id

  tags = {
    Name = "sample-subnet-2"
  }
}
◆ vpc_routetable.tf
vpc_routetable.tf
# ====================
# Subnet
# ====================
resource "aws_subnet" "sample-subnet-1" {
  cidr_block        = "X.X.X.X/24"
  availability_zone = "ap-northeast-1a"
  vpc_id            = aws_vpc.sample-vpc.id

  tags = {
    Name = "sample-subnet-1"
  }
}

resource "aws_subnet" "sample-subnet-2" {
  cidr_block        = "X.X.X.X/24"
  availability_zone = "ap-northeast-1c"
  vpc_id            = aws_vpc.sample-vpc.id

  tags = {
    Name = "sample-subnet-2"
  }
}
◆ vpc_gateway.tf
vpc_gateway.tf
# ====================
# Internet Gateway
# ====================
resource "aws_internet_gateway" "sample-gateway" {
  vpc_id = aws_vpc.sample-vpc.id

  tags = {
    Name = "sample-gateway"
  }
}
◆ variables.tf
variables.tf
/// tfファイルで使用する変数定義 ///
/// 変数の中身はterraform.tfvarsに記載 ///

variable "aws_access_key" {}
variable "aws_secret_key" {}
variable "region" {}

variable "aws_account_id" {}
◆ backend.tf
backend.tf
provider "aws" {
  access_key = "${var.aws_access_key}"
  secret_key = "${var.aws_secret_key}"
  region     = "${var.region}"
  profile    = "s3-profile"
}

terraform {
  backend "s3" {
    bucket                  = "sample-s3-file"
    key                     = "terraform.tfstate"
    region                  = "ap-northeast-1"
    shared_credentials_file = "~/.aws/credentials"
    profile                 = "s3-profile"
  }
}
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?