이번 글에서는 NLB 하나에 여러 서비스를 사용할 수 있도록 해보겠습니다.
해당 작업을 하게된 계기
현재 대부분의 코어 서비스들은 EKS 클러스터 내부에서 동작하고 있습니다.
Redis, Kafka, OpenObserve, AI-Gateway 등 주요 인프라 구성 요소들이 모두 Kubernetes 환경 위에서 운영되고 있습니다.
하지만 AI Agent 중 일부 애플리케이션은 안정성을 최우선으로 고려하여 ECS Fargate Task 기반으로 실행되고 있었고,
이 애플리케이션이 EKS 내부 서비스들과 통신해야 하는 요구사항이 발생했습니다.
처음 고려했던 구조: Internal ALB 통합
여러 서비스를 외부로 노출해야 하는 상황에서, 처음에는 하나의 Internal ALB에 여러 서비스를 묶는 구조를 고려했습니다.
ALB는 Host 기반, Path 기반 라우팅을 지원하기 때문에
HTTP 기반 서비스라면 하나의 로드밸런서로 충분히 통합이 가능하다고 판단했습니다.
그러나 여기서 문제가 발생했습니다.
ALB를 사용할 수 없었던 이유
ALB는 L7(Application Layer) 로드밸런서로, HTTP/HTTPS 프로토콜만을 지원합니다.
반면,
- Redis
- Kafka
이 두 서비스는 TCP 기반의 바이너리 프로토콜을 사용합니다.
즉, ALB는 HTTP 헤더를 기반으로 트래픽을 처리하는 구조이기 때문에,
TCP 레벨에서 동작하는 Redis와 Kafka 트래픽을 처리할 수 없습니다.
결과적으로 ALB는 이 요구사항을 충족할 수 없는 구조였습니다.
L4 기반 설계로 방향 전환
이에 따라 L7이 아닌, L4 레벨에서 동작하는 NLB(Network Load Balancer)를 사용하도록 방향을 전환했습니다.
NLB는 TCP/UDP 레벨에서 동작하기 때문에
Redis, Kafka와 같은 비-HTTP 프로토콜을 문제없이 처리할 수 있습니다.
또 다른 문제: 서비스 수만큼 생성되는 NLB
하지만 새로운 문제가 생겼습니다.
각 서비스마다 Internal NLB를 하나씩 생성하는 구조가 되었고,
- Redis → NLB 1개
- Kafka → NLB 1개
- OpenObserve → NLB 1개
- 기타 서비스 → 각각 NLB
이렇게 되면서 서비스 수만큼 NLB가 증가하게 되었고,
시간당 비용 + LCU 비용이 누적되면서 유지 비용이 비효율적인 구조가 되었습니다.
해결 방법: 단일 NLB + 포트 기반 Listener 분리
이 문제를 해결하기 위해 고민하던 중,
NLB의 Listener를 서비스별로 포트를 다르게 구성하면 하나의 NLB로 여러 서비스를 처리할 수 있다는 점에 주목했습니다.
즉,
- NLB:6379 → Redis
- NLB:31021 → Kafka
- NLB:5080 → OpenObserve
와 같이 Listener 포트 기반으로 Target Group을 분리하는 구조로 설계했습니다.
이렇게 구성함으로써,
- NLB 리소스를 하나로 통합
- 비용 절감
- 관리 포인트 단순화
라는 세 가지 목표를 동시에 달성할 수 있었습니다.
구현 방법
실제로 제가 했던 방법에 대해 알아보겠습니다.
1. NLB 생성
콘솔에서 다음과 같이 생성 하였습니다.

저 같은 경우 같은 ECS와 EKS가 같은 VPC에 있어서 내부 로드밸런서로 생성하였습니다.

ECS, EKS가 존재하는 VPC와 서브넷을 선택 해줍니다.
2. 대상 그룹 생성
이제 EKS 내부에 존재하는 파드들과 연결할 대상 그룹을 생성 해줍니다.

대상 유형은 IP 주소로 선택 하였습니다.
그리고 포트는 EKS Service에서 사용하고 있는 포트를 넣어주면 됩니다.
ex) 만약, redis 서비스가 6380 포트를 사용하고 있다면, 대상 그룹의 포트도 6380으로 지정
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
redis ClusterIP 10.100.206.42 <none> 6380/TCP프로토콜 또한, 각 대상이 사용하는 프로토콜에 맞춰서 사용하면 됩니다.
즉, redis는 TCP 프로토콜 사용하므로 대상 그룹의 프로토콜도 TCP로 지정
3. TargetGroupBinding 리소스 생성
저 같은 경우는 AWS Load Balancer Controller가 설치되어있어서
해당 controller가 제공하는 커스텀 리소스인 TargetGroupBinding을 사용하여
자동으로 대상 그룹의 대상을 매핑하도록 하였습니다.
- TargetGroupBinding 리소스 예시
apiVersion: elbv2.k8s.aws/v1beta1
kind: TargetGroupBinding
metadata:
name: redis-tgb
spec:
serviceRef:
name: redis # 실제 redis 파드와 연결된 서비스 이름
port: 6380 # 서비스가 노출하는 포트
targetGroupARN: <2번 과정에서 생성한 대상 그룹의 ARN을 넣어주면 됩니다.>
targetType: <2번 과정에서 생성한 대상 그룹의 대상 유형을 넣어주면 됩니다.>
networking:
ingress:
- from:
- securityGroup:
groupID: <1번 과정에서 생성한 NLB의 보안그룹을 넣어주면 됩니다.>
ports:
- port: <2번 과정에서 생성한 대상 그룹의 포트를 넣어주면 됩니다.>
protocol: <2번 과정에서 생성한 대상 그룹의 프로토콜을 넣어주면 됩니다.>이제 해당 리소스를 EKS에서 apply 하면

자동으로 대상그룹의 대상에 Redis 파드와 연결이 됩니다.
4. NLB 리스너 추가
1번 과정에서 생성한 NLB에서 아래 이미지 처럼 리스너를 추가합니다.

리스너를 추가할 때는, 대상 그룹이 사용하는 프로토콜과 포트를 넣어서 생성해주면 됩니다.
5. 동작 확인
저는 Redis insight 사용하여 실제로 앞선 과정으로 생성된 NLB 주소와 포트를 넣으면 연결이 되는지 확인해보았습니다.

이미지를 보면 정상적으로 접속이 되는 것을 확인할 수 있습니다.
이상 입니다.
감사합니다.
'AWS' 카테고리의 다른 글
| AWS NAT Gateway 비용 분석: S3 트래픽과 VPC Endpoint의 중요성 (0) | 2025.12.16 |
|---|---|
| AWS Lambda Layer란? Node.js 기반으로 직접 만들어보고 Lambda에서 적용하기 (1) | 2025.11.13 |
| Packer 사용해서 AWS ami 커스텀 해보기 (0) | 2025.09.30 |
| Karpenter로 EKS에서 Spot 인스턴스 자동 프로비저닝하기 (0) | 2025.09.03 |
| GCP <-> AWS VPN 연결 (1) | 2025.06.25 |