쿠버네티스에서 네트워크 트래픽을 최적화하는 기능인 Topology Aware Routing을 실무 관점에서 정리해 보자
개요
Topology Aware Routing(이전명: Topology Aware Hints)는 쿠버네티스 1.23에서 베타 기능으로 도입됐고, 1.27부터 현재의 이름으로 변경되었습니다. Amazon EKS에서는 1.24부터 지원하며, 같은 가용 영역(Availability Zone) 안에서 트래픽을 유지해 네트워크 지연 시간과 비용을 줄이는 것을 목표로 합니다.
하지만 모든 환경에서 작동하는 것은 아니며, 특정 조건을 만족해야 효과가 있습니다. 이 가이드에서는 이론 설명과 함께 실무에서 마주치는 다양한 상황과 해결책을 다룹니다.
이름 변화 히스토리
- Kubernetes 1.21~1.22: Topology Aware Hints (alpha)
- Kubernetes 1.23~1.26: Topology Aware Hints (beta)
- Kubernetes 1.27+: Topology Aware Routing으로 명명 변경
핵심 개념
기본 동작 원리
Topology Aware Routing은 kube-proxy가 Service의 엔드포인트를 선택할 때 토폴로지 정보를 활용하도록 합니다.
# Service 예시
apiVersion: v1
kind: Service
metadata:
name: my-service
annotations:
service.kubernetes.io/topology-mode: "auto"
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
주요 이점
- 네트워크 지연 시간 감소: 동일 AZ 내 통신으로 지연 시간 최소화
- 데이터 전송 비용 절약: 크로스-AZ 트래픽 비용 제거
- 자동 최적화: 수동 설정 없이 자동으로 최적 라우팅
작동 메커니즘
EndpointSlice Controller의 역할
EndpointSlice Controller는 아래 과정으로 힌트를 할당합니다.
- Pod 분산 확인: 각 zone별 Pod 수 계산
- 비례 할당: 각 zone의 Pod 수에 비례하여 엔드포인트 할당
- 힌트 생성: 각 엔드포인트에
hints.forZones필드 추가
# EndpointSlice 예시
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-abc123
endpoints:
- addresses:
- "10.1.2.3"
hints:
forZones:
- name: "zone-a"
kube-proxy 동작
kube-proxy는 힌트가 있는 엔드포인트를 우선적으로 사용합니다.
# iptables 규칙 예시 (실제로는 더 복잡)
-A KUBE-SVC-XYZ -m comment --comment "zone-a endpoints only" \
-j KUBE-SEP-LOCAL-ZONE
사용 조건 및 제한사항
사용 가능 조건
- 균등 분산: 워크로드가 모든 zone에 균등하게 분산되어야 함
- 충분한 엔드포인트: 각 zone에 최소 1개 이상의 엔드포인트 존재
- Service 타입: ClusterIP, NodePort, LoadBalancer 지원
사용 불가 조건
# 불균등 분산 예시 (동작하지 않음)
# Zone A: 10 pods
# Zone B: 2 pods
# Zone C: 1 pod
실무에서 흔한 실수
1. 개발 환경 단일 파드 (작동 안 함)
# 개발환경에서 흔한 실수
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 1 # ← 파드 1개만 있으면 TAR 비활성화!
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/topology-mode: "auto" # ← 설정해도 무시됨
2. 이중화 2대 구성 (대부분 작동 안 함)
# 비용 절약을 위한 2대 이중화 - TAR 제한적
spec:
replicas: 2 # 3개 zone에서는 불균등 분산으로 TAR 비활성화
# 실제 배치 예시:
# Zone A: 1개 파드
# Zone B: 1개 파드
# Zone C: 0개 파드 ← 빈 zone으로 인해 TAR 비활성화
제한사항
- ExternalName Service: 지원하지 않음
- Headless Service: 부분적 지원
- 불균등 분산: 자동으로 힌트가 제거됨
- 파드 수 < Zone 수: EndpointSlice controller가 힌트 생성 안함
- Zone당 파드 3개 미만: 50% 확률로 힌트 생성 실패
구성 방법
1. Service 어노테이션 설정
apiVersion: v1
kind: Service
metadata:
name: my-service
annotations:
# 자동 모드 (권장)
service.kubernetes.io/topology-mode: "auto"
spec:
selector:
app: my-app
ports:
- port: 80
2. Deployment 배포 전략
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 6 # zone당 2개씩 균등 배포
template:
spec:
# Zone 간 균등 분산을 위한 설정
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: my-app
성능 효과 분석
지연 시간 개선
| 시나리오 | 기본 설정 | Topology Aware Hints | 개선율 |
|---|---|---|---|
| 동일 AZ 통신 | ~1ms | ~0.5ms | 50% |
| 크로스 AZ 통신 | ~3-5ms | ~0.5ms | 80-90% |
비용 절감 효과
# AWS 데이터 전송 비용 예시
# 크로스-AZ: $0.01/GB
# 동일-AZ: $0.00/GB
# 월 1TB 데이터 전송 시
# 기존: $10.24 (크로스-AZ)
# 적용 후: $0 (동일-AZ)
# 절약: 100%
모니터링 및 트러블슈팅
1. 클러스터 Zone 구성 확인
# Zone 수 확인 (가장 중요!)
kubectl get nodes -o jsonpath='{.items[*].metadata.labels.topology\.kubernetes\.io/zone}' | tr ' ' '\n' | sort -u | wc -l
# Zone 목록 확인
kubectl get nodes -o custom-columns="NAME:.metadata.name,ZONE:.metadata.labels['topology\.kubernetes\.io/zone']"
# Zone별 노드 분포 확인
kubectl get nodes -o json | jq -r '.items[] | .metadata.labels["topology.kubernetes.io/zone"]' | sort | uniq -c
출력 예시:
2 ap-northeast-2a
2 ap-northeast-2b
2 ap-northeast-2c
# → 3개 zone, TAR 적용 가능 ✅
2. Zone 정보 종합 확인 스크립트
#!/bin/bash
# zone-check.sh - TAR 적용 가능성 자동 판단
ZONE_COUNT=$(kubectl get nodes -o jsonpath='{.items[*].metadata.labels.topology\.kubernetes\.io/zone}' | tr ' ' '\n' | sort -u | wc -l)
echo "=== Topology Aware Routing 적용 가능성 분석 ==="
echo "📊 총 Zone 수: $ZONE_COUNT"
case $ZONE_COUNT in
1)
echo "❌ TAR 적용 불가 (Single AZ)"
echo "💡 권장: 기본 로드밸런싱 사용"
;;
2)
echo "⚠️ TAR 제한적 적용 가능"
echo "💡 권장: 파드 2개 이상 + 균등 분산 필수"
;;
3)
echo "✅ TAR 최적화 가능"
echo "💡 권장: 파드 최소 3개 (zone당 1개씩)"
echo "🚀 이상적: 파드 9개 이상 (zone당 3개씩)"
;;
*)
echo "✅ TAR 최적화 가능"
echo "💡 권장: 파드 최소 ${ZONE_COUNT}개 (zone당 1개씩)"
;;
esac
3. EndpointSlice 힌트 확인
# EndpointSlice 힌트 확인
kubectl get endpointslices -o yaml | grep -A5 hints
# 특정 서비스의 EndpointSlice 상세 확인
kubectl describe endpointslices -l kubernetes.io/service-name=my-service
2. Service 상태 확인
# Service 이벤트 확인
kubectl describe service my-service
# 힌트 관련 로그 확인
kubectl logs -n kube-system -l component=kube-proxy | grep topology
3. 일반적인 문제 해결
힌트가 생성되지 않는 경우
# Pod 분산 상태 확인
kubectl get pods -o wide --show-labels | grep my-app
# Zone별 Pod 수 확인
kubectl get nodes --show-labels | grep topology.kubernetes.io/zone
불균등 분산 해결
# PodDisruptionBudget을 통한 안정적 배포
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 1
selector:
matchLabels:
app: my-app
주의사항 및 실무 권장사항
1. 환경별 TAR 적용 가이드
개발/테스트 환경
# 비용 우선 → TAR 비활성화 권장
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 1-2 # 최소 리소스
---
apiVersion: v1
kind: Service
metadata:
annotations:
# TAR 명시적 비활성화 (불필요한 오버헤드 방지)
service.kubernetes.io/topology-mode: "disabled"
프로덕션 환경
# 성능 + 비용 절약 → TAR 적극 활용
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 6 # zone 수(3) × 2 = 균등 분산
template:
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.kubernetes.io/topology-mode: "auto"
2. Zone 수에 따른 최적 구성
| Zone 수 | 최소 파드 수 | 권장 파드 수 | TAR 효과 |
|---|---|---|---|
| 1개 | N/A | N/A | ❌ 불가능 |
| 2개 | 2개 | 4개 이상 | ⚠️ 제한적 |
| 3개 | 3개 | 9개 이상 | ✅ 최적 |
| 4개+ | zone 수 | zone × 3 | ✅ 최적 |
3. 비용 vs 성능 분석
비용 관점
# 시나리오 1: TAR 미적용 (2대 이중화)
월 인스턴스 비용: $200 × 2 = $400
크로스-AZ 데이터 전송: $10-50/월 (트래픽에 따라)
총비용: $410-450/월
# 시나리오 2: TAR 적용 (3대 분산)
월 인스턴스 비용: $200 × 3 = $600
크로스-AZ 데이터 전송: $0-5/월 (거의 제거)
총비용: $600-605/월
# ROI 계산: 높은 트래픽일수록 TAR이 유리!
4. 가용성 vs 성능 트레이드오프
# 높은 가용성이 필요한 경우 비활성화 고려
metadata:
annotations:
service.kubernetes.io/topology-mode: "disabled"
5. 동적 스케일링 고려
# HPA 사용 시 zone 균형 유지 필수!
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 3 # zone 수와 동일하게 설정
maxReplicas: 12 # zone 수의 배수로 설정
실습 예제
전체 구성 예시
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 6
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web
image: nginx:alpine
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
# 균등 분산 보장
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-app
---
apiVersion: v1
kind: Service
metadata:
name: web-service
annotations:
service.kubernetes.io/topology-mode: "auto"
spec:
selector:
app: web-app
ports:
- name: http
port: 80
targetPort: 80
type: ClusterIP
검증 스크립트
#!/bin/bash
# topology-check.sh
echo "=== Topology Aware Hints 검증 ==="
# 1. Service 힌트 모드 확인
echo "1. Service 어노테이션 확인:"
kubectl get service web-service -o jsonpath='{.metadata.annotations}' | jq
# 2. EndpointSlice 힌트 확인
echo "2. EndpointSlice 힌트 확인:"
kubectl get endpointslices -l kubernetes.io/service-name=web-service -o yaml | grep -A10 hints
# 3. Pod 분산 상태 확인
echo "3. Pod zone별 분산 상태:"
kubectl get pods -l app=web-app -o wide | awk '{print $7}' | sort | uniq -c
# 4. kube-proxy 로그 확인 (선택사항)
echo "4. kube-proxy 토폴로지 관련 로그:"
kubectl logs -n kube-system -l component=kube-proxy --tail=50 | grep -i topology || echo "로그 없음"
성능 측정
벤치마크 테스트
# 성능 측정용 Pod 배포
kubectl run perf-test --image=busybox --rm -it --restart=Never -- sh
# 서비스 응답 시간 측정
for i in {1..100}; do
time wget -qO- http://web-service/health
done | grep real | awk '{sum+=$2} END {print "평균:", sum/NR "초"}'
결론 및 실무 의사결정 가이드
Topology Aware Routing을 쓰면 쿠버네티스 클러스터의 네트워크 성능과 비용 효율성을 크게 개선할 수 있습니다. 하지만 모든 환경에 적합한 것은 아니며, 신중한 검토가 필요합니다.
TAR 도입 결정 플로우차트
1. 클러스터 Zone 수는?
└─ 1개 Zone → ❌ TAR 불가, 끝
└─ 2개 Zone → 다음 단계
└─ 3개+ Zone → 다음 단계
2. 환경 성격은?
└─ 개발/테스트 → ❌ TAR 불필요 (비용 우선)
└─ 프로덕션 → 다음 단계
3. 트래픽 특성은?
└─ 저트래픽 → △ TAR 효과 미미
└─ 고트래픽 → 다음 단계
4. 파드 확장 가능성?
└─ 2대 고정 → ❌ TAR 제한적
└─ 3대+ 가능 → ✅ TAR 도입!
환경별 최종 권장사항
개발/테스트 환경
# 결론: TAR 적용 불필요
replicas: 1-2
service.kubernetes.io/topology-mode: "disabled"
# 이유: 비용 절약 > 성능 최적화
스테이징 환경
# 결론: TAR 테스트 목적으로만 적용
replicas: 3-6
service.kubernetes.io/topology-mode: "auto"
# 이유: 프로덕션 환경 사전 검증
프로덕션 환경
# 결론: 적극적 TAR 도입
replicas: zone_count × 3 # 최적화
service.kubernetes.io/topology-mode: "auto"
# 이유: 성능 + 비용 절약 효과 극대화
핵심 요약
도입하면 좋은 경우
- 3개 이상 Zone을 가진 프로덕션 환경
- 높은 트래픽과 잦은 서비스 간 통신
- 파드를 zone 수의 배수로 확장 가능
- 네트워크 지연 시간과 비용에 민감한 워크로드
도입하지 말아야 하는 경우
- 단일 Zone 클러스터
- 개발/테스트 환경 (비용 우선)
- 파드 1-2개로 고정된 마이크로서비스
- 트래픽이 매우 적은 서비스
신중히 검토해야 하는 경우
- 2개 Zone 클러스터 (제한적 효과)
- 동적 스케일링이 중요한 서비스
- 높은 가용성이 절대적으로 필요한 서비스
실무 체크리스트
도입 전 확인사항:
- [ ]
kubectl get nodesZone 수 확인 (3개+ 권장) - [ ] 현재 파드 수와 확장 계획 검토
- [ ] 트래픽 패턴 및 비용 분석
- [ ] HPA 설정 시 zone 균형 고려
- [ ] 모니터링 및 알람 설정 계획
도입 후 검증사항:
- [ ] EndpointSlice hints 필드 생성 확인
- [ ] 크로스-AZ 트래픽 감소 측정
- [ ] 네트워크 지연 시간 개선 확인
- [ ] 데이터 전송 비용 절감 확인
권장사항
- 단계적 도입: 비즈니스 임팩트가 낮은 서비스부터 시작
- 충분한 테스트: 스테이징 환경에서 먼저 검증
- 지속적 모니터링: 힌트 생성 상태와 효과 측정
- 팀 교육: 운영팀 대상 TAR 원리와 트러블슈팅 방법 공유
- 문서화: 의사결정 과정과 설정 기준 문서화
Topology Aware Routing은 모든 환경에 적용하는 만능 해결책이 아니라, 적절한 조건에서 큰 효과를 내는 도구입니다.