Kubernetes Topology Aware Routing 가이드

목차

쿠버네티스에서 네트워크 트래픽을 최적화하는 기능인 Topology Aware Routing을 실무 관점에서 정리해 보자

개요

Topology Aware Routing(이전명: Topology Aware Hints)는 쿠버네티스 1.23에서 베타 기능으로 도입됐고, 1.27부터 현재의 이름으로 변경되었습니다. Amazon EKS에서는 1.24부터 지원하며, 같은 가용 영역(Availability Zone) 안에서 트래픽을 유지해 네트워크 지연 시간과 비용을 줄이는 것을 목표로 합니다.

하지만 모든 환경에서 작동하는 것은 아니며, 특정 조건을 만족해야 효과가 있습니다. 이 가이드에서는 이론 설명과 함께 실무에서 마주치는 다양한 상황과 해결책을 다룹니다.

이름 변화 히스토리

핵심 개념

기본 동작 원리

Topology Aware Routing은 kube-proxy가 Service의 엔드포인트를 선택할 때 토폴로지 정보를 활용하도록 합니다.

yaml
# 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

주요 이점

  1. 네트워크 지연 시간 감소: 동일 AZ 내 통신으로 지연 시간 최소화
  2. 데이터 전송 비용 절약: 크로스-AZ 트래픽 비용 제거
  3. 자동 최적화: 수동 설정 없이 자동으로 최적 라우팅

작동 메커니즘

EndpointSlice Controller의 역할

EndpointSlice Controller는 아래 과정으로 힌트를 할당합니다.

  1. Pod 분산 확인: 각 zone별 Pod 수 계산
  2. 비례 할당: 각 zone의 Pod 수에 비례하여 엔드포인트 할당
  3. 힌트 생성: 각 엔드포인트에 hints.forZones 필드 추가
yaml
# 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는 힌트가 있는 엔드포인트를 우선적으로 사용합니다.

bash
# iptables 규칙 예시 (실제로는 더 복잡)
-A KUBE-SVC-XYZ -m comment --comment "zone-a endpoints only" \
  -j KUBE-SEP-LOCAL-ZONE

사용 조건 및 제한사항

사용 가능 조건

  1. 균등 분산: 워크로드가 모든 zone에 균등하게 분산되어야 함
  2. 충분한 엔드포인트: 각 zone에 최소 1개 이상의 엔드포인트 존재
  3. Service 타입: ClusterIP, NodePort, LoadBalancer 지원

사용 불가 조건

yaml
# 불균등 분산 예시 (동작하지 않음)
# Zone A: 10 pods
# Zone B: 2 pods  
# Zone C: 1 pod

실무에서 흔한 실수

1. 개발 환경 단일 파드 (작동 안 함)

yaml
# 개발환경에서 흔한 실수
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 1  # ← 파드 1개만 있으면 TAR 비활성화!
---
apiVersion: v1
kind: Service
metadata:
  annotations:
    service.kubernetes.io/topology-mode: "auto"  # ← 설정해도 무시됨

2. 이중화 2대 구성 (대부분 작동 안 함)

yaml
# 비용 절약을 위한 2대 이중화 - TAR 제한적
spec:
  replicas: 2  # 3개 zone에서는 불균등 분산으로 TAR 비활성화
  
# 실제 배치 예시:
# Zone A: 1개 파드
# Zone B: 1개 파드  
# Zone C: 0개 파드 ← 빈 zone으로 인해 TAR 비활성화

제한사항

구성 방법

1. Service 어노테이션 설정

yaml
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 배포 전략

yaml
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%

비용 절감 효과

bash
# AWS 데이터 전송 비용 예시
# 크로스-AZ: $0.01/GB
# 동일-AZ: $0.00/GB

# 월 1TB 데이터 전송 시
# 기존: $10.24 (크로스-AZ)
# 적용 후: $0 (동일-AZ)
# 절약: 100%

모니터링 및 트러블슈팅

1. 클러스터 Zone 구성 확인

bash
# 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

출력 예시:

bash
   2 ap-northeast-2a
   2 ap-northeast-2b  
   2 ap-northeast-2c
# → 3개 zone, TAR 적용 가능 ✅

2. Zone 정보 종합 확인 스크립트

bash
#!/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 힌트 확인

bash
# EndpointSlice 힌트 확인
kubectl get endpointslices -o yaml | grep -A5 hints

# 특정 서비스의 EndpointSlice 상세 확인
kubectl describe endpointslices -l kubernetes.io/service-name=my-service

2. Service 상태 확인

bash
# Service 이벤트 확인
kubectl describe service my-service

# 힌트 관련 로그 확인
kubectl logs -n kube-system -l component=kube-proxy | grep topology

3. 일반적인 문제 해결

힌트가 생성되지 않는 경우

bash
# Pod 분산 상태 확인
kubectl get pods -o wide --show-labels | grep my-app

# Zone별 Pod 수 확인
kubectl get nodes --show-labels | grep topology.kubernetes.io/zone

불균등 분산 해결

yaml
# PodDisruptionBudget을 통한 안정적 배포
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: my-app-pdb
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: my-app

주의사항 및 실무 권장사항

1. 환경별 TAR 적용 가이드

개발/테스트 환경

yaml
# 비용 우선 → TAR 비활성화 권장
apiVersion: apps/v1
kind: Deployment
spec:
  replicas: 1-2  # 최소 리소스
---
apiVersion: v1
kind: Service  
metadata:
  annotations:
    # TAR 명시적 비활성화 (불필요한 오버헤드 방지)
    service.kubernetes.io/topology-mode: "disabled"

프로덕션 환경

yaml
# 성능 + 비용 절약 → 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 성능 분석

비용 관점

bash
# 시나리오 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 성능 트레이드오프

yaml
# 높은 가용성이 필요한 경우 비활성화 고려
metadata:
  annotations:
    service.kubernetes.io/topology-mode: "disabled"

5. 동적 스케일링 고려

yaml
# 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 수의 배수로 설정

실습 예제

전체 구성 예시

yaml
---
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

검증 스크립트

bash
#!/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 "로그 없음"

성능 측정

벤치마크 테스트

bash
# 성능 측정용 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 도입 결정 플로우차트

bash
1. 클러스터 Zone 수는?
   └─ 1개 Zone → ❌ TAR 불가, 끝
   └─ 2개 Zone → 다음 단계
   └─ 3개+ Zone → 다음 단계

2. 환경 성격은?
   └─ 개발/테스트 → ❌ TAR 불필요 (비용 우선)
   └─ 프로덕션 → 다음 단계

3. 트래픽 특성은?
   └─ 저트래픽 → △ TAR 효과 미미
   └─ 고트래픽 → 다음 단계

4. 파드 확장 가능성?
   └─ 2대 고정 → ❌ TAR 제한적
   └─ 3대+ 가능 → ✅ TAR 도입!

환경별 최종 권장사항

개발/테스트 환경

yaml
# 결론: TAR 적용 불필요
replicas: 1-2
service.kubernetes.io/topology-mode: "disabled"
# 이유: 비용 절약 > 성능 최적화

스테이징 환경

yaml
# 결론: TAR 테스트 목적으로만 적용
replicas: 3-6
service.kubernetes.io/topology-mode: "auto"
# 이유: 프로덕션 환경 사전 검증

프로덕션 환경

yaml
# 결론: 적극적 TAR 도입
replicas: zone_count × 3  # 최적화
service.kubernetes.io/topology-mode: "auto"
# 이유: 성능 + 비용 절약 효과 극대화

핵심 요약

도입하면 좋은 경우

도입하지 말아야 하는 경우

신중히 검토해야 하는 경우

실무 체크리스트

도입 전 확인사항:

도입 후 검증사항:

권장사항

  1. 단계적 도입: 비즈니스 임팩트가 낮은 서비스부터 시작
  2. 충분한 테스트: 스테이징 환경에서 먼저 검증
  3. 지속적 모니터링: 힌트 생성 상태와 효과 측정
  4. 팀 교육: 운영팀 대상 TAR 원리와 트러블슈팅 방법 공유
  5. 문서화: 의사결정 과정과 설정 기준 문서화

Topology Aware Routing은 모든 환경에 적용하는 만능 해결책이 아니라, 적절한 조건에서 큰 효과를 내는 도구입니다.


참고 자료

  1. Kubernetes Official Documentation - Topology Aware Hints
  2. AWS Blog - Exploring the effect of Topology Aware Hints on network traffic in Amazon EKS
  3. Kubernetes Enhancement Proposal - Topology Aware Routing
  4. Amazon EKS User Guide - Topology Aware Hints

도식

100%

끌어서 이동, 두 손가락이나 휠로 확대·축소. 키보드: 화살표 이동, + − 확대·축소, 0 맞춤, Esc 닫기. 같은 내용은 그림 아래 “그림 관계를 글로 읽기”에 있다.