pulumi를 활용한 로드밸런서 통합

김성진·2025년 10월 13일

AWS ECS 환경에서 도메인별 로드밸런서 통합하기 (Pulumi + TypeScript)

🎯 프로젝트 배경

기존에는 각 마이크로서비스마다 개별 ALB(Application Load Balancer)를 생성하여 운영하고 있었습니다. 예를 들어:

  • kms-auth-api → 전용 ALB
  • kms-api → 전용 ALB
  • math-more-api → 전용 ALB
  • travel-agent → 전용 ALB
  • ... 등등

이러한 구조는 다음과 같은 문제가 있었습니다:
1. 비용 증가: ALB는 시간당 과금되므로, 앱이 늘어날수록 비용이 선형적으로 증가
2. 관리 복잡도: 각 ALB마다 별도의 보안 그룹, 리스너, 인증서 관리 필요
3. IP 리소스 낭비: 각 ALB마다 Public IP 할당

목표:

  • 도메인별로 하나의 ALB를 공유하도록 통합

  • 같은 도메인(laivdata.com, mathmore.ai, tripora.ai)을 사용하는 앱들끼리 ALB 공유

  • HOST 헤더 기반 라우팅으로 각 앱의 타겟 그룹으로 트래픽 분산


    🏗️ 아키텍처 설계

    Before (앱별 ALB)

    laivdata.com 도메인:
    ├─ kms-auth-api-dev.laivdata.com → ALB #1 → Target Group #1
    ├─ kms-api-dev.laivdata.com → ALB #2 → Target Group #2
    └─ kk-be-dev.laivdata.com → ALB #3 → Target Group #3

    mathmore.ai 도메인:
    └─ api-dev.mathmore.ai → ALB #4 → Target Group #4

    tripora.ai 도메인:
    ├─ api-dev.tripora.ai → ALB #5 → Target Group #5
    └─ tourvis-planwith-dev.laivdata.com → ALB #6 → Target Group #6

    After (도메인별 ALB 통합)

    laivdata.com 도메인:
    └─ dev-gluon-laivdata-com-alb (공통 ALB)
    ├─ kms-auth-api-dev.laivdata.com → Target Group #1
    ├─ kms-api-dev.laivdata.com → Target Group #2
    └─ kk-be-dev.laivdata.com → Target Group #3

    mathmore.ai 도메인:
    └─ dev-gluon-mathmore-ai-alb (공통 ALB)
    └─ api-dev.mathmore.ai → Target Group #4

    tripora.ai 도메인:
    └─ dev-gluon-tripora-ai-alb (공통 ALB)
    └─ api-dev.tripora.ai → Target Group #5


    📝 구현 단계

1단계: 인터페이스 및 타입 정의

기존에는 단일 로드밸런서 리소스였지만, 이제는 도메인별 맵 구조로 변경했습니다.

 infra/interface.ts
 // 단일 로드밸런서 리소스
 export interface ISingleLoadBalancerResource {
   sharedAlb: LoadBalancer;
   albSecurityGroup: SecurityGroup;
   httpListener: Listener;
   httpsListener: Listener;
 }

 // 도메인별 맵
 export interface ILoadBalancerResource {
   [domain: string]: ISingleLoadBalancerResource;
 }

 // 도메인 설정
 export interface IDomainConfig {
   hostedZoneId: string;
   domain: string;
 }

2단계: 도메인별 로드밸런서 생성

3단계: HOST 기반 라우팅 규칙 추가
각 앱 배포 시, 해당 도메인의 HTTPS 리스너에 HOST 헤더 기반 라우팅 규칙을 추가합니다.

4단계: Route53 수정

각 앱의 도메인이 해당 도메인의 ALB를 바라보도록 수정합니다.

  app/default-app-fargate/![](https://velog.velcdn.com/images/kimsj5259/post/721d0188-4f9c-4f38-9939-0cfd90c14eb3/image.jpeg)
route53.ts

  export function createRoute53(
    appDeployInfo: IAppDeployInfo,
    lbResource?: ILbResource
  ) {
    if (!appDeployInfo.domainInfo) return {};

    // 도메인에 해당하는 로드밸런서 가져오기
    const baseDomain = appDeployInfo.domainInfo.baseDomain.replace("*.", "");
    const lbResourceForDomain = appDeployInfo.infraResource.loadBalancerResource[baseDomain];

    if (!lbResourceForDomain) {
      console.error(`Load balancer not found for domain: ${baseDomain}`);
      return {};
    }

    const sharedAlb = lbResourceForDomain.sharedAlb;

    // Route 53 A 레코드 생성
    new aws.route53.Record(
      `${ENV}-${appDeployInfo.infraName}-${appDeployInfo.appName}-record`,
      {
        zoneId: appDeployInfo.domainInfo.hostedZoneId,
        name: `${appDeployInfo.domainInfo.domain}${
          ENV === "prod" ? "" : `-${ENV}`
        }.${baseDomain}`,
        type: "A",
        aliases: [{
          name: sharedAlb.dnsName,
          zoneId: sharedAlb.zoneId,
          evaluateTargetHealth: true,
        }],
      }
    );

    return {};
  }

5단계: Security Group 수정

ECS 보안 그룹이 해당 도메인의 ALB 보안 그룹만 허용하도록 수정합니다.


🚀 배포 및 마이그레이션

  1. 타입 에러 해결

    문제: HTTPS 리스너 생성 시 인증서가 필수
    error: A certificate must be specified for HTTPS listeners

    해결: ACM에서 도메인별 인증서를 가져와서 설정
    const certificateArn = pulumi.output(
    aws.acm.getCertificate({
    domain: domainConfig.domain,
    mostRecent: true,
    })
    ).arn;

  2. 타겟 그룹 충돌 해결

    문제: 기존 ALB에 연결된 타겟 그룹을 새 ALB에 연결 시도
    error: TargetGroupAssociationLimit: The following target groups cannot be
    associated with more than one load balancer

    해결 방법:

  3. AWS 콘솔에서 기존 앱별 ALB 수동 삭제

  4. 또는 Pulumi state에서 제거:
    pulumi state delete 'aws:lb/loadBalancer:LoadBalancer::dev-gluon-kms-auth-api-alb' --yes

  5. Pulumi refresh 후 재배포:
    pulumi refresh --yes
    pulumi up


    📊 결과 및 효과

    비용 절감

  • Before: 8개 앱 = 8개 ALB

  • After: 3개 도메인 = 3개 ALB

  • 절감률: ~62.5% (8개 → 3개)

    관리 간소화

  • ✅ 도메인별로 하나의 ALB만 관리

  • ✅ 보안 그룹, 인증서 관리 포인트 감소

  • ✅ HOST 헤더 기반으로 자동 라우팅

    확장성

  • ✅ 새로운 앱 추가 시 리스너 룰만 추가하면 됨

  • ✅ 동일 도메인의 앱은 추가 비용 없음


    💡 핵심 포인트

  1. 도메인별 그룹핑: 같은 도메인을 사용하는 앱들을 하나의 ALB로 묶음

  2. HOST 헤더 라우팅: ALB 리스너 룰의 HOST 조건으로 각 앱 분기

  3. Pulumi Output: 비동기 리소스는 pulumi.output() 사용

  4. 마이그레이션 전략: 기존 리소스 정리 후 새 구조로 전환


    🔗 참고 자료

profile
multi-national communicator with programming (back-end)

0개의 댓글