LoginSignup
0
0

More than 1 year has passed since last update.

Terraform(Fargate)でNginxをデプロイ

Last updated at Posted at 2023-02-26

はじめに

Terraformの学習用健忘録です。

ディレクトリはこちらになります。

terrformの構成

ファイル構成

ファイル構成
.
├── Dockerfile
├── nginx
│   └── index.html
└── terraform
    ├── main.tf
    ├── modules
    │   ├── bash
    │   │   └── null_resource.tf
    │   ├── ecr
    │   │   └── ecr.tf
    │   ├── ecs
    │   │   ├── ecs.tf
    │   │   ├── ecs_service.tf
    │   │   └── ecs_task_definition.tf
    │   ├── iam
    │   │   ├── aws_iam_policy.tf
    │   │   ├── aws_iam_policy_attachment.tf
    │   │   ├── aws_iam_role.tf
    │   │   └── outputs.tf
    │   └── network
    │       ├── aws_vpc.tf
    │       ├── igw.tf
    │       ├── outputs.tf
    │       ├── route_table.tf
    │       ├── security_group.tf
    │       ├── security_group_rule.tf
    │       └── subnet.tf
    ├── terraform.tfstate
    ├── terraform.tfstate.backup
    └── variables.tf

ネットワーク構成

ローカルからECRにpushされたdockerimageをfargateでpullしデプロイするという手法をとります。

fargate.png

DockerfileとHTML

画面にHello world!!!!!!!!!!!と出力する簡単な構成にしています。

fargate
FROM nginx:latest

COPY ./nginx /usr/share/nginx/html
index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
</head>

<body>
    <div style="  line-height: 200px;height: 200px;text-align: center;">
        <p style="  line-height: 1.5;display: inline-block;vertical-align: middle;">
            Hello world!!!!!!!!!!!
        </p>
    </div>
</body>

</html>

main.tf

各output.tfは他のモジュールにmain.tfを経由してデータを転送するためのものですが、
説明は省きます。

main.tf
provider "aws" {
  region      = var.region
}

# IAM
module "iam" {
  source = "./modules/iam"
}

# ECR
module "ecr" {
  source = "./modules/ecr"
  image_name = var.image_name
}

# Null Resource
module "after_ecr" {
  source = "./modules/bash"
  region = var.region
  image_name = var.image_name
}

# network
module "network" {
  source = "./modules/network"
  app_name = var.app_name
}

# ECS
module "ecs" {
  source = "./modules/ecs"
  app_name = var.app_name
  vpc_id       = module.network.security-group-id
  subnet_id    = module.network.subnet-public-1a-id
  aws_iam_role =  module.iam.aws_iam_role

}

IAM構成

aws_iam_role.tf
resource "aws_iam_role" "newworld_role" {
  name = "newworld_role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid: ""
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "ecs-tasks.amazonaws.com"
        }
      },
    ]
  })
}

"ecr:*"という記述がfargateによるpullを可能にしています。
これがないとpull時に400エラーを吐きます。

aws_iam_policy.tf
resource "aws_iam_policy" "newworld_policy" {
  name        = "test_policy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ecr:*",
        ]
        Effect   = "Allow"
        Resource = "*"
      },
    ]
  })
}
aws_iam_policy_attachment.tf
resource "aws_iam_policy_attachment" "attach" {
  name       = "iam-attach"
  roles      = ["${aws_iam_role.newworld_role.name}"]
  policy_arn = "${aws_iam_policy.newworld_policy.arn}"
}

ECR構成

aws_ecr_repository.tf
variable "image_name" {}

resource "aws_ecr_repository" "repository" {
  name                 = var.image_name
  image_tag_mutability = "IMMUTABLE"
  force_delete         = true

  image_scanning_configuration {
    scan_on_push = true
  }
}

Null Resource構成

ECR構築後に自動でECRにdockerimageをpushします。
以下の記述をterraformで実行しています。

aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin AWSのアカウントID.dkr.ecr.ap-northeast-1.amazonaws.com
docker tag hello-world-from-ecs:latest AWSのアカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest
docker push AWSのアカウントID.dkr.ecr.ap-northeast-1.amazonaws.com/hello-world-from-ecs:latest

aws_caller_identityはAWSのアカウントIDを呼び出している。

null_resource.tf
data "aws_caller_identity" "self" { }
variable "image_name" {}
variable "region" {}

resource "null_resource" "default" {
  provisioner "local-exec" {
    command = "aws ecr get-login-password --region ${var.region} | docker login --username AWS --password-stdin ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com"
  }

  provisioner "local-exec" {
    command = "docker tag ${var.image_name}:latest ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/${var.image_name}:latest"
  }

  provisioner "local-exec" {
    command = "docker push ${data.aws_caller_identity.self.account_id}.dkr.ecr.ap-northeast-1.amazonaws.com/${var.image_name}:latest"
  }
}

network構成

長いので割愛します。

ECS構成

ecr.tf
variable "app_name" {}

resource "aws_ecs_cluster" "newworld-cluster" {
  name = "${var.app_name}-cluster"
}

resource "aws_ecs_cluster_capacity_providers" "newworld_capacity_providers" {
  cluster_name = "${var.app_name}-cluster"
  capacity_providers = ["FARGATE"]

  default_capacity_provider_strategy {
    base              = 1
    weight            = 100
    capacity_provider = "FARGATE"
  }
}
aws_ecs_service.tf
variable "vpc_id" {}
variable "subnet_id" {}

resource "aws_ecs_service" "newworld-service" {
  name            = "nginx-service"
  cluster         = aws_ecs_cluster.newworld-cluster.id
  task_definition = aws_ecs_task_definition.newworld-definition.arn
  desired_count   = 1

  network_configuration {
    security_groups  = [var.vpc_id]
    subnets          = ["${var.subnet_id}"]
    assign_public_ip = true
  }

  lifecycle {
    ignore_changes = [desired_count]
  }
}
aws_ecs_task_definition.tf
variable "vpc_id" {}
variable "subnet_id" {}

resource "aws_ecs_service" "newworld-service" {
  name            = "nginx-service"
  cluster         = aws_ecs_cluster.newworld-cluster.id
  task_definition = aws_ecs_task_definition.newworld-definition.arn
  desired_count   = 1

  network_configuration {
    security_groups  = [var.vpc_id]
    subnets          = ["${var.subnet_id}"]
    assign_public_ip = true
  }

  lifecycle {
    ignore_changes = [desired_count]
  }
}

結果

Screenshot 2023-02-25 at 20.44.16.png

0
0
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
0
0