사이드카리스 서비스 메시의 현실: eBPF가 Istio 사이드카를 어떻게 대체하는가
마이크로서비스를 운영하다 보면 어느 순간 이상한 광경을 마주칩니다. 서비스가 100개인데 kubectl get pods를 찍어보니 실행 중인 컨테이너가 200개 넘게 뜹니다. 각 Pod에 Envoy 사이드카가 하나씩 달려 있는 거죠. 저도 처음 Istio를 도입하고 이 화면을 봤을 때 잠시 멍했습니다. "서비스 간 통신을 안전하게 하려고 도입했더니 클러스터 절반이 프록시 컨테이너로 채워진 건가?" 싶었죠.
그 프록시 컨테이너 하나하나가 메모리를 50100MB씩 잡아먹고, 트래픽이 지나갈 때마다 13ms씩 레이턴시를 더합니다. 100개 서비스면 사이드카도 100개, Istio 버전을 올릴 때마다 전체를 롤링해야 합니다. 서비스 메시가 문제를 해결하는 게 아니라 새로운 문제를 만들고 있는 게 아닌가 싶은 순간이 옵니다.
그렇다면 이 문제를 구조적으로 다르게 접근할 방법이 있을까요?
핵심 개념
서비스 메시가 왜 필요한가
마이크로서비스 수가 늘어나면 서비스 간 통신이 스파게티가 됩니다. 어떤 서비스가 어떤 서비스와 이야기하는지, 특정 서비스가 느려졌을 때 연쇄 장애를 막으려면 어떻게 해야 하는지, 서비스 간 인증은 어디서 처리해야 하는지 — 이걸 각 서비스 코드 안에 직접 구현하면 금방 한계가 옵니다.
서비스 메시는 이 관심사들을 애플리케이션 코드 밖으로 꺼냅니다. 트래픽 관리, mTLS 기반 서비스 간 인증, 서킷 브레이킹, 분산 추적을 인프라 계층에서 처리하는 거죠.
mTLS(Mutual TLS): 클라이언트와 서버가 상호 인증서를 교환해 양방향으로 신원을 확인하는 방식입니다. 일반 TLS는 서버만 인증하지만, mTLS는 서비스 간 통신에서 양쪽 모두 "너도 증명해"를 요구합니다. 서비스 간 제로 트러스트 보안의 기반이 됩니다.
전통적인 사이드카 방식의 한계
기존 Istio + Envoy 방식을 그려보면 이렇습니다.
[Pod A] [Pod B]
├── 앱 컨테이너 ├── 앱 컨테이너
└── Envoy 사이드카 └── Envoy 사이드카
↕ ↕
iptables 인터셉션 iptables 인터셉션
↕ ↕
[L7 처리 후 목적지 전달]L4/L7: OSI 네트워크 모델의 레이어 번호입니다. L4(Transport Layer)는 TCP/UDP 포트 수준 트래픽을 다루고, L7(Application Layer)은 HTTP 헤더, gRPC 메서드 같은 애플리케이션 프로토콜까지 이해합니다. 서비스 메시에서 L7 처리가 가능하다는 건 "특정 헤더가 있을 때만 라우팅하라"처럼 세밀한 제어가 된다는 뜻입니다.
모든 인바운드/아웃바운드 트래픽이 iptables 규칙을 거쳐 Envoy로 우회된 뒤 목적지로 전달됩니다. 강력하지만 비용이 따릅니다. Pod당 Envoy 사이드카가 50~100MB 메모리를 소비하고, 네트워크 홉이 늘면서 1~3ms의 레이턴시가 추가됩니다.
eBPF가 이 자리를 대신하는 방법
eBPF(Extended Berkeley Packet Filter)는 Linux 커널 안에서 사용자 정의 프로그램을 안전하게 실행하는 기술입니다. 커널 소스를 수정하거나 커널 모듈을 올릴 필요가 없습니다.
eBPF 샌드박스: eBPF 프로그램은 커널에 올라가기 전에 verifier가 안전성을 검증합니다. 무한 루프나 잘못된 메모리 접근을 사전에 차단하기 때문에 커널 크래시 걱정 없이 동적으로 로드할 수 있습니다. 참고로 Linux 5.3부터는 반복 횟수가 증명 가능한 bounded loop는 허용됩니다.
eBPF가 서비스 메시에서 특히 강력한 이유는 소켓 리다이렉션(socket redirection) 덕분입니다. 패킷이 네트워크 스택 전체를 순회하는 대신, 소켓 레벨에서 목적지로 바로 연결됩니다. iptables 우회는 물론 프록시 컨테이너 없이도 트래픽을 처리할 수 있는 거죠.
eBPF 프로그램은 BPF 맵(Map) 을 통해 상태를 공유합니다. 서비스 엔드포인트 목록이나 정책을 BPF 맵에 올려두면, 트래픽이 들어올 때마다 유저스페이스를 거치지 않고 커널에서 직접 라우팅 결정을 내릴 수 있습니다. XDP(eXpress Data Path) hook은 드라이버 레벨에서 처리해 가장 빠르고, TC(Traffic Control) hook은 네트워크 스택 안쪽에서 작동해 더 풍부한 메타데이터를 다룰 수 있습니다. 서비스 메시 구현에는 주로 TC hook과 소켓 레벨 hook이 함께 쓰입니다.
구조를 그려보면 이렇습니다.
[Node]
┌──────────────────────────────────────────────┐
│ Linux Kernel │
│ ┌──────────────────────────────────────┐ │
│ │ eBPF 프로그램 (TC hook / 소켓 hook) │ │
│ │ BPF 맵: 엔드포인트, 정책, 메트릭 │ │
│ └──────────────────────────────────────┘ │
│ ↕ 트래픽 직접 처리 (iptables 우회) │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Pod A │ │ Pod B │ │
│ │ 앱 컨테이너 │ │ 앱 컨테이너 │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────┘사이드카가 없어지는 게 아니라, 역할을 커널이 흡수하는 구조입니다.
실전 적용
세 가지 시나리오로 나눠볼 수 있습니다. 새 클러스터를 구축하는 경우라면 Cilium이 가장 깔끔한 선택입니다. 기존 Istio 환경에서 성능만 개선하고 싶다면 Merbridge가 최소 변경으로 적용 가능합니다. 현재 클러스터가 어떻게 동작하는지 먼저 들여다보고 싶다면 Pixie로 관찰 가능성부터 확보하는 것이 좋은 출발점입니다.
예시 1: Cilium으로 사이드카 없는 서비스 메시 구축 (새 클러스터)
Cilium은 처음부터 사이드카 없이 eBPF만으로 서비스 메시를 구현한 솔루션입니다. GKE Dataplane V2, AKS의 Azure CNI Powered by Cilium 등 주요 클라우드가 이미 기본 데이터플레인으로 채택했습니다.
CNI(Container Network Interface): Kubernetes에서 Pod 네트워킹을 담당하는 플러그인 인터페이스입니다. flannel, Calico, Cilium 등이 CNI 구현체입니다. 클러스터 생성 시 어떤 CNI를 쓰느냐에 따라 네트워크 기능의 범위가 달라집니다.
기존 클러스터의 CNI를 바꾸는 건 꽤 큰 작업이기 때문에, 새로 프로비저닝하는 클러스터라면 처음부터 Cilium을 선택해볼 수 있습니다.
# Cilium v1.15 기준 — Helm으로 서비스 메시 + Hubble 관찰 가능성 포함 설치
helm repo add cilium https://helm.cilium.io/
helm install cilium cilium/cilium \
--namespace kube-system \
--set kubeProxyReplacement=true \
--set hubble.relay.enabled=true \
--set hubble.ui.enabled=true \
--set serviceMesh.enabled=true \
--set authentication.mutual.spire.enabled=true # v1.14+ 기능
# 설치 상태 확인
cilium status --wait정상 설치가 완료되면 이런 출력을 볼 수 있습니다.
/¯¯\
/¯¯\__/¯¯\ Cilium: OK
\__/¯¯\__/ Operator: OK
/¯¯\__/¯¯\ Envoy DaemonSet: disabled (using embedded mode)
\__/¯¯\__/ Hubble Relay: OK
\__/ ClusterMesh: disabled
DaemonSet cilium Desired: 3, Ready: 3/3, Available: 3/3
Deployment cilium-operator Desired: 1, Ready: 1/1, Available: 1/1
Deployment hubble-relay Desired: 1, Ready: 1/1, Available: 1/1이후 mTLS를 서비스 간에 적용하는 정책은 Kubernetes CRD로 선언합니다.
# 코드 변경 없이 서비스 간 mTLS 강제 적용
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: require-mtls
namespace: production
spec:
endpointSelector:
matchLabels:
app: payment-service
ingress:
- fromEndpoints:
- matchLabels:
app: order-service
authentication:
mode: requiredSPIFFE/SPIRE: SPIFFE(Secure Production Identity Framework for Everyone)는 서비스 간 신원을 증명하는 표준 규격이고, SPIRE는 그 구현체입니다.
authentication.mutual.spire.enabled=true를 활성화하면 SPIRE가 각 서비스에 고유한 암호화 신원(SVID)을 발급하고, 이를 기반으로 mTLS 인증이 이루어집니다. 애플리케이션 코드 변경 없이 서비스 신원을 관리할 수 있는 게 핵심입니다.
| 항목 | 사이드카 방식 | Cilium eBPF 방식 |
|---|---|---|
| 트래픽 경로 | 앱 → iptables → Envoy → 목적지 | 앱 → eBPF(커널) → 목적지 |
| 추가 컨테이너 | Pod당 Envoy 1개 | 없음 |
| 정책 적용 위치 | 사이드카 내부(유저스페이스) | 커널 레벨(BPF 맵) |
| mTLS 지원 | Envoy가 처리 | SPIFFE/SPIRE 연동 |
예시 2: 기존 Istio 환경에 Merbridge로 eBPF 가속 적용
이미 Istio를 쓰고 있다면 전면 교체 없이 iptables를 eBPF로 대체해 레이턴시를 줄이는 선택지가 있습니다. Merbridge가 그 역할을 합니다. Istio 설정 변경도, 코드 수정도 없이 적용 가능한 게 실무에서 매력적인 부분이에요.
# 기존 Istio 클러스터에 Merbridge 적용 (Linkerd, Kuma도 지원)
# ⚠️ 아래 명령어는 실습 환경용입니다.
# 프로덕션에서는 매니페스트를 먼저 다운로드해 내용을 검토한 뒤 적용해보시기 바랍니다.
kubectl apply -f https://raw.githubusercontent.com/merbridge/merbridge/main/deploy/all-in-one.yaml
# 적용 확인 — eBPF 프로그램 로드 상태
kubectl -n merbridge get pods
kubectl -n merbridge logs -l app=merbridge --tail=50Merbridge는 기존 iptables 규칙을 eBPF 소켓 리다이렉션으로 대체합니다. 패킷이 네트워크 스택을 완전히 순회하지 않고 소켓 레벨에서 목적지로 직접 연결되기 때문에 왕복 레이턴시가 줄어듭니다. 가장 큰 장점은 Istio 컨트롤 플레인 설정을 전혀 건드리지 않아도 된다는 점입니다.
예시 3: Pixie로 코드 한 줄 바꾸지 않고 관찰 가능성 확보
솔직히 분산 추적 설정이 귀찮아서 미루다가 장애 나고 나서야 후회했던 분이라면 — Pixie가 그 찜찜함을 없애줄 수 있습니다. 코드 한 줄 바꾸지 않고, 사이드카도 없이 서비스 트래픽을 자동으로 수집합니다.
한 가지 알아두면 좋은 전제 조건이 있습니다. px deploy는 Pixie Cloud 계정이 필요하고 클러스터에서 외부 클라우드로의 연결이 허용되어야 합니다. "제로 인스트루멘테이션"이라는 표현이 "완전히 독립 실행"을 의미하지는 않습니다. 에어갭 환경이나 클라우드 연결이 제한된 환경이라면 Cilium + Hubble 조합을 대안으로 검토해보시기 바랍니다.
# ⚠️ curl | bash 방식은 스크립트 내용을 직접 확인하지 않습니다.
# 신뢰할 수 없는 환경에서는 스크립트를 먼저 다운로드해 내용을 확인한 후 실행해보세요.
# Pixie CLI 설치 (Pixie Cloud 계정 필요)
curl -fsSL https://withpixie.ai/install.sh | bash
# 클러스터에 Pixie 배포
px deploy
# HTTP 요청/응답 실시간 확인 (최근 5분, production 네임스페이스)
px run px/http_data -- \
-start_time="-5m" \
-namespace="production"배포 직후부터 HTTP, gRPC, MySQL, Redis 등의 프로토콜을 자동 파싱해 요청/응답, 레이턴시, 에러율을 보여줍니다. eBPF가 커널 레벨 소켓 데이터를 가로채기 때문에 가능한 일입니다.
장단점 분석
장점
eBPF 방식으로 전환했을 때 가장 체감이 큰 부분은 역시 자원 효율입니다. 100개 서비스 기준으로 사이드카가 없어지면 최대 10GB의 메모리가 해방됩니다. 이 숫자를 처음 계산했을 때 꽤 놀랐는데, 노드를 한두 대 줄일 수 있는 수준이기도 합니다. 성능도 실제로 달라집니다. 고TPS 환경에서 사이드카 홉 하나가 1~3ms씩 더하면 p99 레이턴시에서 확실히 누적됩니다.
| 항목 | 내용 |
|---|---|
| 성능 | 사이드카 홉당 1~3ms 추가 레이턴시 제거. 고TPS 환경에서 체감 차이 큼 |
| 자원 효율 | Pod당 50~100MB 사이드카 메모리 절감. 100개 서비스면 최대 10GB 절약 |
| 가시성 범위 | 커널 레벨 수집으로 syscall, 네트워크 이벤트, CPU 사이클까지 관찰 가능 |
| 투명성 | 애플리케이션 코드·설정 변경 없이 네트워크 정책과 모니터링 적용 |
| 운영 단순성 | 사이드카 버전 관리, 롤링 업그레이드 불필요 |
단점 및 주의사항
장점이 많다고 해서 무조건 전환이 정답은 아닙니다. 특히 L7 처리 부분은 지금도 현실적인 한계가 있고, 멀티테넌시 환경에서는 보안 격리 수준을 꼭 따져봐야 합니다.
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| L7 처리 한계 | eBPF 프로그램의 크기 제한과 루프 횟수 제한으로 복잡한 HTTP/gRPC 라우팅 처리 어려움 | Istio Ambient의 waypoint proxy처럼 L7은 별도 프록시에 위임 |
| 보안 격리 수준 | 노드 공유 프록시 방식은 멀티테넌시 환경에서 사이드카보다 격리 약함 | 민감한 테넌트 분리가 필요하면 사이드카 방식 병행 검토 |
| 성숙도 | Cilium Service Mesh, Istio Ambient Mesh는 엔터프라이즈 프로덕션 레퍼런스가 아직 제한적 | 새 클러스터부터 점진적 도입 권장 |
| 디버깅 난이도 | 커널 레벨 문제는 원인 추적이 사이드카보다 복잡 | Hubble, bpftool 등 eBPF 전용 디버깅 도구 숙지 권장 |
| 커널 버전 의존성 | eBPF 고급 기능은 Linux 5.10+ 이상 권장, 일부는 5.15+ 요구 | 노드 OS 버전 사전 확인 필수 |
waypoint proxy: Istio Ambient Mesh의 L7 처리 컴포넌트입니다. L4는 노드당 ztunnel이 처리하고, HTTP/gRPC 같은 L7 정책이 필요한 경우에만 네임스페이스별 waypoint proxy가 개입합니다. 필요한 곳에만 프록시를 두는 방식이라 사이드카 전부를 유지하는 것보다 훨씬 효율적입니다.
실무에서 가장 흔한 실수
-
커널 버전 확인 없이 eBPF 기능을 붙이는 경우 —
uname -r로 노드 커널 버전을 먼저 확인해보시기 바랍니다. 온프레미스 환경에서 Ubuntu 20.04 LTS(커널 5.4)를 쓰고 있다면 일부 고급 기능을 사용하지 못합니다. 관리형 클러스터라고 자동 해결되지도 않습니다. GKE, AKS는 eBPF 지원 환경이 기본이지만, EKS는 기본 CNI가 AWS VPC CNI이기 때문에 Cilium을 쓰려면 별도 구성이 필요합니다. -
Cilium 도입이 Istio 전체 대체라고 오해하는 경우 — Cilium은 L4 네트워크 정책과 기본 mTLS를 잘 처리하지만, 헤더 기반 라우팅이나 카나리 배포 같은 복잡한 L7 트래픽 제어가 필요하다면 Istio나 waypoint proxy가 여전히 필요합니다.
-
멀티테넌시 환경에서 격리 요건 검토 없이 전환하는 경우 — 서로 다른 고객의 워크로드가 같은 노드를 공유하는 환경이라면, 노드 레벨 프록시 방식이 보안 감사에서 문제가 될 수 있습니다. 보안 팀이랑 먼저 얘기해두는 게 낫습니다. 나중에 감사 때 나오는 것보다 훨씬 편합니다.
마치며
사이드카리스 서비스 메시가 주목받는 이유는 단순히 트렌드여서가 아닙니다. eBPF는 서비스 메시의 인프라 비용을 커널로 내려보내, 애플리케이션 코드 외부에서 관찰 가능성과 보안을 동시에 확보하는 가장 현실적인 방향이 되었습니다. 사이드카가 "모든 Pod에 프록시를 주입하자"는 사고방식이었다면, eBPF는 "커널이 이미 모든 트래픽을 보고 있는데 거기서 처리하자"는 사고방식의 전환입니다.
지금 바로 시작해볼 수 있는 순서를 제안드립니다.
시작 전 체크: kubectl get nodes -o wide로 노드 OS를, uname -r로 커널 버전이 5.10 이상인지 확인해보시기 바랍니다. EKS 환경이라면 별도 Cilium 구성이 필요한지도 미리 파악해두는 것이 좋습니다.
- 관찰부터 시작 — 새 클러스터라면 Cilium + Hubble 조합으로, 기존 Istio 환경이라면 Merbridge 적용 후 Hubble 또는 Pixie(클라우드 연결이 가능한 경우)로 현재 서비스 트래픽 패턴을 코드 변경 없이 시각화해볼 수 있습니다.
- 새 클러스터부터 Cilium으로 시작 — 기존 환경의 CNI를 교체하는 건 큰 작업이지만, 신규 클러스터라면 처음부터 Cilium을 선택해 별도 서비스 메시 없이 핵심 기능을 확보할 수 있습니다.
- 기존 Istio 환경은 Merbridge로 먼저 가속 — 전면 교체 없이 iptables를 eBPF로 대체하는 것만으로도 레이턴시 개선을 확인해볼 수 있습니다. 그 결과를 보고 나서 Ambient Mesh로의 마이그레이션을 고려해도 늦지 않습니다.
참고 자료
- eBPF and Service Mesh: Performance and Observability | Groundcover
- Service Mesh with eBPF: 5 Key Capabilities | Tigera
- eBPF and the Service Mesh: Don't Dismiss the Sidecar Yet | InfoQ
- eBPF: The Silent Power Behind Cloud Native's Next Phase | Cloud Native Now
- Istio Ambient vs. Cilium | Istio 공식 블로그
- Unlocking Cloud Native Security with Cilium and eBPF | CNCF
- Sidecar-Free Service Mesh: Understanding Cilium's eBPF Architecture | Aicademy
- Real-World Use Cases of eBPF | Medium
- eBPF Applications Landscape | ebpf.io
- Merbridge GitHub Repository
- Deep Dive into Istio Ambient Mode Traffic Paths | Jimmy Song
- eBPF, Sidecars, and the Future of the Service Mesh | Buoyant