Istio 1편: 왜 Istio Ambient mode인가?

Istio Ambient mode의 도입 배경과 동작 원리

Jetty, 정재홍 • DevOps Engineer

  • 엔지니어링

안녕하세요, 채널코퍼레이션 DevOps팀 엔지니어 재티, 딜런입니다.

채널팀은 2025년 3월부터 11월까지, 약 8개월에 걸쳐 Istio를 프로덕션에 도입했습니다. 눈 여겨볼 점은 기존의 Sidecar mode가 아닌, 최근 GA(General Availability)된 Ambient mode를 선택했다는 부분입니다. 이 시리즈에서는 3편에 걸쳐서 도입 과정에서의 의사결정, 트러블슈팅, 그리고 운영 경험을 공유하려고 합니다.

  • 1편: 왜 Istio Ambient mode인가? (현재 글)

  • 2편: Envoy config로 해부하는 Ambient mode

  • 3편: 프로덕션에서 만난 당황스러운 이슈들과 트러블슈팅

첫 번째 글에서는 1) 왜 Service mesh를 도입했는지, 2) 왜 Sidecar가 아닌 Ambient mode를 선택했는지, 그리고 3) Ambient mode가 어떻게 동작하는지에 대해 간략하게 이야기합니다.

오랫동안 미뤄왔던 숙원 프로젝트, Service mesh

Service mesh 도입은 사실 여러 해 전부터 논의되어 왔던 프로젝트입니다. 매번 "지금은 아니다"라는 결론으로 미뤄졌는데, 2025년 초에 드디어 본격적으로 시작하게 되었습니다.

개별 기능만 놓고 보면 Service mesh가 꼭 필요한가? 라는 질문에 "아니오"라고 답할 수도 있습니다. 대략적인 네트워크 가시성은 APM 도구로, 카나리 배포는 Ingress 수준에서 트래픽제어로, rate-limit은 애플리케이션 레벨에서 각각 해결하는 방식으로 빠르게 해결할 수 있으니까요.

하지만 채널팀에서 서로 다른 역할과 기능을 가진 서비스들이 계속 해서 늘어나고 있고, 앞으로의 인프라 규모와 방향성을 고려했을 때, 이 기능들을 통합적으로 제공하는 Service mesh에 투자하는 것이 장기적으로 맞다고 판단했습니다.

Service mesh에게 기대했던 점

도입을 결정하면서 Service mesh로부터 기대한 것들을 정리했습니다.

핵심 목표

  • 네트워크 가시성: 기본적인 L7 네트워크 metrics부터 서비스 간 호출 관계 등 전반적인 트래픽 현황 파악

  • 카나리 배포: Service Mesh를 통해 L7 네트워크에 대한 통제력을 강화하여, 더 정교한 카나리 배포 구현

추가 기대 사항

  • Distributed Tracing (서비스 간 요청 추적)

  • Traffic Management (rate-limit, timeout 설정)

  • Circuit Breaking (장애 전파 방지)

  • mTLS / 상호 인증 (Optional)

물론 모든 기능을 당장 사용하려는 건 아니었습니다. 하지만 Service mesh라는 기반을 마련해두면 필요할 때 상대적으로 쉽게 적용할 수 있다는 점이 매력적이었습니다.

그러면 Istio?

Service mesh를 도입하기로 했으니, 어떤 솔루션을 쓸지 결정해야 했습니다.

Linkerd와 Cilium Service mesh도 검토했었습니다. Linkerd는 가볍고 단순하다는 장점이 있었지만, Istio에 비해서 사용 사례가 적어서 참고할 자료가 부족했습니다. Cilium은 Service mesh 기능을 포함하고 있지만, eBPF 기반 CNI로서 더 잘 알려져 있어서 Service mesh만을 위해 채택하기엔 부담스러웠습니다. (저희는 CNI로 Cilium이 아닌 다른 솔루션을 사용하고 있습니다.)

Istio를 선택한 이유는 단순했습니다. 커뮤니티와 생태계가 가장 크고, 레퍼런스와 자료가 가장 많기 때문입니다. Service mesh는 인프라의 핵심 요소인만큼 문제가 생겼을 때 고민을 함께할 커뮤니티가 있는 게 중요하다고 생각했습니다. Istio는 그 조건을 가장 잘 충족했습니다.

왜 Sidecar가 아닌 Ambient mode인가?

Istio를 쓰기로 했으니, 다음 질문은 Sidecar mode vs Ambient mode였습니다.

Ambient mode를 접하게 된 계기

2024년 말, Istio 1.24에서 Ambient mode가 GA(General Availability)에 이르렀다는 소식을 접했습니다; https://istio.io/latest/blog/2024/ambient-reaches-ga/. "Sidecar 없이 Service mesh를 운영한다"는 컨셉이 흥미로웠고, 본격적으로 리서치를 시작했습니다.

Ambient mode란?

https://istio.io/latest/blog/2023/waypoint-proxy-made-simple

Ambient mode는 기존 Sidecar 방식과는 많이 다른 아키텍처입니다.

  • Sidecar mode: 모든 Pod마다 Envoy proxy가 붙습니다.

  • Ambient mode: ztunnel(노드당 1개, L4 처리)과 waypoint(namespace/service 단위, L7 처리)로 구성됩니다.

구성요소와 동작 원리에 대해서는 이 글 뒷편에서 더 자세히 다루고자 합니다.

Ambient mode의 장점 — Sidecar mode의 한계

Ambient mode의 장점을 다룰 때에는, Istio 팀에서 제안한 Sidecar mode의 구조적 한계를 함께 짚어나가야 합니다. Ambient mode는 이 한계들을 넘어서기 위해 설계되었기 때문입니다.

1. Control Plane 부하의 확장성 문제

Sidecar mode에서는 기본적으로 모든 sidecar가 mesh 내 다른 모든 destination의 정보를 알고 있어야합니다. 따라서 만약 destination 설정이 변경되면 모든 sidecar에 한꺼번에 전파해야 하므로, 클러스터가 커질수록 istiod(control plane)의 부담이 가파르게 증가합니다.

Ambient mode에서도 ztunnel은 기존 sidecar와 마찬가지로 mesh 전체의 정보를 알고 있어야 합니다. 하지만 핵심은 단순히 전파 대상 수가 줄어드는 것이 아니라, polynomial scaling problem 자체를 해결할 수 있다는 점입니다. Sidecar mode에서는 Pod 수가 곧 proxy 수이므로, 서비스가 늘어날수록 전파해야 할 설정 크기 × 전파 대상 수가 비선형적으로 증가합니다.

https://www.cncf.io/blog/2023/04/26/istio-ambient-waypoint-proxy-made-simple/

더 자세한 내용은 Istio 공식 블로그을 참고해주세요.

2. Data Plane 자원 낭비 — Pod마다 추가되는 Envoy proxy

Sidecar mode에서는 Pod 하나당 Envoy proxy 하나가 필요합니다. 현재 채널팀은 약 4,000개의 Pod을 운영하고 있습니다.

Istio 공식 문서 및 기준으로 Envoy sidecar 및 ztunnel의 리소스 사용량은 다음과 같습니다:

  • 1,000 RPS 기준: sidecar 당 약 0.2 vCPU, 60Mi 메모리

  • 1,000 RPS 기준: ztunnel 당 약 0.06 vCPU, 12Mi 메모리

저희가 측정한 Envoy의 리소스 사용량은 다음과 같았습니다:

  • Idle 상태: 약 0.05~0.01 vCPU, 60Mi 메모리

  • 2,000 RPS 기준: 약 0.8~1.2 vCPU, 300~500Mi 메모리

4,000개 Pod에 모두 sidecar를 붙인다면, idle 상태에서만 수십~수백 vCPU와 약 240Gi 메모리가 순수하게 프록시에 소모됩니다. Ambient mode에서는 ztunnel이 노드당 하나, waypoint가 namespace나 service 단위로 존재합니다. 물론 서비스가 확장되면 노드 수도 늘어나므로 ztunnel 수도 증가하지만, Pod 수에 비례하여 1:1로 늘어나는 Sidecar에 비하면 리소스 사용량의 증가폭이 훨씬 완만합니다.

3. K8s Gateway API 지원; https://gateway-api.sigs.k8s.io/

오늘날 Kubernetes에서는 기존 Ingress 리소스의 업데이트가 freeze되고 Gateway API가 새로운 표준으로 자리잡고 있습니다. Istio 팀도 이 흐름에 맞춰 Gateway API를 기본 옵션으로 채택하는 방향으로 움직이고 있었고, 공식 문서도 Gateway API 기준으로 작성되기 시작했습니다.

Gateway API 자체는 Sidecar mode에서도 사용할 수 있지만, 당시에는 Sidecar mode가 Istio API(VirtualService 등)가 주된 방식이었고, Ambient mode의 공식 문서와 예제가 처음부터 Gateway API 기준으로 작성되어 있어서 Ambient mode와 함께 도입하기에 자연스러웠습니다.

Ambient mode의 단점

물론 단점 또한 존재합니다.

  • 장애 영향 범위의 확대: Sidecar mode에서는 proxy가 Pod과 lifecycle을 같이하여, 장애의 영향 범위가 각 Pod에 그칩니다. 반면 Ambient mode에서는 ztunnel(노드 단위)과 waypoint(namespace/service 단위)에 의존하므로, 이 컴포넌트에 장애가 발생하면 노드 전체 혹은 namespace 전체로 영향 범위가 확대됩니다. 다른 관점에서 보면, Sidecar mode에서는 존재하지 않았던 SPoF(Single Point of Failure)가 생긴 것입니다.

  • 높아진 디버깅 난이도: ztunnel, waypoint, HBONE 같은 새로운 개념들을 익혀야 하며, proxy와 hop이 늘어남에 따라 문제가 발생했을 때 원인을 추적하기가 더 까다롭습니다.

  • 안정성 우려 및 낮은 성숙도: GA 직후라 프로덕션에서 검증된 사례가 적었고, Sidecar mode 및 Istio API(e.g. VirtualService)에 비해 덜 성숙합니다.

솔직히 파격적인 리소스 절약이라는 점 외에는 Sidecar mode가 낫다고 생각합니다. 그런데도 우리는 Ambient mode를 선택했습니다.

팀 내 의사결정 과정

팀 내에서 Sidecar vs Ambient 논의를 진행했습니다.

"2~3년 동안은 건드리지 않을 걸 선택하고 싶음. 차라리 시간을 들이고 깊게 고민해서 결정했으면 좋겠음."

"네트워크 트래픽에 대한 조작과 가시성이 핵심임. 그것만 잘 되면 Ambient mode도 상관없음. 대신 버그나 안정성이 걸리긴 함."

"리소스 측면 제외하고는 Sidecar 장점이 많아 보이는데, 다양한 기능을 사용하지 않을 거면 Ambient. 문제 발생 빈도보다는 장애 복구 속도에 집중해야 함."

핵심 논점은 이랬습니다. Sidecar mode가 더 성숙한 건 맞지만, 계속해서 커지는 서비스 규모와 인프라에 대응하며 확정성을 고려했을 때, 앞서 다룬 세 가지 측면에서 Ambient mode가 우리 팀에 적합한 선택이라고 판단했습니다.

Sidecar mode는 도입한 이후 다시 Ambient mode로 마이그레이션 하는 상황을 피하고 싶었기 때문에, 우리는 팀 내 Istio와 Envoy에 대한 이해도를 높이면서, 신중히 리서치를 진행하는 방향으로 Ambient mode를 선택했습니다.

Istio Ambient mode의 구성요소와 동작 원리

앞에서 Service mesh의 필요성과 Ambient mode를 선택한 이유를 간략하게 다뤘으니, 이제 Ambient mode가 실제로 어떻게 동작하는지 살펴보겠습니다. 아래 내용은 도입 전 리서치 단계에서 팀이 가장 집중적으로 파악했던 부분들이며, 특히 HBONE의 동작 방식과 traffic redirection 구조를 이해하는 것이 이후 트러블슈팅에서 결정적이었습니다.

대부분의 Service mesh 구현체(Istio Sidecar mode, Linkerd 등)는 Pod마다 proxy를 sidecar 형태로 부착합니다. 반면 Istio Ambient mode는 Node마다 ztunnel을 배치하고, 필요한 경우에 한해 waypoint proxy가 L7 라우팅을 하는 방식입니다.

Sidecar mode: Envoy 프록시를 사이드카로 배포하는 Istio의 기존 모델

이 섹션에서는 Ambient mode의 구성요소와 동작원리를 간단하게만 전달하고자 합니다. 보다 자세한 내용은 Istio 공식문서Istio GitHub의 ARCHITECTURE.md를 참고해주세요.

1. Ambient mode와 Istio control plane

Istio에서 Control Plane(istiod)은 data plane에 설정(configuration 및 policy)를 전파하는 역할을 합니다. Ambient mode에서 ztunnel과 waypoint는 data plane 컴포넌트로서 istiod와 xDS API를 통해 통신하며 클러스터 상태를 전달받습니다.

  • ztunnel은 xDS API를 통해서 istiod와 통신합니다.

  • ztunnel은 서비스 간 mTLS 통신을 위해 인증서를 받습니다.

data plane에 설정 정보를 전파하는 역할은 sidecar mode와 다르지 않습니다. sidecar mode에서는 전파 대상이 service마다 실행되는 sidecar proxy라면, ambient mode에서는 waypoint와 ztunnel이라는 점에서 차이가 있습니다.

https://istio.io/latest/docs/ops/deployment/architecture/

2. Ambient data plane

  • Ztunnel은 L4에서 노드당 1개씩 배치돼 mTLS 터널과 기본 정책을 처리합니다.

  • Waypoint Proxy은 L7에서 필요한 네임스페이스/서비스에만 선택적 배치, 정교한 라우팅·관측을 담당합니다.

  • reference: https://istio.io/latest/docs/ambient/architecture/data-plane/

Ambient mode에서 workload는 크게 3가지로 나눌 수 있습니다.

  1. Mesh에 속하지 않는 경우

  2. Mesh에 속하는 경우

  3. Mesh에 속하며, Waypoint가 설정된 경우

2-1. Mesh에 속하지 않는 경우

두 Pods 모두 Out-mesh(Mesh에 속하지 않는) 경우에는 기존 쿠버네티스 네트워크(via kube-proxy) 동작 방식과 동일합니다.

2-2. Mesh에 속하는 경우

  • Outbound 트래픽

  • Inbound 트래픽

    • Outbound와 마찬가지로 들어오는 트래픽 또한 해당 node의 ztunnel을 거쳐서 들어옵니다. AuthorizationPolicy에 위배되지 않는 한, 요청이 성공적으로 들어옵니다. pod(+ztunnel)는 HBONE 트래픽 혹은 plaintext 트래픽을 받을 수 있습니다.

Ambient mesh에 속한 workloads들은 서로 HBONE, ztunnel, x509 certs를 통한 mTLS로 이루어져 있습니다. mTLS를 강제하는 만큼, source와 destination 모두 고유한 x509 certs를 가지고 있으며, ztunnel은 자신이 속한 node의 workloads(pod)들의 certificate를 이용합니다. 그리고, pods 간의 mTLS 과정 중간에는 ztunnel 자신의 identity를 이용하지 않습니다.

2-3. Mesh에 속하며, Waypoint가 설정된 경우

waypoint가 enable된 경우, waypoint의 범위에 적용되는 트래픽은 모두 waypoint를 거쳐가며, 이를 통해 L7 policy(AuthorizationPolicy, RequestAuthentication, WasmPlugin, Telemetry, …)를 적용합니다.

ztunnel과 달리 waypoint proxy는 꼭 source/destination pod와 같은 node에 존재하지 않을 수 있습니다.

3. HBONE

HBONE (HTTP-Based Overlay Network Environment)은 Istio에서 쓰이는 개념이며, Istio 컴포넌트 간의 통신에서 사용되는 secure tunneling protocol을 가리킵니다.

HBONE은 다음 3가지 표준을 포함합니다.

  • HTTP/2

  • HTTP CONNECT (tunnel connection)

  • mTLS

이름만 보면 복잡한 별도의 프로토콜처럼 느껴지지만, 실체는 Envoy의 기존 기능들을 조합한 것에 가깝습니다. HTTP CONNECT 메서드로 터널을 열고, 그 위에 TLS를 씌운 것이 HBONE의 전부입니다. 이미 검증된 표준들을 Envoy config로 조립한 것이라고 이해하면 됩니다.

HBONE 이전의 방식에서는, 트래픽의 내용을 변경하거나 특정 헤더를 추가해야 하는 경우가 많았습니다. Istio는 애플리케이션 간의 통신을 관리하기 위해 종종 Istio 고유의 메타데이터를 트래픽에 삽입했습니다. 하지만 HBONE은 애플리케이션 트래픽의 원본 상태를 전혀 변경하지 않고도 프록시 처리를 수행할 수 있습니다.

다만 이 특성은 디버깅에서는 양날의 검이 됩니다. 실제로 TCP connection reset 이슈를 추적할 때, ztunnel·pod·waypoint에서 tcpdump를 떠봤지만 HBONE 구간에서는 암호화된 TLS 내용만 보였습니다. destination 측에서 모든 네트워크 인터페이스를 대상으로 캡처해야 ztunnel이 복호화한 트래픽을 확인할 수 있었는데, 이 과정은 3편 트러블슈팅에서 자세히 다루겠습니다.

4. Ztunnel traffic redirection

traffic redirection; data plane functionality that intercepts traffic sent to and from ambient-enabled workloads, routing it through the ztunnel node proxies that handle the core data path

Sidecar mode가 sidecar가 애플리케이션으로 향하는 모든 트래픽을 가로채는 것처럼 Ambient mode에서는 모든 트래픽은 리다이렉트됩니다. 이 때 주의할 점은, ztunnel이 우회하게 된다면 mesh에서 설정한 모든 Authorization policy 또한 무시된다는 점입니다.

ztunnel은 다음 그림과 같이 istio-cni pod의 도움으로 workload pod의 모든 트래픽을 수신할 수 있게 됩니다. istio-cni node agent는 pod 생성/삭제와 같은 CNI events에 반응하며, pod의 네트워크 규칙을 변경하여 node-local ztunnel로 트래픽이 리다이렉트 될 수 있도록 합니다. 이 때 리다이렉트는 모두 Pod network 안에서 이루어지며, host(node) side에서 이루어지지 않습니다.

이 구조에서 주의할 점은, ztunnel과 istio-cni는 항상 Running 상태여야 한다는 것입니다. 만약 istio-cni가 아직 준비되지 않은 상태에서 Pod이 스케줄되면, 해당 Pod은 mesh에 불완전(partially)하게 참여하는 상태가 될 수 있습니다. 이 문제를 방지하기 위해 untaint-controller를 활용할 수 있으며, 이에 대한 자세한 내용은 3편에서 다루겠습니다.

istio-cni는 workload pod만 변경하는 것이 아니라, ztunnel에게도 새로운 pod와 연결을 맺어야 함을 알립니다.

Pod에 들어오는 모든 TCP 트래픽은 유입 처리를 위해 ztunnel로 리다이렉트 됩니다. 트래픽이 plaintext(source port != 15008)인 경우 pod 내 ztunnel plaintext source port 15006으로 리다이렉트 됩니다. 트래픽이 HBONE(source port == 15008)인 경우 pod 내 ztunnel HBONE listening port 15008로 리다이렉트 됩니다. pod를 나가는 모든 TCP 트래픽은 HBONE 캡슐화를 사용하여 ztunnel에서 전송되기 전에 egress 처리를 위해 ztunnel의 port 15001로 리다이렉트 됩니다.

여기서 한 가지 짚고 넘어갈 점이 있습니다. 공식 문서에는 "in-pod ztunnel"이라는 표현이 등장하는데, ztunnel은 엄연히 workload pod과는 별개의 DaemonSet 컨테이너입니다. 실제 동작을 보면, istio-cni가 iptables에 주입하는 규칙은 단순히 ztunnel 컨테이너로 트래픽을 보내는 것이 아니라, Pod의 container network namespace 안에 생성된 TCP socket(localhost의 port 15001/15006/15008)으로 REDIRECT하는 것입니다. 이 socket이 노드의 ztunnel DaemonSet과 연결되어 있기 때문에, "in-pod ztunnel port"라는 표현이 가능한 것입니다. 즉, traffic redirection의 실제 대상은 ztunnel 컨테이너가 아니라 ztunnel과 연결된 Pod 내부 socket입니다.

다음 글 예고

이 글에서는 Ambient mode의 동작 원리를 개념 수준에서 다뤘습니다. 하지만 앞서 언급했듯이 Ambient mode의 실체는 Envoy config의 모음입니다. 다음 글에서는 ztunnel과 waypoint의 Envoy config를 직접 들여다보면서, 이 글에서 설명한 HBONE 터널링과 traffic redirection이 실제로 어떻게 구현되어 있는지 살펴보겠습니다.


이 글은 Istio Ambient Mode 도입기 시리즈의 첫 번째 글입니다.

  • 1편: 왜 Istio Ambient mode인가? (현재 글)

  • 2편: Envoy config로 해부하는 Ambient mode

  • 3편: 프로덕션에서 만난 당황스러운 이슈들과 트러블슈팅

We Make a Future Classic Product