Devops/Terraform

[테라폼] 테라폼(Terraform) 완전 정복: AWS 인프라를 Terraform으로 완전 자동화하기 (Route53, ALB, Lambda, CloudFront) - 2

일요일좋아하는사람 2025. 4. 19. 22:06
728x90
반응형

Terraform + aws

✨ 들어가며

이전 글에서는 Terraform을 이용해 AWS의 기초 인프라 서비스들인 VPC, IAM, EC2, EKS, ECS, Fargate 등을 구성하는 방법에 대해 살펴봤습니다. IAM 사용자 생성, EC2 인스턴스 배포, Kubernetes 클러스터 구축까지 자동화해보며 인프라를 코드로 관리하는 경험을 해보셨을 텐데요.

이번 글에서는 조금 더 확장된 인프라 서비스들인 Route53, ALB, Lambda, CloudWatch, CloudFront 같은 고급 AWS 리소스들을 Terraform으로 어떻게 구성할 수 있는지 구체적인 예제와 함께 소개하려고 합니다.


목차

  1. Terraform으로 Route53 도메인/레코드 관리
  2. Application Load Balancer(ALB) 구성
  3. Lambda 함수 배포
  4. CloudWatch 로그 및 메트릭 설정
  5. CloudFront CDN 구성
  6. 보안그룹, 인증서(ACM), HTTPS 연동
  7. 정리 및 실전 팁

1. Route53 도메인/레코드 관리

도메인 등록은 Terraform으로 할 수 없어

Terraform은 AWS에서 직접 도메인을 등록하는 기능은 없지만, 이미 등록된 도메인의 호스팅 존과 레코드 관리는 가능합니다.

예시: 호스팅 존과 A 레코드 생성

resource "aws_route53_zone" "main" {
  name = "example.com"
}

resource "aws_route53_record" "www" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "www.example.com"
  type    = "A"
  ttl     = 300
  records = ["203.0.113.10"]
}

ALB와 연동한 레코드 생성

resource "aws_route53_record" "alb_record" {
  zone_id = aws_route53_zone.main.zone_id
  name    = "app.example.com"
  type    = "A"

  alias {
    name                   = aws_lb.alb.dns_name
    zone_id                = aws_lb.alb.zone_id
    evaluate_target_health = true
  }
}

2. ALB (Application Load Balancer) 구성

ALB 생성

resource "aws_lb" "alb" {
  name               = "app-load-balancer"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.lb.id]
  subnets            = var.subnet_ids

  tags = {
    Environment = "production"
  }
}

리스너와 대상 그룹 구성

resource "aws_lb_target_group" "web" {
  name     = "web-target-group"
  port     = 80
  protocol = "HTTP"
  vpc_id   = var.vpc_id
}

resource "aws_lb_listener" "http" {
  load_balancer_arn = aws_lb.alb.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.web.arn
  }
}

3. Lambda 함수 배포

Terraform은 S3에 zip 파일을 업로드하고 Lambda 함수로 배포할 수 있도록 지원합니다.

예제 코드

resource "aws_iam_role" "lambda_exec" {
  name = "lambda_exec_role"

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

resource "aws_lambda_function" "hello" {
  function_name = "helloLambda"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "index.handler"
  runtime       = "nodejs18.x"

  filename         = "lambda/hello.zip"
  source_code_hash = filebase64sha256("lambda/hello.zip")
}

이벤트 트리거 연결 예: API Gateway

resource "aws_apigatewayv2_api" "http_api" {
  name          = "lambda-http-api"
  protocol_type = "HTTP"
}

resource "aws_apigatewayv2_integration" "lambda_integration" {
  api_id             = aws_apigatewayv2_api.http_api.id
  integration_type   = "AWS_PROXY"
  integration_uri    = aws_lambda_function.hello.invoke_arn
  integration_method = "POST"
  payload_format_version = "2.0"
}

4. CloudWatch 모니터링 설정

Lambda나 EC2, ALB 등의 로그를 수집하려면 CloudWatch 로그 그룹 설정이 필요합니다.

예제: CloudWatch 로그 그룹 생성

resource "aws_cloudwatch_log_group" "lambda_logs" {
  name              = "/aws/lambda/helloLambda"
  retention_in_days = 14
}

CloudWatch 알람 예: CPU 80% 초과 시 경고

resource "aws_cloudwatch_metric_alarm" "cpu_high" {
  alarm_name          = "high-cpu-alarm"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = "2"
  metric_name         = "CPUUtilization"
  namespace           = "AWS/EC2"
  period              = "120"
  statistic           = "Average"
  threshold           = "80"
  alarm_description   = "이 인스턴스는 CPU 사용률이 80%를 넘었습니다."
  dimensions = {
    InstanceId = aws_instance.web.id
  }
}

5. CloudFront CDN 구성

CloudFront는 전 세계 엣지 위치를 통해 콘텐츠를 빠르게 제공할 수 있는 CDN입니다.

S3 + CloudFront 연결 예제

resource "aws_cloudfront_origin_access_identity" "oai" {
  comment = "OAI for S3"
}

resource "aws_s3_bucket_policy" "s3_policy" {
  bucket = aws_s3_bucket.example.bucket

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          AWS = aws_cloudfront_origin_access_identity.oai.iam_arn
        }
        Action = "s3:GetObject"
        Resource = "${aws_s3_bucket.example.arn}/*"
      }
    ]
  })
}

resource "aws_cloudfront_distribution" "cdn" {
  origin {
    domain_name = aws_s3_bucket.example.bucket_regional_domain_name
    origin_id   = "s3-origin"

    s3_origin_config {
      origin_access_identity = aws_cloudfront_origin_access_identity.oai.cloudfront_access_identity_path
    }
  }

  enabled             = true
  is_ipv6_enabled     = true
  default_root_object = "index.html"

  default_cache_behavior {
    allowed_methods  = ["GET", "HEAD"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "s3-origin"

    viewer_protocol_policy = "redirect-to-https"
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

6. 보안과 HTTPS 구성

ACM (AWS Certificate Manager) 인증서 생성 예

resource "aws_acm_certificate" "cert" {
  domain_name       = "app.example.com"
  validation_method = "DNS"
}

ALB와 HTTPS 연결

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.alb.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-2016-08"
  certificate_arn   = aws_acm_certificate.cert.arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.web.arn
  }
}

7. 정리 및 실전 팁

Terraform으로 구성할 수 있는 AWS 서비스는 이 외에도 매우 다양합니다:

  • Elasticache (Redis/Memcached)
  • SNS / SQS
  • DynamoDB / Aurora / DocumentDB
  • Step Functions / EventBridge

실전 팁

  • 상태 파일은 S3 + DynamoDB로 저장하고 잠금 관리하세요.
  • terraform workspace를 사용하여 개발/운영 환경을 나눌 수 있습니다.
  • CI/CD와 연동할 때는 terraform plan 결과를 PR에 붙이는 것도 좋은 방법입니다.
  • 변경 이력 관리를 위해 terraform-docs, tflint, checkov 등의 도구를 함께 쓰세요.

 

728x90
반응형