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