본문 바로가기

AWS

[CICD / ECS] CodePipeline으로 ECS Fargate 배포 자동화 #3 - 테라폼으로 인프라 기본 환경 프로비저닝

반응형

Terraform을 활용하여 간단한 인프라 환경을 프로비저닝 하였다.

 

기본적인 VPC, Security Groups, ECS Cluster, Application Load Balancer, Blue-Green을 위한 Target Group A, B 등을 생성하였다.

 

Dev, Stg, Prd 등 각 환경마다 설정을 다르게 하고 싶다면 env 디렉터리에 각각 설정값을 저장한 tfvars 파일 생성 후 각 Workspace에서 terraform 명령을 수행하면 된다.

 

예를 들어, Dev 환경 인프라를 만든 후 STG 환경을 만들고싶다면 VPC 대역, ENV 이름 등을 겹치지 않게 수정 후 별도 Workspace에서 terraform init, .. 등을 수행하면 된다.

 

Code Build, Deploy, Pipeline, ASG랑 Service, Task Definition 등은 생성하지 않았으며 웹 콘솔로 생성 예정

 

 

  • 정적 코드 분석

❯ terraform validate && terraform fmt Success! The configuration is valid.

..

..

 

  • Plan

terraform plan -var-file=./env/test.tfvars

 

  • Apploy

terraform apply --var-file=./env/test.tfvars --auto-approve

 

❯ tree
.
├── alb.tf
├── autoscaling.tf
├── data.tf
├── ec2.tf
├── ecr.tf
├── ecs.tf
├── env
│   └── test.tfvars
├── global_vars.tf -> ../common/variables/global_vars.tf
├── iam_roles.tf
├── locals.tf
├── outputs.tf
├── provider.tf
├── scripts
│   └── common
│       └── amz2_init.sh
├── security_groups.tf
├── templates
│   └── taskdef
│       └── nodejs_app.json.tpl
├── variables.tf
└── vpc.tf

5 directories, 17 files

 

VPC 생성 설명은 생략

 

1. ALB

Blue - Green 배포를 위해 ALB에 Target Group을 2EA 생성하였다.

locals {
  ssl_policy                     = "ELBSecurityPolicy-2016-08"
  nodejs_app_listener_http_port  = 80
  nodejs_app_listener_https_port = 443
}
############################################################################
# Route 53 -> WEB ALB ( A Record )
############################################################################
resource "aws_route53_record" "nodejs_app" {
  zone_id = data.aws_route53_zone.pingping2_shop.zone_id
  name    = var.domain
  type    = "A"
  alias {
    name                   = aws_lb.nodejs_app.dns_name
    zone_id                = aws_lb.nodejs_app.zone_id
    evaluate_target_health = true
  }
}
############################################################################
# WEB ALB - Security Group
############################################################################
resource "aws_security_group" "nodejs_app" {
  name        = "${local.name_prefix}-nodejs-app-alb-sg"
  description = "nodejs_app ALB Security Group"
  vpc_id      = module.main_vpc.vpc_id
  # Outbound
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
  # Inbound
  ingress {
    description = "http"
    from_port   = 80
    to_port     = 80
    protocol    = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    description = "https"
    from_port   = 443
    to_port     = 443
    protocol    = "TCP"
    cidr_blocks = ["0.0.0.0/0"]
  }
  tags = {
    Name        = "${local.name_prefix}-nodejs_app-alb-sg"
    Environment = var.tags.Environment
  }
}
############################################################################
# WEB ALB
############################################################################
resource "aws_lb" "nodejs_app" {
  name                       = "${local.name_prefix}-nodejs-app-alb"
  internal                   = false # Internet Facing
  load_balancer_type         = "application"
  security_groups            = [aws_security_group.nodejs_app.id]
  subnets                    = module.main_vpc.public_subnets_ids
  enable_deletion_protection = var.nodejs_app_alb_enable_deletion_protection
  tags = {
    Name        = "${local.name_prefix}-nodejs_app-alb"
    Environment = var.tags.Environment
  }
}

############################################################################
# ALB Listener
############################################################################
resource "aws_lb_listener" "nodejs_app" {
  load_balancer_arn = aws_lb.nodejs_app.arn
  port              = local.nodejs_app_listener_https_port # 443
  protocol          = "HTTPS"
  certificate_arn   = data.aws_acm_certificate.this.arn
  ssl_policy        = local.ssl_policy
  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.nodejs_app-A.id
  }
}
############################################################################
# ALB Listener - Redirect
############################################################################
resource "aws_lb_listener" "nodejs_app_https_redirect" {
  load_balancer_arn = aws_lb.nodejs_app.arn
  port              = local.nodejs_app_listener_http_port #80
  protocol          = "HTTP"
  default_action {
    type = "redirect"
    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }
}
############################################################################
# ALB Target Group - A (Blue)
############################################################################
resource "aws_lb_target_group" "nodejs_app-A" {
  name     = "${local.name_prefix}-nodejs-app-tg-A"
  vpc_id   = module.main_vpc.vpc_id
  port     = var.backend_port
  protocol = "HTTP"
  health_check {
    interval            = 30
    path                = "/"
    port                = "traffic-port"
    protocol            = "HTTP"
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
    matcher             = 200
  }
  target_type = "ip"
  lifecycle {
    create_before_destroy = true
  }
}

############################################################################
# ALB Target Group - B (Green)
############################################################################
resource "aws_lb_target_group" "nodejs_app-B" {
  name     = "${local.name_prefix}-nodejs-app-tg-B"
  vpc_id   = module.main_vpc.vpc_id
  port     = var.backend_port
  protocol = "HTTP"
  health_check {
    interval            = 30
    path                = "/"
    port                = "traffic-port"
    protocol            = "HTTP"
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
    matcher             = 200
  }
  target_type = "ip"
  lifecycle {
    create_before_destroy = true
  }
}%

 

2. ECS

클러스터만 생성해주었다.

//////////////////////////////////////
// 1. ECS
//////////////////////////////////////

resource "aws_ecs_cluster" "this" {
  name = local.cluster
  tags = {
    "Name"      = local.name_prefix
    Environment = var.tags.Environment
  }
}

 

3. ECR

ECR 1개를 생성하였으며, ECR Lifecycle Policy도 설정하였음.

resource "aws_ecr_repository" "nodejs_app" {
  name = "nodejs_app"
  image_scanning_configuration {
    scan_on_push = true
  }

  tags = {
    Name        = "nodejs_app"
    Environment = var.tags.Environment
  }
}

resource "aws_ecr_lifecycle_policy" "nodejs_app_policy" {
  repository = aws_ecr_repository.nodejs_app.name

  policy = <<EOF
{
    "rules": [
        {
            "rulePriority": 1,
            "description": "Keep last 30 images",
            "selection": {
                "tagStatus": "tagged",
                "tagPrefixList": ["v"],
                "countType": "imageCountMoreThan",
                "countNumber": 5
            },
            "action": {
                "type": "expire"
            }
        }
    ]
}
EOF
}

 

4. tfvars 파일

TEST 환경에서 필요한 각종 변수들을 기입해주었다.

# VPC Configuration
available_azs = ["ap-northeast-2a", "ap-northeast-2c"]
cidr_block = "10.60.0.0/18"
public_subnet_cidr = ["10.60.0.0/20", "10.60.16.0/20"]
private_subnet_cidr = ["10.60.32.0/22", "10.60.36.0/22"]
# db_subnet_cidr = ["10.60.40.0/24", "10.60.41.0/24"]

tags = {
  Service           = "node"
  Environment       = "dev"
  RegionAlias       = "apne2"
}

# EC2 Configurations
default_instance_type = "t3.micro"
key_pair              = "pingping95-key"

# Security Groups Rules
bastion_ingress_rules =[
  # From, To, Protocol, Source CIDR, Description
  [22, 22, "tcp", ["0.0.0.0/0"], "SSH Inbound"]
]

nodejs_app_ingress_rules =[
  # From, To, Protocol, Source CIDR, Description
  [8080, 8080, "tcp", ["10.60.0.0/18"], "SSH Inbound"]
]

# ECS Configurations

// Route 53, ALB, ACM
domain = "pingping2.shop"


// ELB
backend_port = "8080"

 

 

 

 

 

 

1. LB

 

 

2. TG

 

 

3. SG

 

4. Endpoint

 

5. ECS Fargate cluster

 

6. ECR

 

7. ECR Lifecycle Policy

 

8. EC2 Instance

 

 

 

 

 

 

 

 

 

 

반응형