서비스 메시의 핵심 구성요소인 데이터 플레인과 컨트롤 플레인의 역할, Envoy 프록시의 내부 구조, 그리고 다양한 배포 모델을 분석합니다.
서비스 메시는 크게 두 가지 계층으로 구성됩니다. 실제 트래픽을 처리하는 **데이터 플레인(Data Plane)**과 정책과 설정을 관리하는 **컨트롤 플레인(Control Plane)**입니다. 이 장에서는 각 계층의 역할과 내부 구조를 살펴보고, 서비스 메시의 핵심 프록시인 Envoy의 아키텍처를 분석합니다.
데이터 플레인은 서비스 간 실제 네트워크 트래픽을 처리하는 계층입니다. 모든 서비스의 인바운드/아웃바운드 요청이 데이터 플레인의 프록시를 통과합니다.
데이터 플레인 프록시는 다음과 같은 기능을 수행합니다.
트래픽 인터셉트: iptables 규칙이나 eBPF 프로그램을 통해 Pod의 모든 네트워크 트래픽을 투명하게 가로챕니다. 애플리케이션은 프록시의 존재를 인식하지 못합니다.
로드 밸런싱: 대상 서비스의 여러 인스턴스 중 어디로 요청을 보낼지 결정합니다. 라운드 로빈, 가중치 기반, 최소 연결(least connections) 등 다양한 알고리즘을 지원합니다.
TLS 종료와 시작: 인바운드 트래픽의 TLS를 종료(termination)하고, 아웃바운드 트래픽에 mTLS를 자동 적용합니다.
프로토콜 관찰: HTTP, gRPC, TCP 등 프로토콜을 파싱하여 메트릭, 트레이스, 로그를 생성합니다.
정책 적용: 컨트롤 플레인에서 전달받은 라우팅 규칙, 인가 정책, 레이트 리미팅 등을 실시간으로 적용합니다.
Istio와 대부분의 서비스 메시 구현에서 데이터 플레인의 핵심은 Envoy 프록시입니다. Lyft에서 개발하고 CNCF에 기부된 Envoy는 고성능 L4/L7 프록시로, C++로 작성되었습니다.
Envoy 프록시 내부 구조
┌─────────────────────────────────────────────┐
│ Envoy │
│ │
│ ┌──────────┐ ┌──────────────────────┐ │
│ │ Listener │───→│ Filter Chain │ │
│ │ (포트) │ │ ┌───────────────────┐ │ │
│ └──────────┘ │ │ Network Filter │ │ │
│ │ │ (TCP proxy) │ │ │
│ │ ├───────────────────┤ │ │
│ │ │ HTTP Filter │ │ │
│ │ │ (Router, Auth) │ │ │
│ │ ├───────────────────┤ │ │
│ │ │ Custom Filter │ │ │
│ │ │ (Wasm, Lua) │ │ │
│ │ └───────────────────┘ │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────▼───────────┐ │
│ │ Cluster Manager │ │
│ │ (엔드포인트, 헬스체크) │ │
│ └──────────────────────┘ │
└─────────────────────────────────────────────┘
Listener: 특정 포트에서 연결을 수신합니다. 하나의 Envoy 인스턴스가 여러 리스너를 가질 수 있습니다.
Filter Chain: 수신된 요청을 순서대로 처리하는 필터의 체인입니다. 네트워크 필터(L4)와 HTTP 필터(L7)로 구분됩니다.
Cluster: 업스트림 서비스의 엔드포인트 그룹입니다. 로드 밸런싱, 헬스 체크, 서킷 브레이커 설정이 클러스터 단위로 적용됩니다.
Route: 요청을 어떤 클러스터로 전달할지 결정하는 라우팅 규칙입니다.
Envoy의 가장 강력한 특징은 xDS(x Discovery Service) API를 통한 동적 설정입니다. 프록시를 재시작하지 않고도 컨트롤 플레인에서 설정을 실시간으로 전달받아 적용합니다.
| API | 역할 |
|---|---|
| LDS (Listener Discovery) | 리스너 설정 동적 배포 |
| RDS (Route Discovery) | 라우팅 규칙 동적 배포 |
| CDS (Cluster Discovery) | 클러스터(업스트림) 설정 동적 배포 |
| EDS (Endpoint Discovery) | 엔드포인트(서비스 인스턴스) 목록 동적 배포 |
| SDS (Secret Discovery) | TLS 인증서와 키 동적 배포 |
이 아키텍처 덕분에 서비스 메시는 서비스 재배포 없이 트래픽 정책을 실시간으로 변경할 수 있습니다.
컨트롤 플레인은 데이터 플레인의 "두뇌" 역할을 합니다. 관리자가 정의한 정책과 설정을 데이터 플레인 프록시에 배포하고, 서비스 디스커버리 정보를 수집하여 전달합니다.
설정 배포: 관리자가 YAML로 정의한 트래픽 라우팅, 보안 정책, 관측 설정을 데이터 플레인에 배포합니다.
서비스 디스커버리: Kubernetes API 서버와 연동하여 서비스 엔드포인트의 변경을 감지하고 프록시에 전파합니다.
인증서 관리: mTLS에 필요한 인증서의 발급, 갱신, 폐기를 자동으로 처리합니다.
정책 변환: 사용자 친화적인 정책 정의(CRD)를 Envoy가 이해할 수 있는 xDS 설정으로 변환합니다.
Istio의 컨트롤 플레인은 Istiod라는 단일 바이너리로 통합되어 있습니다. 과거에는 Pilot, Mixer, Citadel, Galley 등 여러 컴포넌트로 분리되어 있었지만, 운영 복잡성을 줄이기 위해 하나로 합쳐졌습니다.
Istiod 내부 구성
┌─────────────────────────────────────┐
│ Istiod │
│ │
│ ┌──────────────┐ ┌─────────────┐ │
│ │ Pilot │ │ Citadel │ │
│ │ (xDS 서버) │ │ (CA, 인증서)│ │
│ └──────┬───────┘ └──────┬──────┘ │
│ │ │ │
│ ┌──────▼──────────────────▼──────┐ │
│ │ Config Controller │ │
│ │ (Kubernetes CRD 감시) │ │
│ └────────────────────────────────┘ │
└──────────────────┬──────────────────┘
│ xDS (gRPC)
┌──────────┴──────────┐
▼ ▼
[Envoy 1] [Envoy N]
Pilot 기능: Kubernetes 서비스, 엔드포인트, Istio CRD(VirtualService, DestinationRule 등)를 감시하여 Envoy 설정을 생성하고 xDS API로 배포합니다.
Citadel 기능: SPIFFE 호환 워크로드 아이덴티티를 발급합니다. 각 서비스에 X.509 인증서를 자동 발급하고 주기적으로 갱신합니다.
서비스 메시의 데이터 플레인은 크게 세 가지 배포 모델로 나뉩니다.
가장 전통적인 방식으로, 각 Pod에 프록시 컨테이너를 주입합니다.
┌─────────────────────────┐
│ Pod │
│ ┌─────────┐ ┌─────────┐ │
│ │ App │ │ Envoy │ │
│ │ :8080 │ │ :15001 │ │
│ └────┬────┘ └────┬────┘ │
│ └───────────┘ │
│ iptables redirect │
└─────────────────────────┘
장점: 서비스별 세밀한 설정이 가능하고, 격리성이 높습니다.
단점: Pod당 50~100MB 메모리 오버헤드, mTLS만으로도 166%에 달하는 지연 시간 증가(벤치마크 기준), 사이드카 버전 관리 부담이 큽니다.
노드당 하나의 공유 프록시를 배치하여 해당 노드의 모든 Pod 트래픽을 처리합니다.
┌────────────────────────────────────────┐
│ Node │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Pod A │ │Pod B │ │Pod C │ ... 앱 Pod│
│ └──┬───┘ └──┬───┘ └──┬───┘ │
│ └────────┼────────┘ │
│ ▼ │
│ ┌────────────────┐ │
│ │ ztunnel (L4) │ DaemonSet │
│ │ (노드당 1개) │ │
│ └────────────────┘ │
│ │
│ ┌────────────────┐ │
│ │ Waypoint (L7) │ 선택적 배포 │
│ │ (네임스페이스당) │ │
│ └────────────────┘ │
└────────────────────────────────────────┘
장점: 리소스 오버헤드가 극적으로 감소합니다. mTLS 전용 모드에서 약 8%의 오버헤드만 발생합니다. Pod에 사이드카가 없으므로 시작 시간에 영향이 없습니다.
단점: L7 기능을 위한 웨이포인트 프록시 배포 시 추가 네트워크 홉이 발생합니다. 서비스별 세밀한 L4 설정이 제한적입니다.
eBPF 프로그램을 리눅스 커널에 로드하여 네트워킹을 처리합니다.
┌────────────────────────────────────┐
│ Node │
│ │
│ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Pod A │ │Pod B │ │Pod C │ │
│ └──┬───┘ └──┬───┘ └──┬───┘ │
│ └────────┼────────┘ │
│ ───────────▼────────────── │
│ ┌─────────────────────────┐ │
│ │ Linux Kernel │ │
│ │ ┌─────────────────────┐ │ │
│ │ │ eBPF 프로그램 │ │ │
│ │ │ (L3/L4 처리) │ │ │
│ │ └─────────────────────┘ │ │
│ └─────────────────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ Envoy (L7) │ 필요 시에만 │
│ └──────────────┘ │
└────────────────────────────────────┘
장점: 커널 수준에서 직접 처리하므로 유저스페이스 프록시 대비 40% 낮은 지연 시간과 60% 적은 CPU 사용량을 달성합니다. CNI(Container Network Interface)와 서비스 메시를 하나의 컴포넌트로 통합할 수 있습니다.
단점: 리눅스 커널 버전에 대한 의존성이 있습니다(최소 5.4+, 권장 5.10+). L7 기능은 여전히 Envoy 프록시가 필요합니다.
각 서비스 메시가 사용하는 데이터 플레인 프록시는 서로 다른 특성을 가지고 있습니다.
| 특성 | Envoy (Istio) | linkerd2-proxy (Linkerd) | eBPF (Cilium) |
|---|---|---|---|
| 언어 | C++ | Rust | C (eBPF) + Go |
| 프로토콜 | HTTP/1.1, HTTP/2, gRPC, TCP, 커스텀 | HTTP/1.1, HTTP/2, gRPC, TCP | L3/L4 전체, L7 일부 |
| 확장성 | Wasm, Lua 필터 | 제한적 | eBPF 프로그램 |
| 메모리 | ~50MB/인스턴스 | ~20MB/인스턴스 | 커널 내 실행 (최소) |
| L7 기능 | 풀 스펙 | HTTP 중심 | Envoy 위임 |
프록시 선택은 서비스 메시 선택에 종속됩니다. Envoy의 풍부한 L7 기능이 필요하면 Istio, 경량성을 중시하면 Linkerd, 최고의 성능을 원하면 Cilium이 적합합니다. 3장부터 각 프로젝트를 깊이 있게 분석하겠습니다.
다음 장에서는 가장 널리 사용되는 서비스 메시인 Istio의 아키텍처와 핵심 기능을 심층 분석하겠습니다.
이 글이 도움이 되셨나요?
Istio의 내부 아키텍처, Ambient 모드와 사이드카 모드의 비교, 설치와 기본 설정까지 Istio의 핵심을 깊이 있게 분석합니다.
마이크로서비스 아키텍처에서 서비스 간 통신이 왜 어려운지, 그리고 서비스 메시가 어떤 문제를 해결하기 위해 등장했는지 살펴봅니다.
Istio의 트래픽 관리 기능을 실전 시나리오로 살펴봅니다. 가중치 기반 라우팅, 카나리 배포, 서킷 브레이커, 폴트 인젝션, 트래픽 미러링까지.