- Published on
로드 밸런서 내부 완전 가이드 2025: L4/L7, IPVS, DSR, ECMP, Maglev — Google/Netflix/Cloudflare의 트래픽 분배 비밀
- Authors

- Name
- Youngju Kim
- @fjvbn20031
들어가며: 트래픽 분배의 진짜 복잡함
단순한 질문
"웹사이트 트래픽이 늘어서 서버 10대로 분산하고 싶어."
답: "로드 밸런서 쓰세요."
다음 질문:
- L4? L7?
- Nginx? HAProxy? Envoy?
- DNS 로드 밸런싱? Anycast?
- Health check는? Session persistence는?
- SSL termination은 어디서?
- DDoS 방어는?
단순한 문제가 아니다. Google, Netflix, Cloudflare 같은 회사들이 전담 팀을 두고 로드 밸런서를 연구하는 이유다.
규모의 문제
트래픽 스케일별 로드 밸런서 요구사항:
| 규모 | 요구사항 |
|---|---|
| 1 Kbps | 아무거나 |
| 1 Mbps | 단일 서버 |
| 1 Gbps | Nginx, HAProxy 충분 |
| 10 Gbps | 커널 우회 (DPDK, XDP) |
| 100 Gbps+ | 분산 LB (Maglev, Katran) |
| 1 Tbps | Anycast + 수십 개 POP |
Cloudflare는 초당 수천만 요청을 처리한다. 이는 단일 서버에서 절대 불가능하다. 완전히 다른 아키텍처가 필요하다.
이 글에서 다룰 것
- L4 vs L7: 근본 차이.
- IPVS: Linux 커널의 LB.
- DSR (Direct Server Return): 하드웨어급 효율.
- ECMP + Consistent Hashing: 분산 LB의 기초.
- Maglev: Google의 소프트웨어 LB.
- HAProxy: L7의 성능왕.
- Envoy: 현대 service mesh의 기반.
- Anycast: 전 세계 트래픽 분산.
- BPF/XDP: 최신 커널 기반 LB.
- 실전 튜닝과 디버깅.
1. OSI 모델과 로드 밸런서 계층
로드 밸런서 계층
┌─────────────────────┐
│ L7 (Application) │ ← HTTP, gRPC, WebSocket
├─────────────────────┤
│ L6 (Presentation) │ ← TLS
├─────────────────────┤
│ L5 (Session) │
├─────────────────────┤
│ L4 (Transport) │ ← TCP, UDP
├─────────────────────┤
│ L3 (Network) │ ← IP
├─────────────────────┤
│ L2 (Data Link) │ ← Ethernet
├─────────────────────┤
│ L1 (Physical) │
└─────────────────────┘
로드 밸런서는 L3, L4, L7 중 어느 층에서 결정하느냐에 따라 구분된다:
- L3: IP 주소 기반. DNS, Anycast.
- L4: IP + Port 기반. IPVS, HAProxy TCP 모드.
- L7: Application 내용 기반. Nginx, Envoy, HAProxy HTTP 모드.
L4 vs L7 핵심 차이
L4 (Transport Layer):
- TCP/UDP 연결 수준에서 분배.
- Payload 안 봄. 빠름.
- Stateful: 연결 table 유지.
- 예:
source_ip:port → backend_ip:port매핑.
L7 (Application Layer):
- HTTP, gRPC 등 애플리케이션 내용 해석.
- URL, header, cookie 기반 라우팅 가능.
- TLS termination 가능.
- 느리지만 유연.
- 예:
/api/users → backend1, /api/orders → backend2.
성능 비교
대략적 수치 (최근 하드웨어):
| 항목 | L4 (IPVS) | L7 (Nginx) |
|---|---|---|
| 처리량 | ~10M pps | ~500K rps |
| 지연 | ~10 μs | ~50 μs |
| CPU/core | ~10 Gbps | ~2 Gbps |
| 메모리 | 낮음 | 중간 |
| 유연성 | 낮음 | 높음 |
L4 + L7 계층 구조
가장 흔한 패턴:
Internet
↓
┌──────────────┐
│ L4 LB (ECMP) │ ← 극도의 처리량
└──────────────┘
↓ ↓ ↓ ↓
┌────┐┌────┐┌────┐┌────┐
│ L7 ││ L7 ││ L7 ││ L7 │ ← HTTP 라우팅, TLS, WAF
└────┘└────┘└────┘└────┘
↓
Backend Services
L4가 먼저 (빠른 분배), L7이 다음 (지능적 라우팅). Google, Facebook 같은 대기업이 쓰는 구조.
2. IPVS: Linux 커널의 L4 LB
IPVS란
IPVS (IP Virtual Server) 는 Linux 커널 모듈로, L4 로드 밸런싱을 구현한다. 1998년부터 개발. 커널 수준이라 극도로 빠르다.
주요 특징
- 커널 모듈: 시스템콜 오버헤드 없음.
- Netfilter 통합: iptables와 공존.
- 수십만 연결: 단일 서버에서.
- TCP, UDP, SCTP 지원.
기본 사용
# ipvsadm 도구로 설정
sudo ipvsadm -A -t 10.0.0.1:80 -s rr # Virtual service, round robin
sudo ipvsadm -a -t 10.0.0.1:80 -r 10.0.1.1:80 -g # 실제 서버 (DSR mode)
sudo ipvsadm -a -t 10.0.0.1:80 -r 10.0.1.2:80 -g
sudo ipvsadm -a -t 10.0.0.1:80 -r 10.0.1.3:80 -g
# 확인
sudo ipvsadm -L -n
세 가지 전달 모드
IPVS는 패킷을 backend로 전달하는 3가지 방식을 지원:
1. NAT (Network Address Translation):
Client → LB: dst=VIP
LB → Backend: dst=backend_ip (NAT)
Backend → LB: src=backend_ip
LB → Client: src=VIP (reverse NAT)
- 장점: 설정 쉬움.
- 단점: LB가 양방향 트래픽 처리. 병목.
2. IP Tunneling (IPIP):
Client → LB: dst=VIP
LB → Backend: IP-in-IP encapsulated
Backend → Client: 직접 (VIP로 src 변조)
- 장점: 응답이 LB 안 거침.
- 단점: Backend 서버가 IPIP 해석 가능해야.
3. Direct Routing (DR) - 일명 DSR:
Client → LB: dst=VIP (MAC: LB)
LB → Backend: 원래 packet 그대로, MAC만 backend로 변경
Backend → Client: 직접 (VIP로 src)
- 장점: 응답 트래픽이 LB 안 거침. 극도의 효율.
- 단점: Backend가 VIP를 loopback에 가져야. Same L2 network.
DSR (Direct Server Return)의 힘
DSR이 왜 대단한가?
일반 LB (요청과 응답 모두 LB 경유):
- 트래픽의 비대칭성: 요청은 작고(~1KB) 응답은 크다(~100KB+).
- LB는 응답까지 처리 → bottleneck.
- 10 Gbps LB가 1 Gbps 요청도 감당 못 할 수 있음.
DSR:
- LB는 요청만 처리.
- 응답은 backend가 직접 client에게.
- LB 대역폭 요구사항 90% 감소.
실전 효과: 100 Gbps 트래픽을 1 Gbps LB로 처리 가능 (요청만 10% = 10 Gbps, 근접한 한계).
Health Check
IPVS 단독으론 health check 없음. Keepalived 같은 도구와 조합:
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
virtual_ipaddress {
10.0.0.1
}
}
virtual_server 10.0.0.1 80 {
delay_loop 10
lb_algo rr
lb_kind DR
real_server 10.0.1.1 80 {
HTTP_GET {
url { path /health status_code 200 }
connect_timeout 3
}
}
}
Keepalived가 주기적으로 health check 후 IPVS rule 갱신.
Scheduling 알고리즘
IPVS가 지원하는 LB 알고리즘:
- rr: Round robin.
- wrr: Weighted round robin.
- lc: Least connections.
- wlc: Weighted least connections.
- sh: Source hashing (같은 client → 같은 backend).
- dh: Destination hashing.
- sed: Shortest expected delay.
- nq: Never queue.
wrr과 wlc가 가장 흔히 쓰인다.
실전 사용
많은 Kubernetes 배포판이 IPVS를 Service의 백엔드로 쓴다:
kube-proxy mode: ipvs
기본 iptables 모드보다 훨씬 빠르며 확장 가능하다 (수만 service에서).
3. HAProxy: L4/L7의 성능왕
탄생
- 2000년: Willy Tarreau가 개발 시작.
- 현재: 인터넷의 핵심 인프라.
- 사용자: GitHub, Stack Overflow, Twitter, Instagram, Reddit...
HAProxy는 단일 이진 파일로 L4와 L7 모두를 제공. 엄청나게 빠르고 안정적.
아키텍처
이벤트 기반: Single-threaded event loop (최근 multi-process/thread):
- epoll/kqueue 기반 비동기 I/O.
- 수십만 동시 연결 가능.
- CPU 효율 극대화.
예시 설정:
frontend http-in
bind *:80
default_backend servers
backend servers
balance roundrobin
option httpchk GET /health
server web1 10.0.0.1:80 check
server web2 10.0.0.2:80 check
server web3 10.0.0.3:80 check
성능 특성
HAProxy의 벤치마크는 놀랍다:
- 2M+ HTTP req/sec 단일 서버.
- 100 Gbps 처리 가능.
- 수백만 동시 TCP 연결.
Nginx가 웹서버 겸 LB라면, HAProxy는 순수 LB에 최적화. 더 빠른 경우가 많다.
Layer 7 라우팅
복잡한 HTTP 라우팅:
frontend http-in
bind *:80
# URL 기반
acl api_request path_beg /api/
acl admin_request path_beg /admin/
# Header 기반
acl mobile_client hdr(User-Agent) -i -m sub Mobile
use_backend api_servers if api_request
use_backend admin_servers if admin_request
use_backend mobile_servers if mobile_client
default_backend web_servers
SSL Termination
frontend https-in
bind *:443 ssl crt /etc/haproxy/cert.pem
default_backend http_servers
TLS 연결을 HAProxy가 종료하고, 내부 통신은 HTTP. CPU 집약적이지만 유연.
Stick Tables
Session persistence를 위한 메커니즘:
backend servers
stick-table type ip size 1m expire 1h
stick on src
server web1 ...
server web2 ...
같은 client IP는 같은 backend로. Session sticky에 유용.
최신 기능: HTTP/3, gRPC
HAProxy는 계속 진화:
- HTTP/3 (QUIC): 최신 프로토콜 지원.
- gRPC: HTTP/2 기반 라우팅.
- Data plane API: 동적 설정.
- Runtime API: 무중단 설정 변경.
단점
- 설정 복잡: 강력하지만 학습 곡선 있음.
- GUI 부족: 상용 버전 있지만 비쌈.
- Service mesh 통합: Envoy보다 약함.
4. Nginx: 웹 서버 + LB
역사
- 2004: 러시아의 Igor Sysoev가 개발.
- C10K 문제: 만 개 동시 연결. Nginx가 해결.
- 현재: 인터넷 웹서버의 1/3.
아키텍처
- Master + Worker 프로세스: 각 worker가 event loop.
- 비동기 I/O: epoll 기반.
- 경량: 메모리 효율 탁월.
Load Balancer로서
upstream backend {
least_conn;
server web1.example.com weight=3;
server web2.example.com;
server web3.example.com;
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_next_upstream error timeout http_500;
}
}
Nginx vs HAProxy
| 항목 | Nginx | HAProxy |
|---|---|---|
| 주 용도 | 웹서버 + LB | 순수 LB |
| L7 HTTP | 강력 | 강력 |
| L4 TCP | 가능 (stream module) | 최적화됨 |
| 성능 | 빠름 | 약간 더 빠름 |
| 설정 | 더 간결 | 더 세밀 |
| 생태계 | 방대 | 중간 |
| Plus (유료) | 동적 설정, GUI | 동적 설정, 분석 |
실전 선택:
- 웹서버 + 간단한 LB: Nginx.
- 순수 LB, 극한 성능: HAProxy.
5. ECMP + Maglev: Google의 답
문제: 단일 LB의 한계
한 대의 HAProxy가 100 Gbps를 처리한다면?
- 10 Tbps가 필요하면? 100대 필요.
- 그 100대를 어떻게 분산?
- 한 대가 죽으면?
해결: ECMP + Consistent Hashing.
ECMP (Equal-Cost Multi-Path Routing)
네트워크 라우터의 기능. 같은 목적지로 여러 경로가 있으면 트래픽을 분산:
Client → Router → [LB1, LB2, LB3, ..., LB100]
ECMP로 분산
ECMP는 패킷의 5-tuple 해시 (src_ip, dst_ip, src_port, dst_port, protocol)로 LB를 선택. 같은 연결의 모든 패킷이 같은 LB로.
ECMP의 함정
문제: LB가 장애로 제거되면? Hash가 바뀌며 모든 연결이 재분배된다:
Before: hash(5-tuple) % 100 = LB_42
After (LB_42 죽음): hash(5-tuple) % 99 = LB_??
거의 모든 기존 연결이 다른 LB로 이동. 기존 연결 상태가 새 LB에 없어 모두 끊김.
Maglev: Google의 해결책
2016년 Google이 발표한 Maglev 는 이 문제를 해결한다. 핵심:
Maglev 해싱: Consistent hashing의 개선판.
- Lookup table 기반: 미리 계산된 테이블.
- 균등 분포: 거의 완벽한 load 분산.
- 최소 변경: 노드 제거 시 소수의 연결만 재배치.
- O(1) 조회: 매우 빠름.
Maglev Hash 테이블 구축
1. 각 backend 서버에 permutation (순열) 생성.
2. 큰 테이블 (예: 65537 크기, 소수).
3. Round-robin으로 각 서버가 테이블 슬롯을 채움.
4. 최종: 각 슬롯에 배정된 서버 목록.
Lookup: hash(5-tuple) % 65537 → 서버
서버가 죽으면 그 서버의 슬롯만 재분배. 전체 재구성 아님.
Maglev 클러스터
Google의 Maglev는 수십~수백 대로 구성된다:
Router (ECMP) → Maglev Cluster (L4)
↓
Backend Servers
ECMP가 Maglev 클러스터에 분산. Maglev는 개별 연결을 backend로 라우팅. 합쳐서 수 Tbps 처리 가능.
Maglev의 공개 구현
Katran (Facebook): XDP/eBPF 기반 L4 LB. Maglev 아이디어 적용. Envoy: L7 라우팅에 Maglev 해시 옵션 제공. Cilium: Kubernetes에서 Maglev 스타일 LB.
6. XDP / eBPF: 커널의 새 힘
전통 커널 LB의 한계
IPVS는 빠르지만 여전히 커널 네트워크 스택을 거친다:
- Netfilter hook.
- Socket buffer (sk_buff).
- Routing table lookup.
오버헤드가 있다. 10-40 Gbps가 실전 한계.
XDP (eXpress Data Path)
Linux 4.8+에서 도입. NIC 드라이버 수준에서 패킷 처리:
NIC → NIC Driver → XDP program → (decision)
├── XDP_PASS (커널 스택)
├── XDP_DROP (버림)
├── XDP_TX (되돌려 보냄)
└── XDP_REDIRECT (다른 곳)
XDP program은 eBPF (extended Berkeley Packet Filter)로 작성. 커널 스택보다 먼저 실행됨.
성능
XDP의 벤치마크:
- DDoS 차단: 200 Gbps급.
- Load balancing: 100 Gbps+ 단일 NIC.
- CPU 효율: IPVS 대비 10배.
Katran: Facebook의 XDP LB
Facebook의 Katran은 XDP 기반 오픈소스 L4 LB:
- Maglev hashing 구현.
- 수십 Gbps 단일 서버에서.
- DDoS 방어 내장.
Facebook 전체 트래픽의 상당 부분이 Katran 위에서 돌아간다.
Cilium: Kubernetes의 새 표준
Cilium은 eBPF 기반 CNI + LB:
- Kubernetes Service를 eBPF로 구현.
- Network policy.
- Service mesh (Envoy 대체 가능).
- kube-proxy를 완전히 대체 가능.
Cilium을 쓰면 IPVS보다 10배 빠르고, 관찰성이 크게 향상된다. 2024년 이후 CNCF graduated.
7. Envoy: 현대 L7의 표준
탄생
- 2016: Lyft가 내부 service mesh용으로 개발.
- 오픈소스: 즉시 큰 호응.
- CNCF graduated: 최상위 프로젝트.
왜 Envoy인가
기존 L7 LB (Nginx, HAProxy)의 한계:
- 동적 설정 약함: 재로드 필요.
- 관찰성 제한적: 메트릭, 트레이싱 약함.
- Service mesh 비친화적: 정적 설정.
Envoy는 이를 해결:
- Dynamic configuration (xDS): 런타임에 설정 변경.
- 강력한 관찰성: 상세한 메트릭, 트레이싱, 로깅.
- HTTP/2, gRPC, HTTP/3 네이티브.
- Sidecar 패턴: 각 서비스 옆에 배치.
xDS API
Envoy의 핵심 혁신. xDS (x Discovery Service) 는 동적 설정 API:
- LDS: Listener Discovery Service.
- RDS: Route Discovery Service.
- CDS: Cluster Discovery Service.
- EDS: Endpoint Discovery Service.
Control plane (예: Istio)이 xDS로 설정을 push하면 Envoy가 무중단으로 적용.
기본 설정
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 80
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: service_backend }
http_filters:
- name: envoy.filters.http.router
clusters:
- name: service_backend
connect_timeout: 5s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: service_backend
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: backend.example.com
port_value: 80
복잡하지만 극도로 강력.
LB Policies
Envoy는 다양한 LB 알고리즘 지원:
- ROUND_ROBIN: 단순.
- LEAST_REQUEST: 최소 연결.
- RING_HASH: 일관된 해시.
- MAGLEV: Google Maglev 스타일.
- RANDOM: 무작위.
Outlier Detection
Envoy는 자동 이상 감지:
outlier_detection:
consecutive_5xx: 5
interval: 10s
base_ejection_time: 30s
max_ejection_percent: 50
5번 연속 5xx → 30초간 해당 backend 제외. 자동 ejection.
Circuit Breaker
circuit_breakers:
thresholds:
- max_connections: 1000
max_pending_requests: 100
max_requests: 1000
max_retries: 3
과부하 시 새 요청 거부. 연쇄 실패 방지.
Service Mesh
Envoy의 주 용도: service mesh. Istio, Linkerd 2, Consul Connect가 모두 Envoy를 데이터 플레인으로 사용.
- 각 마이크로서비스 옆에 Envoy sidecar.
- 모든 트래픽이 sidecar 통과.
- 자동 mTLS, 관찰성, 정책.
8. DNS 기반 로드 밸런싱
가장 단순한 LB
DNS가 여러 IP를 반환:
$ dig example.com
;; ANSWER SECTION:
example.com. 60 IN A 10.0.0.1
example.com. 60 IN A 10.0.0.2
example.com. 60 IN A 10.0.0.3
Client가 무작위로 하나를 선택. 많은 클라이언트 → 자동 분산.
Round-Robin DNS
DNS 서버가 요청마다 순서를 바꿔서 반환. 자동 분산.
장점
- 매우 단순.
- 무료.
- 글로벌 가능 (GeoDNS).
단점
- Caching: DNS TTL 동안 캐싱. 서버가 죽어도 계속 그 IP 사용.
- 불균등: 캐시 때문에 일부 클라이언트가 특정 IP에 쏠림.
- Health check 없음: DNS는 서버 상태 모름.
- 세밀한 제어 불가.
GeoDNS (Geographic DNS)
Cloudflare, Route 53 같은 서비스가 제공:
- Client의 위치 감지.
- 가장 가까운 서버의 IP 반환.
- 글로벌 분산에 효과적.
한계: 여전히 DNS의 문제들 (caching, no health check). 그래서 L4/L7 LB와 조합해서 사용.
9. Anycast: 하나의 IP, 여러 장소
Anycast란
같은 IP를 여러 장소에서 알린다. BGP 라우팅이 가장 가까운 곳으로 라우팅:
IP: 1.1.1.1 (Cloudflare DNS)
Advertised from:
- US East (Virginia)
- US West (California)
- Europe (London)
- Asia (Tokyo)
- 전 세계 100+ POP
Client in Japan → Tokyo POP
Client in UK → London POP
효과:
- 짧은 지연: 항상 가까운 서버.
- 분산: 자동.
- 내결함성: 한 POP 다운 → BGP가 다른 곳으로.
사용 사례
- DNS: Cloudflare 1.1.1.1, Google 8.8.8.8.
- CDN: Akamai, Cloudflare 전반.
- DDoS 방어: 공격이 여러 POP에 분산.
한계
- TCP 연결 문제: 중간에 경로가 바뀌면 연결 끊김.
- BGP 지식 필요: 설정 복잡.
- 비용: BGP peering 필요.
그래서 UDP 기반 서비스 (DNS, QUIC) 가 Anycast에 더 적합.
10. Cloudflare / Netflix / Google의 아키텍처
Cloudflare
전 세계 300+ POP. 각 POP가:
- Anycast BGP: 가장 가까운 사용자에게 라우팅.
- Katran (XDP) 또는 자체 LB: L4.
- Nginx: L7 (현재는 자체 Rust 기반 Pingora로 교체 중).
- Workers: edge computing.
매일 25+ TB/s 트래픽 처리. 모든 POP가 전 세계 트래픽을 감당.
Netflix
CDN 중심:
- Open Connect Appliance (OCA): ISP 내부에 배치.
- DNS + Anycast: 가장 가까운 OCA 선택.
- FreeBSD + sendfile + KTLS: 앞서 설명한 zero-copy.
- 단일 서버 200 Gbps 달성.
Netflix 트래픽이 전체 인터넷의 상당 비율을 차지할 때도 있다.
여러 레이어:
- Frontend: Maglev 클러스터.
- GFE (Google Front End): L7 LB + TLS termination.
- Backend: 각 서비스의 fleet.
Google Cloud Load Balancer도 내부적으로 Maglev 사용. 글로벌 LB 제공.
11. 실전 구성 가이드
시나리오 1: 소규모 웹사이트
트래픽: < 1 Gbps, < 10K req/s. 추천: Nginx 단독.
upstream app {
server app1:8080;
server app2:8080;
}
server {
listen 80;
location / {
proxy_pass http://app;
}
}
단순. 저렴. 충분.
시나리오 2: 중규모 서비스
트래픽: 110 Gbps, 10K100K req/s.
추천: HAProxy + Nginx (또는 HAProxy 단독).
Internet → HAProxy (SSL termination) → Nginx (static) + App servers
시나리오 3: Kubernetes 클러스터
추천: Cilium 또는 MetalLB + Ingress (Nginx, Traefik, Envoy).
External LB → MetalLB (L2/BGP) → Ingress Controller → Service
Cloud (AWS EKS, GCP GKE)라면 Cloud LB + Ingress.
시나리오 4: 대규모 글로벌 서비스
트래픽: 100 Gbps+, 전 세계. 추천: Anycast + ECMP + Maglev + L7 mesh.
Anycast DNS → BGP Anycast → L4 LB (Maglev) → L7 (Envoy) → Services
Cloudflare, Google Cloud Load Balancer 같은 관리형 서비스 고려.
시나리오 5: 고성능 전문가 환경
트래픽: DDoS 방어, 수백 Gbps. 추천: Katran + XDP + eBPF.
직접 구축하거나 Cloudflare Magic Transit 같은 서비스 사용.
12. 실전 문제와 해결
문제 1: Session 유지 안 됨
증상: 사용자가 로그인했는데 다음 요청에서 다른 서버로 가 로그아웃됨.
원인: LB가 round-robin으로 분산. 세션이 특정 서버 메모리에만 있음.
해결:
- Sticky session: 쿠키 또는 source IP로.
- Shared session store: Redis, Memcached.
- JWT: 서버 상태 없는 인증.
문제 2: Thundering Herd
증상: 한 서버가 재시작되면 다른 서버들이 한꺼번에 많은 요청 받음.
원인: Health check 복구 시 즉시 100% 트래픽.
해결:
- Slow start: 복구 후 점진적 트래픽 증가.
- Warm-up: 사전 예열.
문제 3: TLS 재협상 과부하
증상: HTTPS 트래픽 CPU 사용률 급증.
원인: 매 연결마다 새 TLS 핸드셰이크.
해결:
- Session resumption: TLS ticket.
- HTTP/2: 하나의 연결로 여러 요청.
- SSL offloading: LB에서 TLS 종료.
- HW acceleration: AES-NI, QAT.
문제 4: Long-lived connections
증상: WebSocket, gRPC 장기 연결이 재배포 시 문제.
원인: 연결이 오래 유지되어 새 인스턴스로 안 옮겨감.
해결:
- Graceful drain: 주기적으로 연결 종료 요청.
- Connection limit: 시간 제한.
- 재연결 로직: 클라이언트가 재시도.
문제 5: Client IP 잃어버림
증상: Backend 로그에 LB의 IP만 보임.
원인: LB가 NAT 모드로 동작.
해결:
- X-Forwarded-For header: L7 LB가 client IP 추가.
- PROXY protocol: L4에서도 IP 전달.
- DSR mode: LB가 NAT 안 함.
문제 6: Health check 오탐
증상: 실제로는 건강한데 LB가 unhealthy로 판단.
원인: Health check endpoint 설정 오류.
해결:
- 적절한 경로:
/health만들기. - 충분한 timeout: DB 체크 포함 가능하게.
- Threshold: 3번 연속 실패 후 unhealthy.
- Shallow vs deep check: 경로에 따라.
퀴즈로 복습하기
Q1. L4와 L7 로드 밸런서의 근본적 차이와 성능/유연성 트레이드오프는?
A.
L4 (Transport Layer):
- TCP/UDP 연결 수준에서 결정.
- 패킷의 header만 봄 (IP, Port).
- Payload 해석 안 함 → 매우 빠름.
- 결정 후엔 해당 연결의 모든 패킷을 투명하게 전달.
L7 (Application Layer):
- HTTP, gRPC 등 애플리케이션 프로토콜 해석.
- URL, header, cookie, method 모두 접근.
- TLS termination, HTTP 버전 변환 가능.
- 지능적 라우팅 가능.
성능 차이 (대략):
| 항목 | L4 | L7 |
|---|---|---|
| 처리량 | ~10M pps | ~500K rps |
| 지연 | ~10 μs | ~50 μs |
| CPU 10-Gbps당 | 1 core | 5 cores |
| TLS 처리 | 불가 (통과만) | O |
| 복잡한 라우팅 | 불가 | O |
유연성 차이:
L4가 할 수 없는 것들:
- URL 기반 라우팅 (
/api/v1vs/api/v2). - 쿠키 기반 sticky session.
- HTTP header 수정 (X-Forwarded-For).
- TLS termination.
- 압축, 캐싱, WAF.
- gRPC 개별 메시지 라우팅.
L4가 유리한 것들:
- 순수 속도: 10배 빠름.
- 비HTTP 프로토콜: SMTP, SSH, DB.
- DSR 가능: 응답이 LB 안 거침 → 대역폭 절약.
- 투명성: 패킷 건드리지 않음.
실전에서의 조합:
대규모 시스템은 거의 항상 둘 다 쓴다:
Internet
↓
L4 LB (Maglev, IPVS) — 수십 Gbps 처리, ECMP 스프레드
↓ ↓ ↓
L7 LB (Envoy, HAProxy) — HTTP 라우팅, TLS, 관찰성
↓
Backend Services
이유: L4만 쓰면 라우팅 제어 부족, L7만 쓰면 성능 한계.
언제 어느 것만 쓰는가:
- L4 단독: DB LB, 저수준 프록시, 극한 성능, TCP 투명성.
- L7 단독: 일반 웹사이트, API gateway, 소규모~중규모.
- 둘 다: 대규모, 글로벌, service mesh.
결정 트리:
HTTP/gRPC 트래픽? → L7
TCP만 되고 payload 안 봐? → L4
둘 다? → L4 + L7 체인
역사적 관점:
- 90년대: LB = L4 (Cisco LocalDirector, F5 BIG-IP).
- 2000년대: L7이 일반화 (Nginx, HAProxy).
- 2010년대: L4 + L7 체인이 표준 (Google, Facebook).
- 2020년대: eBPF/XDP L4 + Envoy L7 (Cloudflare, Cilium).
각 레이어가 자기 영역에서 최적화되며 공존한다. "L7이 L4를 대체"가 아니라 "각자의 역할" 이다.
교훈: 기술 스택은 하나의 도구가 모든 것을 하려 하지 않는다. 계층화가 복잡성을 관리 가능하게 만든다. 로드 밸런싱도 마찬가지다.
Q2. DSR (Direct Server Return)이 어떻게 "응답 트래픽을 우회"해서 LB 부하를 줄이는가?
A.
전통 LB (NAT 모드)의 경로:
Client (1 KB request)
↓
LB (NAT): src=client, dst=VIP → src=LB, dst=backend
↓
Backend
↓ (200 KB response)
LB (NAT): src=backend, dst=LB → src=VIP, dst=client
↓
Client
문제: 요청 1 KB + 응답 200 KB = 201 KB가 LB를 두 번 통과 (in + out). 특히 응답이 큰 웹 트래픽(HTML, 이미지, 동영상)에서 LB가 응답 대역폭 때문에 병목.
DSR 모드의 경로:
Client (1 KB request)
↓
LB: dst=VIP에 도착. NAT 안 함. 원래 패킷 그대로, MAC만 backend로 변경.
↓
Backend (VIP를 loopback에 가짐)
↓ (200 KB response 직접)
Client
LB는 요청만 처리. 응답은 backend가 client에게 직접.
어떻게 가능한가:
- VIP를 backend의 loopback에 설정:
ip addr add 10.0.0.1/32 dev lo
Backend가 "나는 VIP야"라고 주장.
- ARP 억제:
echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
Backend가 VIP를 ARP로 광고하지 않음 (LB만 광고).
-
LB가 MAC만 변경: IP는 그대로 VIP, dst MAC만 backend로.
-
Backend가 패킷 수신: VIP가 내 loopback이니 수락.
-
응답 전송: source IP = VIP (loopback에서). client에게 직접.
효과:
대역폭 절약:
- 일반 웹 트래픽: 요청/응답 비율 1:100 이상.
- LB는 1%만 처리. 나머지 99%는 backend에서 직접.
- 10 Gbps LB가 1 Tbps 트래픽 처리 가능 (이론적).
지연 감소:
- 응답이 LB 거치지 않음 → 한 hop 감소.
- 수 ms 단축 가능.
LB CPU 절약:
- 요청만 처리 → CPU 여유.
제약:
- Same L2 network 필요: LB와 backend가 같은 L2 (VLAN).
- Layer 2 ARP 트릭: 네트워크 설정 복잡.
- L4 only: L7 처리 불가 (LB가 응답 안 봄).
- Troubleshooting 어려움: 트래픽이 한쪽만 LB 경유.
- Stateful 서비스 제약: LB가 응답 못 봄 → 연결 추적 제한.
사용처:
- 고대역폭 서빙: 동영상, 이미지, 파일 다운로드.
- L4 LB 뒤의 백엔드: IPVS DR 모드.
- CDN: 하드웨어 LB.
IPIP Tunneling 모드:
L2 제약이 싫으면 IPIP tunneling:
LB: packet을 IP-in-IP로 encapsulate (outer: backend, inner: 원래)
Backend: decapsulate, 원래 packet 처리
Backend: response 직접 client에게
L3 network도 통과 가능. 약간의 오버헤드 (encap/decap).
최신 대안: Maglev + XDP:
Google Maglev와 Facebook Katran 같은 현대 L4 LB는 DSR을 기본으로 쓴다. 이 덕분에 수 Tbps급 트래픽을 소수의 서버로 처리한다.
실전 수치:
- 일반 LB: 10 Gbps NIC → 10 Gbps 트래픽 한계.
- DSR LB: 10 Gbps NIC → 100 Gbps 트래픽 처리 가능 (요청만).
100 Gbps 한 서버 = 10배 효율. CAPEX와 OPEX 큰 절감.
교훈:
DSR은 네트워크 프로토콜의 물리적 특성을 영리하게 활용한다. "요청과 응답의 비대칭성"이라는 현실을 무시하지 않고 받아들여 설계를 최적화한다.
이는 일반 LB 생각의 확장이다: "LB는 요청과 응답 모두를 다뤄야 한다"는 가정을 버리면 훨씬 더 효율적인 구조가 나온다. 엔지니어링의 기본 가정을 의심하는 것의 가치다.
Q3. Maglev hashing이 기본 consistent hashing보다 나은 이유는?
A.
배경: Consistent Hashing의 기본
기본 consistent hashing은 노드와 키를 원형 해시 공간에 배치하고, 각 키를 "다음 노드"로 할당. 노드가 추가/제거되면 일부 키만 재배치.
장점:
- 최소 재배치: N개 노드 → N+1개 변경 시 1/(N+1)의 키만 이동.
- 분산 시스템 친화적.
단점:
- 불균등 분포: 해시 공간의 랜덤 배치 때문에 일부 노드가 많은 키를, 일부는 적은 키를 가짐.
- Virtual nodes 필요: 균등성 위해 각 노드를 수백 개의 가상 노드로 표현 → 메모리, 복잡도.
- Lookup O(log N): binary search of ring.
Maglev Hashing의 아이디어:
Google의 2016년 논문은 LB 용도에 최적화된 새 해싱을 제안:
- Permutation table: 각 backend마다 fixed-size 테이블의 permutation 순서를 생성.
- Lookup table (큰 소수, 예: 65537): round-robin으로 각 backend가 자기 선호 슬롯을 채움.
- 모든 슬롯이 채워질 때까지 반복.
결과:
- 완벽한 균등 분포: 모든 slot이 정확히 균등하게.
- O(1) lookup:
hash(5-tuple) % 65537→ 즉시 slot, slot → backend. - 최소 변경: 노드 추가/제거 시 매우 적은 slot 변경.
구체 비교:
Consistent hashing (vnode 없이):
- 10 노드, 100만 키.
- 분포: 5만 ~ 15만 키 / 노드 (3배 차이).
Consistent hashing (100 vnode/노드):
- 분포: 9만 ~ 11만 (10% 차이).
- 메모리: 노드당 100 entry.
Maglev (65537 slot):
- 분포: 약 9985 ~ 10015 / 10000 (1% 미만 차이).
- 메모리: 65537 slot × 노드 ID (~8 bytes) = ~500KB for 10 nodes.
노드 제거 시:
Consistent hashing: 제거된 노드의 키만 이동. 나머지는 그대로. 약 1/N.
Maglev: 이론적으로 1/N에 가깝게. 실측: 매우 균등.
구현 복잡도:
Consistent hashing (vnode):
class ConsistentHash:
def __init__(self, nodes, vnodes=100):
self.ring = SortedDict()
for node in nodes:
for i in range(vnodes):
h = hash(f"{node}-{i}")
self.ring[h] = node
def get(self, key):
h = hash(key)
idx = self.ring.bisect_right(h) % len(self.ring)
return self.ring.peekitem(idx)[1]
Maglev:
def build_maglev(nodes, table_size=65537):
perms = [generate_permutation(node, table_size) for node in nodes]
table = [None] * table_size
next_idx = [0] * len(nodes)
filled = 0
while filled < table_size:
for i, node in enumerate(nodes):
while table[perms[i][next_idx[i]]] is not None:
next_idx[i] += 1
table[perms[i][next_idx[i]]] = node
next_idx[i] += 1
filled += 1
if filled == table_size:
break
return table
def lookup(table, key):
return table[hash(key) % len(table)]
Maglev의 구현이 더 간결하다.
실전 차이:
Google L4 LB인 Maglev는 수백만 연결을 처리해야 한다. 각 패킷마다 lookup. 성능이 극도로 중요.
- Consistent hashing: 각 lookup에 log(N) binary search → cache miss 가능.
- Maglev: 단순 array indexing → cache-friendly, CPU pipeline 최적.
Cloudflare 측정: Maglev가 consistent hashing보다 20-30% 빠름 단일 node 처리량.
분포의 실제 중요성:
"불균등이 10% vs 1%"는 실전에서 왜 중요한가?
10% 불균등 = 어떤 backend가 10% 더 많이 받음. 그 backend의 CPU/memory가 부족해지면 전체 서비스 성능 저하. Hot spot 발생.
1% 불균등 = 거의 완벽한 균형. 모든 backend가 같은 수준으로 활용됨. 용량 예측 정확.
구현체들:
- Google Maglev: 원본, 2016.
- Envoy:
MAGLEVLB policy. - Facebook Katran: XDP 기반 구현.
- Cilium: Kubernetes 내.
- Linkerd 2: Service mesh.
대안은?
Rendezvous hashing (HRW): 또 다른 선택. 각 key에 대해 모든 node의 hash를 계산하고 최대값의 node 선택.
- 장점: 간단, 균등 분포.
- 단점: O(N) lookup (Maglev는 O(1)).
Rendezvous는 작은 N에 좋지만 Maglev가 큰 LB fleet에 더 적합.
결론:
Maglev hashing은 현대 대규모 L4 LB의 표준이다:
- 균등 분포 (1% 미만 variance).
- O(1) lookup (cache-friendly).
- 최소 재배치 (노드 변경 시).
- 간단한 구현.
기본 consistent hashing의 모든 약점을 해결하면서 본질적 이점을 유지한다. 엔지니어링 관점에서 거의 이상적인 해결책이다.
이는 "더 나은 알고리즘이 반드시 더 복잡하지 않다"는 교훈을 준다. Maglev는 consistent hashing보다 더 간단하고 더 좋다. 이런 경우가 드물지만 발견되면 큰 도약이 된다.
Q4. XDP/eBPF 기반 LB가 IPVS보다 어떻게 더 빠른가?
A.
네트워크 패킷의 커널 여정:
일반 Linux 네트워크 스택에서 패킷이 처리되는 과정:
NIC가 패킷 받음
↓
DMA로 메모리(sk_buff 할당)
↓
Interrupt 발생 → NAPI polling
↓
Driver가 sk_buff 초기화
↓
Netfilter PREROUTING hook (iptables, nftables)
↓
Routing decision (라우팅 테이블)
↓
Netfilter INPUT/FORWARD hook
↓
(L4 LB: IPVS가 여기서 개입)
↓
Routing
↓
Netfilter POSTROUTING hook
↓
Driver → NIC transmit
각 단계의 비용:
- sk_buff 할당: ~200 cycles.
- Netfilter hooks: 수백 cycles (rule 수에 따라).
- Routing lookup: 수십 cycles.
- Connection tracking: 수백 cycles.
단일 패킷 처리에 수천 cycles. 10 Gbps 라인레이트 (~15M pps)는 이미 한계.
XDP (eXpress Data Path)의 아이디어:
NIC driver 수준에서 패킷 처리. 커널 스택을 완전히 우회:
NIC가 패킷 받음
↓
DMA로 메모리
↓
Driver가 RX ring buffer에서 raw packet
↓
★ XDP program 실행 (eBPF) ★
↓
결정:
- XDP_DROP: 즉시 버림 (DDoS 방어에 최적)
- XDP_PASS: 일반 스택으로 (보통 경로)
- XDP_TX: 같은 NIC으로 되돌려 보냄
- XDP_REDIRECT: 다른 NIC 또는 AF_XDP 소켓
핵심: sk_buff 할당 없음. 일반 네트워크 스택 거치지 않음. 거의 hardware 속도.
eBPF란:
extended Berkeley Packet Filter. 원래는 tcpdump의 필터링용. 이제는 범용:
- Verifier: 커널이 eBPF 코드를 안전성 검증 (무한 루프, 메모리 접근 체크).
- JIT: eBPF 바이트코드를 네이티브로 컴파일.
- Map: 커널-사용자 공간 공유 자료구조.
- Sandboxed: 커널 크래시 불가.
XDP는 eBPF의 한 응용.
XDP 기반 LB의 성능:
Katran (Facebook) 벤치마크:
- 단일 NIC: 40 Gbps 라인레이트 처리.
- 단일 CPU 코어: 10+ Mpps.
- IPVS 대비: 5-10배 빠름.
- DPDK 대비: 비슷하거나 약간 느림 (XDP는 커널 내, DPDK는 사용자 공간).
왜 이렇게 빠른가:
- sk_buff 없음: 가장 큰 오버헤드 제거.
- 조기 drop: DDoS 패킷을 매우 일찍 버림.
- Bulk processing: 여러 패킷을 한 번에.
- JIT compiled: 네이티브 속도.
- No context switch: 커널 내부.
- Cache-friendly: 작은 코드, 뜨거운 경로.
XDP 예시 코드:
SEC("xdp_lb")
int xdp_load_balance(struct xdp_md *ctx) {
void *data_end = (void*)(long)ctx->data_end;
void *data = (void*)(long)ctx->data;
struct ethhdr *eth = data;
if (eth + 1 > data_end)
return XDP_PASS;
struct iphdr *ip = (void*)(eth + 1);
if (ip + 1 > data_end)
return XDP_PASS;
// 간단한 해시 기반 LB
__u32 backend_idx = ip->saddr % NR_BACKENDS;
struct backend_info *backend = bpf_map_lookup_elem(&backends, &backend_idx);
if (!backend)
return XDP_DROP;
// DSR: dst MAC을 backend로 변경
__builtin_memcpy(eth->h_dest, backend->mac, ETH_ALEN);
return XDP_TX; // 같은 NIC으로 전송
}
단순한 해시 기반 LB를 수십 Mpps 속도로 실행.
IPVS와의 비교:
| 항목 | IPVS | XDP |
|---|---|---|
| 위치 | Netfilter hook | NIC driver |
| sk_buff 할당 | 있음 | 없음 |
| 커널 스택 | 거침 | 우회 |
| 성능 | 10 Gbps | 100 Gbps |
| 프로그래밍 | 고정 기능 | eBPF 유연 |
| 학습 곡선 | 쉬움 | 어려움 |
| 디버깅 | ipvsadm | bpftool, 복잡 |
XDP의 제약:
- 복잡성: eBPF 프로그래밍 어려움. Verifier 제약.
- 드라이버 지원: 모든 NIC이 native XDP 지원 안 함.
- 기능 제한: 복잡한 stateful 처리 어려움.
- 디버깅: 문제 생기면 추적 힘듦.
- 커널 버전: 최신 기능은 새 커널 필요.
실전 사용:
- Facebook Katran: 전체 edge traffic의 L4 LB.
- Cloudflare: DDoS 방어, L4 LB.
- Cilium: Kubernetes CNI + LB.
- Google Andromeda: 일부 component.
DPDK와의 차이:
DPDK (Data Plane Development Kit):
- Intel의 사용자 공간 네트워킹 프레임워크.
- NIC을 커널에서 분리.
- Polling 기반 (인터럽트 없음).
- 성능 더 높을 수 있음.
- 단점: 커널 네트워킹 완전 포기. 복잡한 통합.
XDP vs DPDK:
- XDP: 커널 내, 일반 네트워킹과 공존. 덜 극단적.
- DPDK: 사용자 공간, 전용 하드웨어. 극단적 성능.
XDP는 "80%의 성능을 20%의 복잡도로"의 접근. 대부분 경우 충분.
미래:
XDP/eBPF는 Linux 네트워킹의 미래로 여겨진다:
- Cilium: Kubernetes의 사실상 표준 CNI (Cloudflare, Google Cloud 등).
- bpfilter: iptables를 eBPF로 대체 계획.
- Tetragon: 보안 관찰.
- Tracing: bcc, bpftrace.
앞으로 10년간 네트워크 성능의 한계는 XDP/eBPF가 결정할 것이다.
결론:
XDP는 Linux 네트워크의 근본 재설계다. "커널 스택을 개선"하는 대신 "커널 스택을 우회"하는 과감한 선택. 결과는 10배 이상의 성능 향상.
IPVS가 "빠른 커널 LB"였다면, XDP는 "하드웨어급 소프트웨어 LB"다. 둘 다 Linux의 강력함을 보여주지만 XDP가 현재의 최전선이다.
교훈: 성능 최적화의 극한은 종종 더 빠르게 하는 것이 아니라 하지 않는 것이다. XDP는 "sk_buff를 할당 안 함", "커널 스택을 거치지 않음"이라는 생략으로 도약을 달성했다. 엔지니어링은 때때로 뺄셈에서 답을 찾는다.
Q5. Envoy의 xDS API가 service mesh를 가능하게 한 이유는?
A.
기존 L7 LB의 한계:
Nginx, HAProxy, Apache 같은 전통 L7 LB는 정적 설정 파일 기반:
upstream backend {
server 10.0.0.1:80;
server 10.0.0.2:80;
}
설정 변경 프로세스:
- 설정 파일 수정.
nginx -s reload또는 재시작.- 새 연결부터 새 설정 적용.
문제:
- 지연: reload까지 시간 필요 (수십 ms~수 초).
- 연결 단절: 재시작 시 기존 연결 영향.
- 분산 동기화: 여러 LB에 설정 배포 복잡.
- 규모 제한: 수백 개 service의 동적 변경 어려움.
- 관찰성 부족: 메트릭 수집 제한.
Envoy의 접근: xDS (x Discovery Service)
Envoy는 설정을 외부 API에서 동적으로 받아온다. "x"는 여러 discovery service의 집합:
- LDS (Listener Discovery): 수신할 포트와 필터.
- RDS (Route Discovery): HTTP 라우팅 규칙.
- CDS (Cluster Discovery): 백엔드 클러스터 정의.
- EDS (Endpoint Discovery): 각 클러스터의 인스턴스.
- SDS (Secret Discovery): TLS 인증서, 비밀.
작동 방식:
Control Plane (예: Istio Pilot)
↑ gRPC (xDS API)
↓
┌──────────────┐
│ Envoy Proxy │
└──────────────┘
- Envoy 시작 시 bootstrap 설정만 (Control Plane 주소).
- Control Plane에 gRPC stream 연결.
- Control Plane이 현재 설정을 push.
- 변경이 있으면 즉시 새 설정 push.
- Envoy는 무중단으로 적용.
왜 이게 혁명적인가:
1. 동적 리로드 없이 설정 변경:
- Control Plane이 "route /api/v2 → new_service" 보냄.
- Envoy가 다음 요청부터 즉시 적용.
- 연결 끊김 없음.
2. 수천 인스턴스 동시 업데이트:
- Control Plane이 한 번의 push로 수천 Envoy 모두 업데이트.
- 일관성 보장.
- 동기화 문제 없음.
3. 관찰성 통합:
- Envoy가 모든 요청에 대한 풍부한 메트릭 생성.
- Control Plane이 수집.
- 실시간 대시보드.
4. 정책의 중앙 관리:
- Retry, circuit breaker, rate limit 등 정책을 중앙에서.
- 코드 배포 없이 정책 변경.
5. 프로그래밍 가능:
- Control Plane이 로직을 담음.
- 예: "오전 9시엔 요청의 10%를 새 버전으로 카나리".
- 기존 LB로는 불가능.
Service Mesh의 탄생:
Envoy + xDS가 service mesh 개념을 실용화했다:
마이크로서비스 아키텍처:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Service A│────→│ Service B│────→│ Service C│
└──────────┘ └──────────┘ └──────────┘
Service Mesh (각 서비스 옆에 Envoy sidecar):
┌──────────┐ ┌──────────┐ ┌──────────┐
│ A + Envoy│────→│ B + Envoy│────→│ C + Envoy│
└──────────┘ └──────────┘ └──────────┘
Control Plane (Istio/Linkerd)
모든 서비스 간 통신이 Envoy를 통해. Envoy가 제공:
- 자동 mTLS: 서비스 간 암호화.
- Retry: 실패 시 자동 재시도.
- Circuit breaker: 과부하 보호.
- Rate limiting: DoS 방어.
- Canary deployment: 점진적 배포.
- A/B testing: 트래픽 분할.
- Chaos engineering: 장애 주입 테스트.
- Distributed tracing: 요청 추적.
- Observability: 메트릭, 로깅.
이 모든 것이 애플리케이션 코드 수정 없이 제공된다.
Istio의 등장:
Istio (Google, IBM, Lyft)는 Envoy를 데이터 플레인으로, Pilot을 control plane으로 사용한다:
Istio Control Plane:
├── Pilot: 설정 xDS API 제공
├── Citadel: 인증서 관리
├── Galley: 설정 검증
└── Mixer: 정책 적용 (deprecated)
Data Plane:
└── Envoy sidecar (각 pod마다)
Kubernetes와 긴밀히 통합. kubectl apply -f virtual-service.yaml로 라우팅 규칙 배포.
경쟁자들:
- Linkerd: 경량화된 service mesh. 자체 Rust 프록시.
- Consul Connect: HashiCorp, Envoy 기반.
- AWS App Mesh: Envoy 기반.
- Kuma: Envoy 기반.
거의 모든 현대 service mesh가 Envoy + xDS 패턴을 따른다.
xDS의 확장:
xDS는 이제 Envoy 외에도 사용된다:
- gRPC-LB: gRPC 클라이언트가 xDS 구독.
- Cilium: CNI가 xDS 지원.
- Istio Ambient Mode: sidecar-less mesh도 xDS.
"Envoy-like" API의 사실상 표준이 되어 가고 있다.
교훈:
Envoy의 xDS는 단순한 API가 아닌 패러다임 전환이다. "설정은 파일"에서 "설정은 API"로, "정적"에서 "동적"으로, "개별 업데이트"에서 "중앙 관리"로.
이 전환이 가능했던 이유:
- gRPC streaming의 성숙: 양방향 실시간 통신.
- Protobuf의 type safety: 잘 정의된 스키마.
- Kubernetes의 declarative 모델: 선언적 설정의 자연스러운 확장.
- 마이크로서비스의 수요: 수백 서비스의 동적 관리 필요.
여러 기술이 동시에 성숙하면서 Envoy가 등장했다. 이는 우연이 아니라 필연이었다.
결론:
Service mesh는 Envoy + xDS + Kubernetes의 산물이다. 하나라도 빠졌으면 현재 형태는 불가능했을 것이다. Envoy가 L7 LB의 역사를 Nginx 이전과 이후로 나눈 것처럼, service mesh도 Envoy 이전과 이후로 나뉜다.
다음번에 마이크로서비스의 "복잡성 증가" 문제를 만나면, service mesh가 답이 될 수 있다. 그리고 그 아래에는 거의 항상 Envoy가 돌아가고 있다.
마치며: 트래픽을 다스리는 기술
핵심 정리
- L4 vs L7: 속도 vs 유연성. 실전에선 둘 다.
- IPVS: Linux 커널 L4 LB. DR 모드로 DSR.
- DSR: 응답을 LB 우회 → 극도의 효율.
- Maglev: 균등 분포 + O(1) + 최소 변경.
- ECMP + Maglev: 분산 LB 확장.
- XDP/eBPF: IPVS의 10배. 커널의 새 힘.
- HAProxy: L7 성능왕.
- Nginx: 웹서버 + LB.
- Envoy + xDS: Service mesh 기반.
- Anycast: 전 세계 분산.
실전 체크리스트
새 시스템 시작 시:
- 예상 트래픽량 파악.
- L4 / L7 / 둘 다 결정.
- Health check endpoint 구현.
- Session 관리 전략 (sticky, shared, JWT).
- SSL termination 위치.
- DDoS 방어.
- 관찰성 (메트릭, 로그, 트레이싱).
- Graceful shutdown.
- 재배포 전략.
도구 선택 매트릭스
| 규모 | 환경 | 추천 |
|---|---|---|
| 소규모 | 단순 | Nginx |
| 중규모 | 고성능 | HAProxy |
| Kubernetes | 모던 | Cilium + Envoy |
| 대규모 | 커스텀 | Maglev + Envoy |
| 글로벌 | 기업 | Cloudflare / CloudLB |
| 극한 | 연구 | XDP + Katran |
마지막 교훈
로드 밸런서는 인터넷의 침묵의 영웅이다. 잘 동작할 때는 존재를 잊지만, 없으면 하루도 못 간다. 수십 년간의 엔지니어링이 축적된 이 기술은 지금도 진화한다:
- 90년대: 하드웨어 LB.
- 2000년대: 소프트웨어 LB (Nginx, HAProxy).
- 2010년대: 분산 LB (Maglev, ECMP).
- 2020년대: eBPF + Service Mesh.
각 시대가 이전을 보존하면서 새 층을 더한다. 오늘날 Google의 LB 스택은 BGP부터 XDP까지 모든 레이어를 활용한다.
당신이 웹사이트를 방문할 때, 요청은 최소 5-10개의 로드 밸런서를 거친다:
- DNS 서버 → Anycast.
- ISP에서 CDN 선택.
- CDN의 edge LB (L4).
- CDN의 L7 proxy.
- Origin server의 LB.
- Kubernetes Ingress.
- Service Mesh sidecar.
- 최종 서비스.
이 모든 레이어가 조화를 이루어 밀리초 안에 응답을 돌려준다. 이것이 현대 인터넷 인프라의 기적이며, 이 글에서 본 모든 기술의 종합이다.
참고 자료
- Maglev: A Fast and Reliable Software Network Load Balancer (Google, 2016)
- Katran: Facebook's L4 LB
- Envoy Proxy Documentation
- HAProxy Documentation
- Linux Virtual Server (LVS/IPVS)
- XDP Tutorial
- Cilium eBPF Load Balancing
- Cloudflare Load Balancing Architecture
- Netflix Open Connect
- Google Cloud Load Balancer Architecture
- Istio Service Mesh
- The Scalable Commutativity Rule (MIT, Maglev related)