Terraform으로 Application Load Balancer 프로비저닝

최근에 Network Load Balancers에 대해 썼습니다. NLB에서 많은 마일리지를 얻지만 때때로 레이어 7 기능이 필요합니다.

한 가지 대안은 NLB를 유지하고 그 뒤에 Traefik과 같은 리버스 프록시를 배치하는 것입니다. 그러나 더 간단한 접근 방식은 둘 다 AWS의 다른 제품인 Application Load Balancer (ALB)으로 대체할 수 있습니다. 이 게시물에서는 old trustyTerraform의 도움으로 ALB를 프로비저닝하는 방법을 보여드리겠습니다.

Application Load Balancer 설정



고려해야 할 세 가지 주요 구성 요소는 로드 밸런서, 리스너 및 대상 그룹입니다. 나는 이것에 대해 내 previous article에 자세히 썼으므로 너무 많이 설명하지 않겠습니다. 대부분의 개념은 비슷합니다.



몇 가지 구체적인 측면에 초점을 맞추겠습니다. aws_lb 의 경우 다른 load_balancer_type ( application )를 사용합니다.


data "aws_subnet_ids" "this" {
  vpc_id = var.vpc_id

  tags = {
    Tier = "Public"
  }
}

resource "aws_lb" "this" {
  name = "basic-load-balancer"
  load_balancer_type = "application"
  subnets = data.aws_subnet_ids.this.ids

  enable_cross_zone_load_balancing = true
}


청취자



ALB의 경우 수신기는 HTTPS 또는 HTTP 여야 합니다. 이 단계에서 SSL 종료를 선택할 수 있습니다. 예를 들어 보겠습니다.


resource "aws_lb_listener" "this" {
  load_balancer_arn = aws_lb.this.arn

  port = 443
  protocol = "HTTPS"

  ssl_policy = "ELBSecurityPolicy-2016-08"
  certificate_arn = aws_acm_certificate.this.arn

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

data "aws_acm_certificate" "this" {
  domain = "${var.dns_record_name}.${var.dns_zone_name}"
}


다른SSL Security policies here에 대한 자세한 내용을 읽을 수 있습니다. 지금은 기존 인증서를 참조하고 있습니다. 나중에 Route53 덕분에 프로비저닝하는 방법을 살펴보겠습니다.

대상 그룹



이전 단계에서 SSL 종료를 수행한 대상 그룹은 HTTP 작업을 수행할 것입니다.


resource "aws_lb_target_group" "this" {
  port = 80
  protocol = "HTTP"
  vpc_id = var.vpc_id

  load_balancing_algorithm_type = "least_outstanding_requests"

  stickiness {
    enabled = true
    type = "lb_cookie"
  }

  health_check {
    healthy_threshold = 2
    interval = 30
    protocol = "HTTP"
    unhealthy_threshold = 2
  }

  depends_on = [
    aws_lb.this
  ]

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_autoscaling_attachment" "target" {
  autoscaling_group_name = var.autoscaling_group_name
  alb_target_group_arn = aws_lb_target_group.this.arn
}


표시할 몇 가지 추가 기능이 있습니다.
  • 로드 밸런싱을 사용자 정의하고 있습니다algorithm.
  • stickiness 블록이 있는 쿠키를 통해 고정 세션을 사용하고 있습니다.
  • health_check 블록이 포함된 사용자 지정 상태 확인이 있습니다.

  • 보안 그룹



    네트워크 로드 밸런서와 마찬가지로 트래픽이 보안 그룹을 통과하도록 허용해야 합니다.


    resource "aws_security_group" "this" {
      description = "Allow connection between ALB and target"
      vpc_id = var.vpc_id
    }
    
    resource "aws_security_group_rule" "ingress" {
      for_each = var.ports
    
      security_group_id = aws_security_group.this.id
      from_port = 443
      to_port = 443
      protocol = "tcp"
      type = "ingress"
      cidr_blocks = ["0.0.0.0/0"]
    }
    


    경로 기반 라우팅



    로드 밸런서는 우리가 요청하는 경로와 헤더를 알고 있으므로 이를 기반으로 라우팅 결정을 내릴 수 있습니다. 추가aws_lb_listener_rule 리소스를 사용하여 일반 리스너를 보강합니다.

    resource "aws_lb_listener_rule" "redirect_based_on_path" {
      listener_arn = aws_lb_listener.this.arn
    
      action {
        type = "forward"
        target_group_arn = aws_lb_target_group.alternative_target.arn
      }
    
      condition {
        path_pattern {
          values = ["/rest/v2/*"]
        }
      }
    }
    


    조건이 일치하면(이 경우 URL에서 새 버전의 API 사용) 기본 리스너가 무시됩니다. 대신 트래픽이 다른 대상 그룹으로 리디렉션됩니다. 마찬가지로 특정 헤더 또는 호스트 이름을 기반으로 다른 규칙을 만들 수 있습니다.

    Route53 설정



    우리는 확실히 자동 생성된 도메인을 통해 로드 밸런서에 액세스하지 않을 것입니다. 우리는 Route53을 사용하여 예쁜 도메인을 원합니다. 먼저 CNAME 레코드를 설정합니다.


    data "aws_route53_zone" "this" {
      name = var.dns_zone_name
    }
    
    resource "aws_route53_record" "this" {
      name = var.dns_record_name
      type = "CNAME"
    
      records = [
        aws_lb.this.dns_name,
      ]
    
      zone_id = data.aws_route53_zone.this.zone_id
      ttl = "60"
    }
    


    또한 도메인에 대한 인증서를 설정하고 있습니다. DNS 챌린지를 통해 자동으로 검증됩니다.


    resource "aws_acm_certificate" "this" {
      domain_name = "${var.dns_record_name}.${var.dns_zone_name}"
      validation_method = "DNS"
    
      lifecycle {
        create_before_destroy = true
      }
    }
    
    resource "aws_acm_certificate_validation" "this" {
      certificate_arn = aws_acm_certificate.this.arn
      validation_record_fqdns = [aws_route53_record.web_cert_validation.fqdn]
    
      lifecycle {
        create_before_destroy = true
      }
    }
    
    resource "aws_route53_record" "web_cert_validation" {
      name = aws_acm_certificate.this.domain_validation_options.0.resource_record_name
      type = aws_acm_certificate.this.domain_validation_options.0.resource_record_type
    
      records = [aws_acm_certificate.this.domain_validation_options.0.resource_record_value]
    
      zone_id = data.aws_route53_zone.zone.id
      ttl = 60
    
      lifecycle {
        create_before_destroy = true
      }
    }
    


    가격에 대한 한마디



    pricing page에서 볼 수 있듯이 ALB는 NLB와 동일한 고정 비용을 갖지만 트래픽을 처리할 때 더 비쌉니다(LCU 대 NLCU). 가격 세부 정보는 약간 난해합니다. 좋은 경험 법칙은 활용하려는 특정 기능이 있는 경우 ALB를 사용하는 것입니다.

    결론



    NLBs과 ALB의 조합은 로드 밸런싱 요구 사항의 전부는 아니지만 대부분을 처리합니다. 기능의 순전한 양은 압도적일 수 있습니다. 기본에 집중하기 시작하고 방대한 가능성을 하나씩 발견하는 것이 더 쉽다는 것을 알게 되었습니다.

    좋은 웹페이지 즐겨찾기