From b5133f2afbcbec85473d0c048ffb6e8caf291be4 Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Fri, 30 May 2025 22:49:56 +0900 Subject: [PATCH 1/7] chore: Drop waf-related resources --- Modules/WAF/main.tf | 88 ---------------------------------------- Modules/WAF/variables.tf | 3 -- main.tf | 5 --- 3 files changed, 96 deletions(-) delete mode 100644 Modules/WAF/main.tf delete mode 100644 Modules/WAF/variables.tf diff --git a/Modules/WAF/main.tf b/Modules/WAF/main.tf deleted file mode 100644 index a48e855..0000000 --- a/Modules/WAF/main.tf +++ /dev/null @@ -1,88 +0,0 @@ -resource "aws_wafv2_web_acl" "waf_web_acl" { - name = "dutymate-waf-web-acl" - scope = "REGIONAL" - - default_action { - block {} - } - - rule { - name = "AllowKoreaOnlyRule" - priority = 100 - - action { - allow {} - } - - statement { - geo_match_statement { - country_codes = ["KR"] - } - } - - visibility_config { - cloudwatch_metrics_enabled = true - sampled_requests_enabled = true - metric_name = "AllowKoreaOnlyRule" - } - } - - rule { - name = "AnonymousIpListRule" - priority = 200 - - override_action { - count {} - } - - statement { - managed_rule_group_statement { - name = "AWSManagedRulesAnonymousIpList" - vendor_name = "AWS" - } - } - - visibility_config { - cloudwatch_metrics_enabled = true - sampled_requests_enabled = true - metric_name = "AnonymousIpListRule" - } - } - - rule { - name = "RateLimitRule" - priority = 300 - - action { - block {} - } - - statement { - rate_based_statement { - limit = 1000 - aggregate_key_type = "IP" - } - } - - visibility_config { - cloudwatch_metrics_enabled = true - sampled_requests_enabled = true - metric_name = "RateLimitRule" - } - } - - visibility_config { - cloudwatch_metrics_enabled = true - sampled_requests_enabled = true - metric_name = "WebACLVisibilityConfig" - } - - tags = { - Name = "dutymate-waf-web-acl" - } -} - -resource "aws_wafv2_web_acl_association" "waf_external_alb_association" { - resource_arn = var.external_alb_arn - web_acl_arn = aws_wafv2_web_acl.waf_web_acl.arn -} diff --git a/Modules/WAF/variables.tf b/Modules/WAF/variables.tf deleted file mode 100644 index 7ca5de5..0000000 --- a/Modules/WAF/variables.tf +++ /dev/null @@ -1,3 +0,0 @@ -variable "external_alb_arn" { - type = string -} diff --git a/main.tf b/main.tf index 6431eba..15c8bc0 100644 --- a/main.tf +++ b/main.tf @@ -134,8 +134,3 @@ module "ssm" { sg_ssm_ec2_id = module.security_group.sg_ssm_ec2_id ssm_instance_profile_name = module.iam.ssm_instance_profile_name } - -module "waf" { - source = "./Modules/WAF" - external_alb_arn = module.alb.external_alb_arn -} From 867af7635ddfdf49248319ade78c49450acfaa92 Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Fri, 30 May 2025 23:09:47 +0900 Subject: [PATCH 2/7] chore: Drop ssm-related resources --- Modules/IAM/main.tf | 32 --------------------------- Modules/IAM/outputs.tf | 4 ---- Modules/Networking/main.tf | 18 --------------- Modules/Networking/variables.tf | 4 ---- Modules/SSM/main.tf | 22 ------------------ Modules/SSM/variables.tf | 11 --------- Modules/SecurityGroup/main.tf | 38 +++----------------------------- Modules/SecurityGroup/outputs.tf | 8 ------- main.tf | 8 ------- 9 files changed, 3 insertions(+), 142 deletions(-) delete mode 100644 Modules/SSM/main.tf delete mode 100644 Modules/SSM/variables.tf diff --git a/Modules/IAM/main.tf b/Modules/IAM/main.tf index 369862d..104325f 100644 --- a/Modules/IAM/main.tf +++ b/Modules/IAM/main.tf @@ -1,35 +1,3 @@ -resource "aws_iam_role" "ssm_role" { - name = "dutymate-ssm-role" - assume_role_policy = jsonencode({ - Version = "2012-10-17", - Statement = [ - { - Effect = "Allow", - Principal = { Service = "ec2.amazonaws.com" }, - Action = "sts:AssumeRole" - } - ] - }) - - tags = { - Name = "dutymate-ssm-role" - } -} - -resource "aws_iam_role_policy_attachment" "ssm_attach" { - role = aws_iam_role.ssm_role.name - policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" -} - -resource "aws_iam_instance_profile" "ssm_instance_profile" { - name = "dutymate-ssm-instance-profile" - role = aws_iam_role.ssm_role.name - - tags = { - Name = "dutymate-ssm-instance-profile" - } -} - data "aws_iam_policy_document" "ec2_instance_role_policy" { statement { actions = ["sts:AssumeRole"] diff --git a/Modules/IAM/outputs.tf b/Modules/IAM/outputs.tf index 3931635..42fd81a 100644 --- a/Modules/IAM/outputs.tf +++ b/Modules/IAM/outputs.tf @@ -18,10 +18,6 @@ output "eventbridge_api_destinations_role_arn" { value = aws_iam_role.eventbridge_api_destinations_role.arn } -output "ssm_instance_profile_name" { - value = aws_iam_instance_profile.ssm_instance_profile.name -} - output "webserver_ecs_task_role_arn" { value = aws_iam_role.webserver_ecs_task_role.arn } diff --git a/Modules/Networking/main.tf b/Modules/Networking/main.tf index 9683778..2e5d779 100644 --- a/Modules/Networking/main.tf +++ b/Modules/Networking/main.tf @@ -189,21 +189,3 @@ resource "aws_vpc_endpoint" "vpce_ecr" { Name = "dutymate-vpce-ecr-${each.key}" } } - -resource "aws_vpc_endpoint" "vpce_ssm" { - for_each = toset([ - "ssm", - "ssmmessages", - "ec2messages" - ]) - vpc_id = aws_vpc.vpc.id - vpc_endpoint_type = "Interface" - service_name = "com.amazonaws.${var.aws_region}.${each.key}" - subnet_ids = aws_subnet.database_subnets[*].id - security_group_ids = [var.sg_vpce_ssm_id] - private_dns_enabled = true - - tags = { - Name = "dutymate-vpce-${each.key}" - } -} diff --git a/Modules/Networking/variables.tf b/Modules/Networking/variables.tf index 15163d3..a8e38ff 100644 --- a/Modules/Networking/variables.tf +++ b/Modules/Networking/variables.tf @@ -22,10 +22,6 @@ variable "sg_vpce_ecr_id" { type = string } -variable "sg_vpce_ssm_id" { - type = string -} - variable "vpc_cidr" { type = string } diff --git a/Modules/SSM/main.tf b/Modules/SSM/main.tf deleted file mode 100644 index 261bedf..0000000 --- a/Modules/SSM/main.tf +++ /dev/null @@ -1,22 +0,0 @@ -data "aws_ami" "amazonlinux2" { - owners = ["amazon"] - most_recent = true - - filter { - name = "name" - values = ["amzn2-ami-hvm*"] - } -} - -resource "aws_instance" "db_access_instance" { - ami = data.aws_ami.amazonlinux2.id - instance_type = "t2.micro" - subnet_id = var.database_subnets[0] - associate_public_ip_address = false - iam_instance_profile = var.ssm_instance_profile_name - vpc_security_group_ids = [var.sg_ssm_ec2_id] - - tags = { - Name = "dutymate-db-access-instance" - } -} diff --git a/Modules/SSM/variables.tf b/Modules/SSM/variables.tf deleted file mode 100644 index d61223f..0000000 --- a/Modules/SSM/variables.tf +++ /dev/null @@ -1,11 +0,0 @@ -variable "database_subnets" { - type = list(string) -} - -variable "sg_ssm_ec2_id" { - type = string -} - -variable "ssm_instance_profile_name" { - type = string -} diff --git a/Modules/SecurityGroup/main.tf b/Modules/SecurityGroup/main.tf index 6c6dc7e..36fbe69 100644 --- a/Modules/SecurityGroup/main.tf +++ b/Modules/SecurityGroup/main.tf @@ -140,7 +140,7 @@ resource "aws_security_group" "sg_mysql" { from_port = 3306 to_port = 3306 protocol = "tcp" - security_groups = [aws_security_group.sg_appserver_ecs.id, aws_security_group.sg_ssm_ec2.id] + security_groups = [aws_security_group.sg_appserver_ecs.id] } egress { @@ -163,7 +163,7 @@ resource "aws_security_group" "sg_valkey" { from_port = 6379 to_port = 6379 protocol = "tcp" - security_groups = [aws_security_group.sg_appserver_ecs.id, aws_security_group.sg_ssm_ec2.id] + security_groups = [aws_security_group.sg_appserver_ecs.id] } egress { @@ -186,7 +186,7 @@ resource "aws_security_group" "sg_mongodb" { from_port = 27017 to_port = 27017 protocol = "tcp" - security_groups = [aws_security_group.sg_appserver_ecs.id, aws_security_group.sg_ssm_ec2.id] + security_groups = [aws_security_group.sg_appserver_ecs.id] } egress { @@ -201,22 +201,6 @@ resource "aws_security_group" "sg_mongodb" { } } -resource "aws_security_group" "sg_ssm_ec2" { - name = "dutymate-sg-ssm-ec2" - vpc_id = var.vpc_id - - egress { - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - } - - tags = { - Name = "dutymate-sg-ssm-ec2" - } -} - resource "aws_security_group" "sg_vpce_ecr" { name = "dutymate-sg-vpce-ecr" vpc_id = var.vpc_id @@ -232,19 +216,3 @@ resource "aws_security_group" "sg_vpce_ecr" { Name = "dutymate-sg-vpce-ecr" } } - -resource "aws_security_group" "sg_vpce_ssm" { - name = "dutymate-sg-ssm" - vpc_id = var.vpc_id - - ingress { - from_port = 443 - to_port = 443 - protocol = "tcp" - security_groups = [aws_security_group.sg_ssm_ec2.id] - } - - tags = { - Name = "dutymate-sg-vpce-ssm" - } -} diff --git a/Modules/SecurityGroup/outputs.tf b/Modules/SecurityGroup/outputs.tf index 3c58fdc..f35aaf3 100644 --- a/Modules/SecurityGroup/outputs.tf +++ b/Modules/SecurityGroup/outputs.tf @@ -18,10 +18,6 @@ output "sg_mysql_id" { value = aws_security_group.sg_mysql.id } -output "sg_ssm_ec2_id" { - value = aws_security_group.sg_ssm_ec2.id -} - output "sg_valkey_id" { value = aws_security_group.sg_valkey.id } @@ -30,10 +26,6 @@ output "sg_vpce_ecr_id" { value = aws_security_group.sg_vpce_ecr.id } -output "sg_vpce_ssm_id" { - value = aws_security_group.sg_vpce_ssm.id -} - output "sg_webserver_ecs_id" { value = aws_security_group.sg_webserver_ecs.id } diff --git a/main.tf b/main.tf index 15c8bc0..72e7e0a 100644 --- a/main.tf +++ b/main.tf @@ -90,7 +90,6 @@ module "networking" { private_subnet_cidr_block = var.private_subnet_cidr_block public_subnet_cidr_block = var.public_subnet_cidr_block sg_vpce_ecr_id = module.security_group.sg_vpce_ecr_id - sg_vpce_ssm_id = module.security_group.sg_vpce_ssm_id vpc_cidr = var.vpc_cidr } @@ -127,10 +126,3 @@ module "security_group" { public_subnet_cidr_block = var.public_subnet_cidr_block vpc_id = module.networking.vpc_id } - -module "ssm" { - source = "./Modules/SSM" - database_subnets = module.networking.database_subnets - sg_ssm_ec2_id = module.security_group.sg_ssm_ec2_id - ssm_instance_profile_name = module.iam.ssm_instance_profile_name -} From 48f9bb5e4d75a6b0c675a0ce953d55f9e4036242 Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Fri, 30 May 2025 23:11:54 +0900 Subject: [PATCH 3/7] chore: Disable eventbridge api calls --- main.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.tf b/main.tf index 72e7e0a..0977042 100644 --- a/main.tf +++ b/main.tf @@ -67,12 +67,12 @@ module "elasticache" { sg_valkey_id = module.security_group.sg_valkey_id } -module "eventbridge" { - source = "./Modules/EventBridge" - api_secret_key = var.api_secret_key - domain_name = var.domain_name - eventbridge_api_destinations_role_arn = module.iam.eventbridge_api_destinations_role_arn -} +# module "eventbridge" { +# source = "./Modules/EventBridge" +# api_secret_key = var.api_secret_key +# domain_name = var.domain_name +# eventbridge_api_destinations_role_arn = module.iam.eventbridge_api_destinations_role_arn +# } module "iam" { source = "./Modules/IAM" From e0d66410520f7b6a000cdb30d8c368052ce5c2f2 Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Fri, 30 May 2025 23:13:47 +0900 Subject: [PATCH 4/7] chore: Disable external alb's ingress and egress --- Modules/SecurityGroup/main.tf | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/Modules/SecurityGroup/main.tf b/Modules/SecurityGroup/main.tf index 36fbe69..0498173 100644 --- a/Modules/SecurityGroup/main.tf +++ b/Modules/SecurityGroup/main.tf @@ -2,25 +2,32 @@ resource "aws_security_group" "sg_external_alb" { name = "dutymate-sg-external-alb" vpc_id = var.vpc_id - ingress { - from_port = 80 - to_port = 80 - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] - } + # 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"] + # } ingress { - from_port = 443 - to_port = 443 - protocol = "tcp" - cidr_blocks = ["0.0.0.0/0"] + from_port = 0 + to_port = 0 + protocol = -1 + cidr_blocks = [] } egress { from_port = 0 to_port = 0 protocol = "-1" - cidr_blocks = var.public_subnet_cidr_block + cidr_blocks = [] } tags = { From adef2924169069bafd2c6dba3d6468ca68daca40 Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Sat, 31 May 2025 04:39:10 +0900 Subject: [PATCH 5/7] chore: Reduce infra cost by switching from 3-tier to 1-tier architecture --- Modules/ACM/main.tf | 14 +- Modules/ACM/outputs.tf | 4 +- Modules/ALB/main.tf | 90 +++-------- Modules/ALB/outputs.tf | 24 +-- Modules/ALB/variables.tf | 18 +-- Modules/CloudWatch/main.tf | 15 +- Modules/CloudWatch/outputs.tf | 8 +- Modules/DocumentDB/main.tf | 3 +- Modules/DocumentDB/variables.tf | 8 +- Modules/ECS/main.tf | 241 +++++------------------------ Modules/ECS/variables.tf | 36 +---- Modules/ElastiCache/main.tf | 2 +- Modules/ElastiCache/variables.tf | 2 +- Modules/IAM/main.tf | 19 +-- Modules/IAM/outputs.tf | 12 +- Modules/Networking/main.tf | 134 ---------------- Modules/Networking/outputs.tf | 12 -- Modules/Networking/variables.tf | 12 -- Modules/RDS/main.tf | 3 +- Modules/RDS/variables.tf | 8 +- Modules/Route53/main.tf | 6 +- Modules/Route53/variables.tf | 10 +- Modules/S3/main.tf | 9 +- Modules/S3/variables.tf | 4 - Modules/SecurityGroup/main.tf | 141 +++++------------ Modules/SecurityGroup/outputs.tf | 20 +-- Modules/SecurityGroup/variables.tf | 8 - main.tf | 91 +++++------ variables.tf | 20 +-- 29 files changed, 201 insertions(+), 773 deletions(-) diff --git a/Modules/ACM/main.tf b/Modules/ACM/main.tf index 1603fa2..9fdf18f 100644 --- a/Modules/ACM/main.tf +++ b/Modules/ACM/main.tf @@ -18,13 +18,13 @@ resource "aws_acm_certificate" "cloudfront_certificate" { } } -resource "aws_acm_certificate" "external_alb_certificate" { +resource "aws_acm_certificate" "alb_certificate" { provider = aws.seoul domain_name = "api.${var.domain_name}" validation_method = "DNS" tags = { - Name = "dutymate-external-alb-certificate" + Name = "dutymate-alb-certificate" } } @@ -37,8 +37,8 @@ resource "aws_route53_record" "cloudfront_route53_record" { ttl = 300 } -resource "aws_route53_record" "external_alb_route53_record" { - for_each = { for dvo in aws_acm_certificate.external_alb_certificate.domain_validation_options : dvo.domain_name => dvo } +resource "aws_route53_record" "alb_route53_record" { + for_each = { for dvo in aws_acm_certificate.alb_certificate.domain_validation_options : dvo.domain_name => dvo } name = each.value.resource_record_name type = each.value.resource_record_type zone_id = var.route53_zone_id @@ -52,8 +52,8 @@ resource "aws_acm_certificate_validation" "cloudfront_certificate_validation" { validation_record_fqdns = [for record in aws_route53_record.cloudfront_route53_record : record.fqdn] } -resource "aws_acm_certificate_validation" "external_alb_certificate_validation" { +resource "aws_acm_certificate_validation" "alb_certificate_validation" { provider = aws.seoul - certificate_arn = aws_acm_certificate.external_alb_certificate.arn - validation_record_fqdns = [for record in aws_route53_record.external_alb_route53_record : record.fqdn] + certificate_arn = aws_acm_certificate.alb_certificate.arn + validation_record_fqdns = [for record in aws_route53_record.alb_route53_record : record.fqdn] } diff --git a/Modules/ACM/outputs.tf b/Modules/ACM/outputs.tf index 10fc166..1753502 100644 --- a/Modules/ACM/outputs.tf +++ b/Modules/ACM/outputs.tf @@ -1,5 +1,5 @@ -output "external_alb_certificate_arn" { - value = aws_acm_certificate.external_alb_certificate.arn +output "alb_certificate_arn" { + value = aws_acm_certificate.alb_certificate.arn } output "cloudfront_certificate_arn" { diff --git a/Modules/ALB/main.tf b/Modules/ALB/main.tf index 6513937..9c8ca3e 100644 --- a/Modules/ALB/main.tf +++ b/Modules/ALB/main.tf @@ -1,66 +1,27 @@ -resource "aws_alb" "external_alb" { - name = "dutymate-external-alb" +resource "aws_alb" "alb" { + name = "dutymate-alb" subnets = var.public_subnets - security_groups = [var.sg_external_alb_id] + security_groups = [var.sg_alb_id] load_balancer_type = "application" internal = false enable_http2 = true idle_timeout = 30 tags = { - Name = "dutymate-external-alb" + Name = "dutymate-alb" } } -resource "aws_alb" "internal_alb" { - name = "dutymate-internal-alb" - subnets = var.private_subnets - security_groups = [var.sg_internal_alb_id] - load_balancer_type = "application" - internal = true - enable_http2 = true - idle_timeout = 30 - - tags = { - Name = "dutymate-internal-alb" - } -} - -resource "aws_alb_target_group" "external_alb_target_group" { - name = "dutymate-external-alb-tg" - port = 80 - protocol = "HTTP" - vpc_id = var.vpc_id - target_type = "ip" - deregistration_delay = 5 - - health_check { - path = var.external_alb_health_check_path - interval = 30 - timeout = 5 - healthy_threshold = 3 - unhealthy_threshold = 2 - } - - lifecycle { - create_before_destroy = true - } - - tags = { - Name = "dutymate-external-alb-tg" - } -} - -resource "aws_alb_target_group" "internal_alb_target_group" { - name = "dutymate-internal-alb-tg" +resource "aws_alb_target_group" "alb_target_group" { + name = "dutymate-alb-tg" port = 8080 protocol = "HTTP" vpc_id = var.vpc_id - target_type = "ip" + target_type = "instance" deregistration_delay = 5 health_check { - path = var.internal_alb_health_check_path + path = var.alb_health_check_path interval = 30 timeout = 5 healthy_threshold = 3 @@ -72,12 +33,12 @@ resource "aws_alb_target_group" "internal_alb_target_group" { } tags = { - Name = "dutymate-internal-alb-tg" + Name = "dutymate-alb-tg" } } -resource "aws_alb_listener" "external_alb_http_listener" { - load_balancer_arn = aws_alb.external_alb.arn +resource "aws_alb_listener" "http_listener" { + load_balancer_arn = aws_alb.alb.arn port = 80 protocol = "HTTP" @@ -85,45 +46,30 @@ resource "aws_alb_listener" "external_alb_http_listener" { type = "redirect" redirect { - port = "443" + port = 443 protocol = "HTTPS" status_code = "HTTP_301" } } tags = { - Name = "dutymate-external-alb-http-listener" + Name = "dutymate-http-listener" } } -resource "aws_alb_listener" "external_alb_https_listener" { - load_balancer_arn = aws_alb.external_alb.arn +resource "aws_alb_listener" "https_listener" { + load_balancer_arn = aws_alb.alb.arn port = 443 protocol = "HTTPS" ssl_policy = "ELBSecurityPolicy-2016-08" - certificate_arn = var.external_alb_certificate_arn - - default_action { - type = "forward" - target_group_arn = aws_alb_target_group.external_alb_target_group.arn - } - - tags = { - Name = "dutymate-external-alb-https-listener" - } -} - -resource "aws_alb_listener" "internal_alb_http_listener" { - load_balancer_arn = aws_alb.internal_alb.arn - port = 8080 - protocol = "HTTP" + certificate_arn = var.alb_certificate_arn default_action { type = "forward" - target_group_arn = aws_alb_target_group.internal_alb_target_group.arn + target_group_arn = aws_alb_target_group.alb_target_group.arn } tags = { - Name = "dutymate-internal-alb-http-listener" + Name = "dutymate-https-listener" } } diff --git a/Modules/ALB/outputs.tf b/Modules/ALB/outputs.tf index 95c3be2..91a1d9c 100644 --- a/Modules/ALB/outputs.tf +++ b/Modules/ALB/outputs.tf @@ -1,23 +1,15 @@ -output "external_alb_arn" { - value = aws_alb.external_alb.arn +output "alb_arn" { + value = aws_alb.alb.arn } -output "external_alb_dns_name" { - value = aws_alb.external_alb.dns_name +output "alb_dns_name" { + value = aws_alb.alb.dns_name } -output "external_alb_zone_id" { - value = aws_alb.external_alb.zone_id +output "alb_zone_id" { + value = aws_alb.alb.zone_id } -output "external_alb_target_group_arn" { - value = aws_alb_target_group.external_alb_target_group.arn -} - -output "internal_alb_dns_name" { - value = aws_alb.internal_alb.dns_name -} - -output "internal_alb_target_group_arn" { - value = aws_alb_target_group.internal_alb_target_group.arn +output "alb_target_group_arn" { + value = aws_alb_target_group.alb_target_group.arn } diff --git a/Modules/ALB/variables.tf b/Modules/ALB/variables.tf index e4b07bc..e9cd03b 100644 --- a/Modules/ALB/variables.tf +++ b/Modules/ALB/variables.tf @@ -1,28 +1,16 @@ -variable "external_alb_certificate_arn" { +variable "alb_certificate_arn" { type = string } -variable "external_alb_health_check_path" { +variable "alb_health_check_path" { type = string } -variable "internal_alb_health_check_path" { - type = string -} - -variable "sg_internal_alb_id" { - type = string -} - -variable "private_subnets" { - type = list(string) -} - variable "public_subnets" { type = list(string) } -variable "sg_external_alb_id" { +variable "sg_alb_id" { type = string } diff --git a/Modules/CloudWatch/main.tf b/Modules/CloudWatch/main.tf index 1281914..02f0689 100644 --- a/Modules/CloudWatch/main.tf +++ b/Modules/CloudWatch/main.tf @@ -1,17 +1,8 @@ -resource "aws_cloudwatch_log_group" "webserver_log_group" { - name = "/ecs/dutymate-webserver-service" +resource "aws_cloudwatch_log_group" "ecs_log_group" { + name = "/ecs/dutymate-service" retention_in_days = 7 tags = { - Name = "dutymate-webserver-log-group" - } -} - -resource "aws_cloudwatch_log_group" "appserver_log_group" { - name = "/ecs/dutymate-appserver-service" - retention_in_days = 7 - - tags = { - Name = "dutymate-appserver-log-group" + Name = "dutymate-ecs-log-group" } } diff --git a/Modules/CloudWatch/outputs.tf b/Modules/CloudWatch/outputs.tf index 0a66129..9b3f264 100644 --- a/Modules/CloudWatch/outputs.tf +++ b/Modules/CloudWatch/outputs.tf @@ -1,7 +1,3 @@ -output "appserver_log_group_name" { - value = aws_cloudwatch_log_group.appserver_log_group.name -} - -output "webserver_log_group_name" { - value = aws_cloudwatch_log_group.webserver_log_group.name +output "ecs_log_group_name" { + value = aws_cloudwatch_log_group.ecs_log_group.name } diff --git a/Modules/DocumentDB/main.tf b/Modules/DocumentDB/main.tf index d6f29b7..dc9a40a 100644 --- a/Modules/DocumentDB/main.tf +++ b/Modules/DocumentDB/main.tf @@ -1,6 +1,6 @@ resource "aws_docdb_subnet_group" "docdbsg" { name = "dutymate-docdbsg" - subnet_ids = var.database_subnets + subnet_ids = var.public_subnets tags = { Name = "dutymate-docdbsg" @@ -10,6 +10,7 @@ resource "aws_docdb_subnet_group" "docdbsg" { resource "aws_docdb_cluster" "docdb" { engine = "docdb" cluster_identifier = "dutymate-docdb-cluster" + snapshot_identifier = "docdb-snapshot" master_username = var.mongodb_username master_password = var.mongodb_password db_subnet_group_name = aws_docdb_subnet_group.docdbsg.id diff --git a/Modules/DocumentDB/variables.tf b/Modules/DocumentDB/variables.tf index 2fb8aab..27d2df4 100644 --- a/Modules/DocumentDB/variables.tf +++ b/Modules/DocumentDB/variables.tf @@ -1,7 +1,3 @@ -variable "database_subnets" { - type = list(string) -} - variable "mongodb_username" { type = string } @@ -10,6 +6,10 @@ variable "mongodb_password" { type = string } +variable "public_subnets" { + type = list(string) +} + variable "sg_mongodb_id" { type = string } diff --git a/Modules/ECS/main.tf b/Modules/ECS/main.tf index 6f90309..9edc552 100644 --- a/Modules/ECS/main.tf +++ b/Modules/ECS/main.tf @@ -1,5 +1,5 @@ -resource "aws_ecs_cluster" "webserver_ecs_cluster" { - name = "dutymate-webserver-ecs-cluster" +resource "aws_ecs_cluster" "ecs_cluster" { + name = "dutymate-ecs-cluster" setting { name = "containerInsights" @@ -7,105 +7,34 @@ resource "aws_ecs_cluster" "webserver_ecs_cluster" { } tags = { - Name = "dutymate-webserver-ecs-cluster" + Name = "dutymate-ecs-cluster" } } -resource "aws_ecs_cluster" "appserver_ecs_cluster" { - name = "dutymate-appserver-ecs-cluster" - - setting { - name = "containerInsights" - value = "enabled" - } - - tags = { - Name = "dutymate-appserver-ecs-cluster" - } -} - -resource "aws_ecs_task_definition" "webserver_ecs_task_definition" { - family = "dutymate-webserver-ecs-task" - network_mode = "awsvpc" - execution_role_arn = var.ecs_task_execution_role_arn - task_role_arn = var.webserver_ecs_task_role_arn - - container_definitions = jsonencode([ - { - name = "webserver-container", - image = "nginx:latest", - memory = 768, - cpu = 512, - essential = true, - portMappings = [ - { - containerPort = 80, - protocol = "tcp" - } - ], - logConfiguration = { - logDriver = "awslogs", - options = { - "awslogs-group" = "${var.webserver_log_group_name}", - "awslogs-region" = "${var.aws_region}", - "awslogs-stream-prefix" = "web" - } - }, - command = [ - "/bin/sh", - "-c", - join("\n", [ - "cat <<'EOF' > /etc/nginx/nginx.conf", - "events {}", - "", - "http {", - " server {", - " listen 80;", - "", - " location / {", - " proxy_pass http://${var.internal_alb_dns_name}:8080;", - " proxy_set_header Host $host;", - " proxy_set_header X-Real-IP $remote_addr;", - " proxy_intercept_errors off;", - " client_max_body_size 30M;", - " }", - " }", - "}", - "EOF", - "nginx -g 'daemon off;'" - ]) - ] - } - ]) - - tags = { - Name = "dutymate-webserver-ecs-task" - } -} - -resource "aws_ecs_task_definition" "appserver_ecs_task_definition" { - family = "dutymate-appserver-ecs-task" - network_mode = "awsvpc" +resource "aws_ecs_task_definition" "ecs_task_definition" { + family = "dutymate-ecs-task" + network_mode = "bridge" execution_role_arn = var.ecs_task_execution_role_arn - task_role_arn = var.appserver_ecs_task_role_arn + task_role_arn = var.ecs_task_role_arn container_definitions = jsonencode([ { - name = "appserver-container", + name = "dutymate-container", image = "${var.ecr_repository_url}:latest", memory = 768, cpu = 512, essential = true, portMappings = [{ containerPort = 8080, + hostPort = 8080, protocol = "tcp" }], logConfiguration = { logDriver = "awslogs", options = { - "awslogs-group" = "${var.appserver_log_group_name}", + "awslogs-group" = "${var.ecs_log_group_name}", "awslogs-region" = "${var.aws_region}", - "awslogs-stream-prefix" = "app" + "awslogs-stream-prefix" = "ecs" } }, environmentFiles = [ @@ -118,47 +47,22 @@ resource "aws_ecs_task_definition" "appserver_ecs_task_definition" { ]) tags = { - Name = "dutymate-appserver-ecs-task" + Name = "dutymate-ecs-task" } } -resource "aws_ecs_service" "webserver_ecs_service" { - name = "dutymate-webserver-service" - cluster = aws_ecs_cluster.webserver_ecs_cluster.id - task_definition = aws_ecs_task_definition.webserver_ecs_task_definition.arn +resource "aws_ecs_service" "ecs_service" { + name = "dutymate-service" + cluster = aws_ecs_cluster.ecs_cluster.id + task_definition = aws_ecs_task_definition.ecs_task_definition.arn desired_count = 2 deployment_minimum_healthy_percent = 50 deployment_maximum_percent = 100 load_balancer { - target_group_arn = var.external_alb_target_group_arn - container_port = 80 - container_name = "webserver-container" - } - - network_configuration { - subnets = var.public_subnets - security_groups = [var.sg_webserver_ecs_id] - } -} - -resource "aws_ecs_service" "appserver_ecs_service" { - name = "dutymate-appserver-service" - cluster = aws_ecs_cluster.appserver_ecs_cluster.id - task_definition = aws_ecs_task_definition.appserver_ecs_task_definition.arn - desired_count = 2 - deployment_minimum_healthy_percent = 50 - deployment_maximum_percent = 100 - - load_balancer { - target_group_arn = var.internal_alb_target_group_arn + target_group_arn = var.alb_target_group_arn container_port = 8080 - container_name = "appserver-container" - } - - network_configuration { - subnets = var.private_subnets - security_groups = [var.sg_appserver_ecs_id] + container_name = "dutymate-container" } } @@ -166,33 +70,16 @@ data "aws_ssm_parameter" "ecs_ami" { name = "/aws/service/ecs/optimized-ami/amazon-linux-2/recommended/image_id" } -resource "aws_launch_template" "webserver_ecs_launch_template" { - name = "dutymate-webserver-ecs-launch-template" - image_id = data.aws_ssm_parameter.ecs_ami.value - instance_type = "t2.micro" - vpc_security_group_ids = [var.sg_webserver_ecs_id] - - iam_instance_profile { - name = var.ecs_instance_profile_name - } +resource "aws_launch_template" "ecs_launch_template" { + name = "dutymate-ecs-launch-template" + image_id = data.aws_ssm_parameter.ecs_ami.value + instance_type = "t2.micro" - instance_market_options { - market_type = "spot" + network_interfaces { + associate_public_ip_address = true + security_groups = [var.sg_ecs_id] } - user_data = base64encode(<> /etc/ecs/ecs.config -EOF - ) -} - -resource "aws_launch_template" "appserver_ecs_launch_template" { - name = "dutymate-appserver-ecs-launch-template" - image_id = data.aws_ssm_parameter.ecs_ami.value - instance_type = "t2.micro" - vpc_security_group_ids = [var.sg_appserver_ecs_id] - iam_instance_profile { name = var.ecs_instance_profile_name } @@ -203,13 +90,13 @@ resource "aws_launch_template" "appserver_ecs_launch_template" { user_data = base64encode(<> /etc/ecs/ecs.config +echo ECS_CLUSTER=${aws_ecs_cluster.ecs_cluster.name} >> /etc/ecs/ecs.config EOF ) } -resource "aws_autoscaling_group" "webserver_ecs_asg" { - name = "dutymate-webserver-ecs-asg" +resource "aws_autoscaling_group" "ecs_asg" { + name = "dutymate-ecs-asg" max_size = 3 min_size = 1 desired_capacity = 2 @@ -217,35 +104,6 @@ resource "aws_autoscaling_group" "webserver_ecs_asg" { health_check_type = "EC2" protect_from_scale_in = true - launch_template { - id = aws_launch_template.webserver_ecs_launch_template.id - version = "$Latest" - } - - instance_refresh { - strategy = "Rolling" - } - - lifecycle { - create_before_destroy = true - } - - tag { - key = "Name" - value = "dutymate-webserver-ecs-asg" - propagate_at_launch = true - } -} - -resource "aws_autoscaling_group" "appserver_ecs_asg" { - name = "dutymate-appserver-ecs-asg" - max_size = 3 - min_size = 1 - desired_capacity = 2 - vpc_zone_identifier = var.private_subnets - health_check_type = "EC2" - protect_from_scale_in = true - enabled_metrics = [ "GroupMinSize", "GroupMaxSize", @@ -258,7 +116,7 @@ resource "aws_autoscaling_group" "appserver_ecs_asg" { ] launch_template { - id = aws_launch_template.appserver_ecs_launch_template.id + id = aws_launch_template.ecs_launch_template.id version = "$Latest" } @@ -272,16 +130,16 @@ resource "aws_autoscaling_group" "appserver_ecs_asg" { tag { key = "Name" - value = "dutymate-appserver-ecs-asg" + value = "dutymate-ecs-asg" propagate_at_launch = true } } -resource "aws_ecs_capacity_provider" "webserver_capacity_provider" { - name = "dutymate-webserver-capacity-provider" +resource "aws_ecs_capacity_provider" "capacity_provider" { + name = "dutymate-capacity-provider" auto_scaling_group_provider { - auto_scaling_group_arn = aws_autoscaling_group.webserver_ecs_asg.arn + auto_scaling_group_arn = aws_autoscaling_group.ecs_asg.arn managed_termination_protection = "ENABLED" managed_scaling { @@ -293,36 +151,11 @@ resource "aws_ecs_capacity_provider" "webserver_capacity_provider" { } tags = { - Name = "dutymate-webserver-capacity-provider" + Name = "dutymate-capacity-provider" } } -resource "aws_ecs_capacity_provider" "appserver_capacity_provider" { - name = "dutymate-appserver-capacity-provider" - - auto_scaling_group_provider { - auto_scaling_group_arn = aws_autoscaling_group.appserver_ecs_asg.arn - managed_termination_protection = "ENABLED" - - managed_scaling { - maximum_scaling_step_size = 5 - minimum_scaling_step_size = 1 - status = "ENABLED" - target_capacity = 100 - } - } - - tags = { - Name = "dutymate-appserver-capacity-provider" - } -} - -resource "aws_ecs_cluster_capacity_providers" "webserver_capacity_provider_association" { - cluster_name = aws_ecs_cluster.webserver_ecs_cluster.name - capacity_providers = [aws_ecs_capacity_provider.webserver_capacity_provider.name] -} - -resource "aws_ecs_cluster_capacity_providers" "appserver_capacity_provider_association" { - cluster_name = aws_ecs_cluster.appserver_ecs_cluster.name - capacity_providers = [aws_ecs_capacity_provider.appserver_capacity_provider.name] +resource "aws_ecs_cluster_capacity_providers" "capacity_provider_association" { + cluster_name = aws_ecs_cluster.ecs_cluster.name + capacity_providers = [aws_ecs_capacity_provider.capacity_provider.name] } diff --git a/Modules/ECS/variables.tf b/Modules/ECS/variables.tf index 25b41df..a104e0b 100644 --- a/Modules/ECS/variables.tf +++ b/Modules/ECS/variables.tf @@ -1,12 +1,4 @@ -variable "internal_alb_dns_name" { - type = string -} - -variable "appserver_ecs_task_role_arn" { - type = string -} - -variable "appserver_log_group_name" { +variable "alb_target_group_arn" { type = string } @@ -26,42 +18,26 @@ variable "ecs_instance_profile_name" { type = string } -variable "ecs_service_role_arn" { +variable "ecs_log_group_name" { type = string } -variable "ecs_task_execution_role_arn" { +variable "ecs_service_role_arn" { type = string } -variable "external_alb_target_group_arn" { +variable "ecs_task_execution_role_arn" { type = string } -variable "internal_alb_target_group_arn" { +variable "ecs_task_role_arn" { type = string } -variable "private_subnets" { - type = list(string) -} - variable "public_subnets" { type = list(string) } -variable "sg_appserver_ecs_id" { - type = string -} - -variable "sg_webserver_ecs_id" { - type = string -} - -variable "webserver_ecs_task_role_arn" { - type = string -} - -variable "webserver_log_group_name" { +variable "sg_ecs_id" { type = string } diff --git a/Modules/ElastiCache/main.tf b/Modules/ElastiCache/main.tf index 8b21ec3..8d478af 100644 --- a/Modules/ElastiCache/main.tf +++ b/Modules/ElastiCache/main.tf @@ -1,6 +1,6 @@ resource "aws_elasticache_subnet_group" "elasticachesg" { name = "dutymate-elasticachesg" - subnet_ids = var.database_subnets + subnet_ids = var.public_subnets tags = { Name = "dutymate-elasticachesg" diff --git a/Modules/ElastiCache/variables.tf b/Modules/ElastiCache/variables.tf index 9a321c7..a0d8bac 100644 --- a/Modules/ElastiCache/variables.tf +++ b/Modules/ElastiCache/variables.tf @@ -1,4 +1,4 @@ -variable "database_subnets" { +variable "public_subnets" { type = list(string) } diff --git a/Modules/IAM/main.tf b/Modules/IAM/main.tf index 104325f..8bf1fb0 100644 --- a/Modules/IAM/main.tf +++ b/Modules/IAM/main.tf @@ -98,26 +98,17 @@ resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" { policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } -resource "aws_iam_role" "webserver_ecs_task_role" { - name = "dutymate-webserver-ecs-task-role" +resource "aws_iam_role" "ecs_task_role" { + name = "dutymate-ecs-task-role" assume_role_policy = data.aws_iam_policy_document.task_assume_role_policy.json tags = { - Name = "dutymate-webserver-ecs-task-role" + Name = "dutymate-ecs-task-role" } } -resource "aws_iam_role" "appserver_ecs_task_role" { - name = "dutymate-appserver-ecs-task-role" - assume_role_policy = data.aws_iam_policy_document.task_assume_role_policy.json - - tags = { - Name = "dutymate-appserver-ecs-task-role" - } -} - -resource "aws_iam_role_policy_attachment" "appserver_ecs_task_role_policy" { - role = aws_iam_role.appserver_ecs_task_role.name +resource "aws_iam_role_policy_attachment" "ecs_task_role_policy" { + role = aws_iam_role.ecs_task_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonElastiCacheFullAccess" } diff --git a/Modules/IAM/outputs.tf b/Modules/IAM/outputs.tf index 42fd81a..a4c2a8e 100644 --- a/Modules/IAM/outputs.tf +++ b/Modules/IAM/outputs.tf @@ -1,11 +1,11 @@ -output "appserver_ecs_task_role_arn" { - value = aws_iam_role.appserver_ecs_task_role.arn -} - output "ecs_instance_profile_name" { value = aws_iam_instance_profile.ecs_instance_profile.name } +output "ecs_task_role_arn" { + value = aws_iam_role.ecs_task_role.arn +} + output "ecs_service_role_arn" { value = aws_iam_role.ecs_service_role.arn } @@ -17,7 +17,3 @@ output "ecs_task_execution_role_arn" { output "eventbridge_api_destinations_role_arn" { value = aws_iam_role.eventbridge_api_destinations_role.arn } - -output "webserver_ecs_task_role_arn" { - value = aws_iam_role.webserver_ecs_task_role.arn -} diff --git a/Modules/Networking/main.tf b/Modules/Networking/main.tf index 2e5d779..fe173b2 100644 --- a/Modules/Networking/main.tf +++ b/Modules/Networking/main.tf @@ -21,28 +21,6 @@ resource "aws_subnet" "public_subnets" { } } -resource "aws_subnet" "private_subnets" { - count = 2 - vpc_id = aws_vpc.vpc.id - cidr_block = var.private_subnet_cidr_block[count.index] - availability_zone = var.availability_zones[count.index] - - tags = { - Name = "dutymate-private-subnet${count.index + 1}" - } -} - -resource "aws_subnet" "database_subnets" { - count = 2 - vpc_id = aws_vpc.vpc.id - cidr_block = var.database_subnet_cidr_block[count.index] - availability_zone = var.availability_zones[count.index] - - tags = { - Name = "dutymate-database-subnet${count.index + 1}" - } -} - resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.vpc.id @@ -51,25 +29,6 @@ resource "aws_internet_gateway" "igw" { } } -resource "aws_eip" "ngw_eip" { - lifecycle { - create_before_destroy = true - } - - tags = { - Name = "dutymate-ngw-eip" - } -} - -resource "aws_nat_gateway" "ngw" { - allocation_id = aws_eip.ngw_eip.id - subnet_id = aws_subnet.public_subnets[0].id - - tags = { - Name = "dutymate-ngw" - } -} - resource "aws_default_route_table" "default_route_table" { default_route_table_id = aws_vpc.vpc.default_route_table_id @@ -96,96 +55,3 @@ resource "aws_route_table_association" "public_route_table_assoc" { subnet_id = aws_subnet.public_subnets[count.index].id route_table_id = aws_route_table.public_route_table.id } - -resource "aws_route_table" "private_route_table" { - vpc_id = aws_vpc.vpc.id - - route { - cidr_block = "0.0.0.0/0" - nat_gateway_id = aws_nat_gateway.ngw.id - } - - tags = { - Name = "dutymate-private-route-table" - } -} - -resource "aws_route_table_association" "private_route_table_assoc" { - count = 2 - subnet_id = aws_subnet.private_subnets[count.index].id - route_table_id = aws_route_table.private_route_table.id -} - -resource "aws_route_table" "database_route_table" { - vpc_id = aws_vpc.vpc.id - - tags = { - Name = "dutymate-database-route-table" - } -} - -resource "aws_route_table_association" "database_route_table_assoc" { - count = 2 - subnet_id = aws_subnet.database_subnets[count.index].id - route_table_id = aws_route_table.database_route_table.id -} - -resource "aws_vpc_endpoint" "vpce_s3" { - vpc_id = aws_vpc.vpc.id - vpc_endpoint_type = "Gateway" - service_name = "com.amazonaws.${var.aws_region}.s3" - route_table_ids = [aws_route_table.private_route_table.id] - - tags = { - Name = "dutymate-vpce-s3" - } -} - -resource "aws_vpc_endpoint" "vpce_amazonlinux" { - vpc_id = aws_vpc.vpc.id - vpc_endpoint_type = "Gateway" - service_name = "com.amazonaws.${var.aws_region}.s3" - route_table_ids = [aws_route_table.database_route_table.id] - - policy = < Date: Sat, 31 May 2025 04:53:47 +0900 Subject: [PATCH 6/7] chore: Remove snapshot_identifier configurations --- Modules/DocumentDB/main.tf | 1 - Modules/RDS/main.tf | 1 - 2 files changed, 2 deletions(-) diff --git a/Modules/DocumentDB/main.tf b/Modules/DocumentDB/main.tf index dc9a40a..13c7229 100644 --- a/Modules/DocumentDB/main.tf +++ b/Modules/DocumentDB/main.tf @@ -10,7 +10,6 @@ resource "aws_docdb_subnet_group" "docdbsg" { resource "aws_docdb_cluster" "docdb" { engine = "docdb" cluster_identifier = "dutymate-docdb-cluster" - snapshot_identifier = "docdb-snapshot" master_username = var.mongodb_username master_password = var.mongodb_password db_subnet_group_name = aws_docdb_subnet_group.docdbsg.id diff --git a/Modules/RDS/main.tf b/Modules/RDS/main.tf index a49b77e..c1becd5 100644 --- a/Modules/RDS/main.tf +++ b/Modules/RDS/main.tf @@ -15,7 +15,6 @@ resource "aws_db_instance" "db" { username = var.mysql_username password = var.mysql_password identifier = "dutymate-db" - snapshot_identifier = "rds-instance-snapshot" multi_az = false db_subnet_group_name = aws_db_subnet_group.dbsg.name vpc_security_group_ids = [var.sg_mysql_id] From 65360425f6fdfcbc135440ad676020a9c340cfcb Mon Sep 17 00:00:00 2001 From: Jongwoo Han Date: Sat, 31 May 2025 04:54:02 +0900 Subject: [PATCH 7/7] chore: Enable eventbridge api calls --- main.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.tf b/main.tf index aa7a838..b2e5d2f 100644 --- a/main.tf +++ b/main.tf @@ -58,12 +58,12 @@ module "elasticache" { sg_valkey_id = module.security_group.sg_valkey_id } -# module "eventbridge" { -# source = "./Modules/EventBridge" -# api_secret_key = var.api_secret_key -# domain_name = var.domain_name -# eventbridge_api_destinations_role_arn = module.iam.eventbridge_api_destinations_role_arn -# } +module "eventbridge" { + source = "./Modules/EventBridge" + api_secret_key = var.api_secret_key + domain_name = var.domain_name + eventbridge_api_destinations_role_arn = module.iam.eventbridge_api_destinations_role_arn +} module "iam" { source = "./Modules/IAM"