반응형
목차
쿠버네티스 환경에서 AWS ALB Ingress Controller를 사용하면, 하나의 ALB로 여러 서비스에 트래픽을 라우팅할 수 있습니다.
이 글에서는 포트와 Path를 활용한 라우팅 개념부터 Terraform 예제, 그리고 포트 매핑 케이스별 매트릭스와 패킷 흐름까지 전부 정리합니다.
1. ALB + Kubernetes에서 포트 흐름 이해하기
ALB → Kubernetes Service → Pod 컨테이너 포트는 아래 4단계로 연결됩니다.
[Client]
↓ Listener Port
[ALB Listener]
↓ Target Group Port (Service Port)
[Kubernetes Service]
↓ targetPort
[Pod Container Port]
| 구분 | 설명 | 예시 |
| ALB Listener Port | ALB가 외부 요청을 받는 포트 | 80, 443, 81 등 |
| Ingress backend.service.port.number | ALB Target Group이 연결하는 Service Port | 80 |
| Service Port | 쿠버네티스 내부에서 Service가 노출하는 포트 | 80 |
| targetPort | Pod 컨테이너 내부에서 앱이 리스닝하는 실제 포트 | 3000 |
💡 중요 포인트
- Listener 포트와 Service Port는 반드시 같을 필요 없습니다.
- Service Port → targetPort 변환은 K8s Service에서 처리됩니다.
2. ALB 포트 매핑 케이스별 매트릭스
| 케이스 | ALB Listener Port | Service Port (backend.service.port.number) | targetPort (Pod Port) | 특징 / 동작 방식 | 주의사항 |
| ① 동일 포트 매핑 | 80 | 80 | 80 | 모든 구간 포트 동일. 관리 단순. | 컨테이너가 해당 포트 리스닝 필요. |
| ② Listener ≠ Service | 81 | 80 | 80 | ALB가 81번에서 받은 요청을 Service 80번에 전달. | 헷갈리지 않게 문서화 필수. |
| ③ Service ≠ targetPort | 80 | 80 | 3000 | Service가 80으로 받고 Pod의 3000으로 전달. | 앱 내부 포트와 외부 노출 포트를 분리 가능. |
| ④ Listener ≠ Service ≠ targetPort | 81 | 80 | 3000 | 각 단계별 포트 변환. | 트러블슈팅 시 흐름 추적 필요. |
| ⑤ 여러 Listener → 각기 다른 Service | 80, 81 | 80, 81 | 3000, 4000 | 포트별로 서비스 분리. | Listener/Service 매핑 설계 중요. |
| ⑥ 같은 Listener, Path별 다른 Service | 80 | 80, 80 | 3000, 4000 | 경로 기반 라우팅. 비용 절감에 유리. | Path 충돌 방지 필요. |
3. 패킷 흐름 다이어그램
아래는 /app1과 /app2가 같은 ALB(80포트)에서 다른 서비스로 라우팅되는 예입니다.
클라이언트
↓ http://ALB:80/app1
[ALB Listener :80]
↓ (Rule: /app1)
[Target Group : service-a:80]
↓
[Service-a Port:80 → targetPort:3000]
↓
[Pod 컨테이너 :3000]
클라이언트
↓ http://ALB:80/app2
[ALB Listener :80]
↓ (Rule: /app2)
[Target Group : service-b:80]
↓
[Service-b Port:80 → targetPort:4000]
↓
[Pod 컨테이너 :4000]
4. Service Port 중복 가능 여부
- 가능: 같은 네임스페이스 내 서로 다른 Service에서 동일한 port 값 사용 가능
- 불가: 같은 Service 내 spec.ports.port 중복
- NodePort 타입: nodePort 값은 클러스터 전체에서 고유해야 함
5. 같은 ALB 그룹, 같은 포트, Path별 다른 서비스 라우팅 예제
아래 예제는
- ALB 하나 (group.name 동일)
- Listener: 80 포트
- /app1 → service-a:80
- /app2 → service-b:80
로 라우팅합니다.
Service 예시
# service-a
apiVersion: v1
kind: Service
metadata:
name: service-a
namespace: app
spec:
selector:
app: app-a
ports:
- port: 80
targetPort: 3000
# service-b
apiVersion: v1
kind: Service
metadata:
name: service-b
namespace: app
spec:
selector:
app: app-b
ports:
- port: 80
targetPort: 4000
Terraform – Ingress 2개로 Path 분리
# Ingress for /app1
resource "kubernetes_ingress_v1" "alb_ingress_app1" {
metadata {
name = "alb-ingress-app1"
namespace = "app"
annotations = {
"kubernetes.io/ingress.class" = "alb"
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/target-type" = "ip"
"alb.ingress.kubernetes.io/group.name" = "shared-alb"
"alb.ingress.kubernetes.io/listen-ports" = jsonencode([{ HTTP = 80 }])
}
}
spec {
rule {
http {
path {
path = "/app1"
path_type = "Prefix"
backend {
service {
name = "service-a"
port { number = 80 }
}
}
}
}
}
}
}
# Ingress for /app2
resource "kubernetes_ingress_v1" "alb_ingress_app2" {
metadata {
name = "alb-ingress-app2"
namespace = "app"
annotations = {
"kubernetes.io/ingress.class" = "alb"
"alb.ingress.kubernetes.io/scheme" = "internet-facing"
"alb.ingress.kubernetes.io/target-type" = "ip"
"alb.ingress.kubernetes.io/group.name" = "shared-alb"
"alb.ingress.kubernetes.io/listen-ports" = jsonencode([{ HTTP = 80 }])
}
}
spec {
rule {
http {
path {
path = "/app2"
path_type = "Prefix"
backend {
service {
name = "service-b"
port { number = 80 }
}
}
}
}
}
}
}
6. 동작 흐름
http://<ALB-DNS>/app1 → service-a:80 → Pod:3000
http://<ALB-DNS>/app2 → service-b:80 → Pod:4000
- ALB Listener: 80 포트
- Path별로 다른 Target Group(Service)로 라우팅
- Service Port는 동일(80)해도 서비스 이름으로 구분되므로 충돌 없음
7. 운영 시 주의사항
- Path는 고유해야 함 → 중복 시 Controller가 충돌로 인식
- 경로 우선순위는 ALB에서 자동 부여
- Host 조건을 추가하면 같은 Path도 구분 가능 (app1.example.com vs app2.example.com)
- target-type=ip 모드 사용 시, ALB가 직접 Pod IP:targetPort로 연결 → NodePort 불필요
🔚 마무리
AWS ALB Ingress Controller를 쓰면 하나의 ALB로 여러 서비스를 깔끔하게 운영할 수 있습니다.
포트와 Path 구조를 이해하면, 비용을 절감하면서도 라우팅을 자유롭게 구성할 수 있습니다.
Terraform으로 관리하면 선언형으로 재현이 가능하니, 실무 환경에서는 반드시 IaC로 적용하는 걸 추천드립니다.
반응형
'DevOps' 카테고리의 다른 글
| Terraform으로 ArgoCD + GitHub Deploy Key 구성 시 SSH 인증 오류 해결기 (0) | 2025.08.08 |
|---|---|
| Terraform으로 AWS ALB Ingress 삭제 시 finalizer에 걸려 무한 대기하는 문제 해결기 (0) | 2025.08.08 |
| GitHub Actions로 FastAPI Docker 이미지 AWS ECR에 자동 배포하기 (0) | 2025.08.07 |
| AWS EKS에서 NLB + ingress-nginx 구성 시 가장 많이 쓰는 방식은? (0) | 2025.07.29 |
| Helm의 기본 개념과 커스터마이징의 한계 그리고 확장 전략 (0) | 2025.07.29 |
댓글