작년 말부터 Istio Ambient Mode를 진지하게 보기 시작했다. 1.22에서 Beta로 올라오고, 1.24~1.25 거치면서 단일 클러스터 한정으로는 production ready라는 얘기가 공식 문서에도 들어갔다. 우리 팀에서도 "그러면 슬슬 옮겨야 하는 거 아니냐"는 얘기가 나왔고, 6개월 정도 PoC와 일부 트래픽 마이그레이션을 진행했다.
결론부터 말하면 새 클러스터는 Ambient로 깔고, 기존 sidecar 클러스터는 당분간 그대로 둔다로 정리됐다. 그 과정에서 정리된 비교를 남긴다.
데이터 플레인 구조의 차이
Sidecar 모드는 다들 알다시피 Pod마다 envoy 컨테이너 하나 더 붙는다. 100개 Pod 띄우면 envoy도 100개. 메모리, CPU, 부팅 시간 다 곱하기 N이 된다.
Ambient는 이걸 두 층으로 나눈다.
- ztunnel: 노드마다 떠있는 DaemonSet. L4 mTLS, 기본 텔레메트리 담당. Rust로 짜여있고 envoy보다 가볍다.
- waypoint proxy: L7이 필요한 namespace나 service account 단위로만 띄우는 별도 Pod. 안 띄워도 mTLS는 동작한다.
핵심은 "L4까지만 필요한 워크로드는 waypoint를 안 띄운다"는 점이다. 사이드카는 L7 라우팅 한 줄도 안 쓰는 서비스에도 envoy가 풀로 붙어있는데, 실제로 우리 팀 워크로드 중 절반 이상이 L4 mTLS만 쓰고 있었다.
리소스 사용량 — 실측치
PoC 클러스터에서 같은 워크로드(약 80개 Deployment, 200여 Pod)를 두 모드로 돌려봤다. 워크로드는 전부 동일하게 두고 mesh 모드만 바꿨다.
| 항목 | Sidecar | Ambient (waypoint 4개) |
|---|---|---|
| 메시 관련 메모리 합 | ≈ 10.2 GiB | ≈ 2.8 GiB |
| 메시 관련 CPU(평시) | ≈ 3.4 vCPU | ≈ 1.1 vCPU |
| Pod 부팅 평균(콜드) | 11.3s | 7.8s |
메모리는 70% 가까이 줄었다. 사실 envoy 자체가 가벼운 편은 아니라서 Pod 수가 늘수록 격차가 더 벌어진다. 부팅 시간은 sidecar inject + envoy 초기화가 빠지면서 줄어든 게 컸다. 배포 중 롤링 업데이트 체감도 분명히 다르다.
다만 waypoint를 namespace 단위로 막 띄우면 이 격차가 빠르게 좁혀진다. Tetrate 쪽 비교 자료에서도 비슷한 얘기를 하고 있는데, L7 정책을 광범위하게 쓰는 팀이라면 메모리 절감 폭이 생각보다 작아질 수 있다.
L7 기능 호환성
이게 마이그레이션 검토에서 가장 시간 많이 잡아먹은 부분이다.
기존 sidecar에서 쓰던 것 중 ambient에서 그대로 동작하는 것:
- mTLS (PeerAuthentication)
- AuthorizationPolicy의 L4 규칙
- 기본 메트릭/로그(
istio_requests_total등은 ztunnel이 일부 쏴준다)
waypoint 없이는 안 되는 것:
- HTTP route 매칭, header 기반 라우팅
- VirtualService의 retries, timeout, fault injection
- L7 AuthorizationPolicy (
paths,methods) - request/response header 조작
여기까진 예상한 범위였는데, 막상 옮겨보니까 기존 VirtualService를 그대로 못 쓴다는 게 좀 컸다. Ambient에서는 Gateway API(HTTPRoute)로 옮기는 걸 권장한다. 우리는 Argo Rollouts로 카나리 배포를 돌리고 있는데, 여기 붙여놓은 VirtualService가 꽤 있어서 이걸 HTTPRoute로 다시 짜는 작업이 필요했다. 한 도메인 옮기는 데 반나절 잡아야 한다.
운영 측면에서 다른 점들
Sidecar 시절에 익숙해져 있던 것들이 Ambient에서는 달라진다.
로그 디버깅. 기존엔 kubectl logs <pod> -c istio-proxy 한 방이면 됐는데, Ambient는 트래픽이 ztunnel → waypoint → 대상 Pod로 흐른다. 어디서 끊겼는지 보려면 ztunnel 로그(노드 단위), waypoint 로그(namespace 단위), 대상 Pod 로그를 다 봐야 한다. 처음에 좀 헤맸다. istioctl ztunnel-config workload가 익숙해지면 빨라진다.
노드 장애의 영향 범위. ztunnel은 DaemonSet이라 노드가 망가지면 그 노드의 모든 Pod의 mesh 통신이 끊긴다. Sidecar는 Pod별로 분리돼 있어서 영향이 좁았다. 다행히 ztunnel은 가벼워서 잘 안 죽는데, 죽었을 때 영향이 더 넓다는 건 운영 체크리스트에 추가해둬야 한다.
namespace 라벨링. istio.io/dataplane-mode=ambient 라벨을 namespace에 붙이면 그 안의 Pod들이 mesh에 자동으로 들어간다. Pod 수정 없이 namespace 단위로 mesh 적용/해제가 되는 건 sidecar(주입 후 재배포 필요)보다 훨씬 편하다. 이건 정말 좋다.
멀티클러스터. 이게 우리가 발이 묶인 가장 큰 이유다. East-West gateway 통한 멀티클러스터 mTLS는 1.25 기준 아직 GA가 아니다. 우리는 prod/recovery 두 클러스터를 mesh로 묶어 쓰고 있어서 여기는 당장 못 옮긴다.
그래서 어떻게 결정했나
| 상황 | 우리 선택 |
|---|---|
| 신규 단일 클러스터 (내부 도구, 데이터 파이프라인) | Ambient |
| 기존 prod 멀티클러스터 | Sidecar 유지, 1.27~1.28 멀티클러스터 GA 보고 재검토 |
| L7 정책이 빽빽한 namespace | Sidecar 유지하거나, Ambient + 전용 waypoint |
| L4 mTLS만 있으면 되는 batch 워크로드 | Ambient (제일 효과 큼) |
생각해보면 당연한 결론인데, 6개월 돌려보기 전엔 "Ambient면 다 되는 거 아닌가" 정도로 생각했었다. 실제로 옮겨보니 케이스별로 트레이드오프가 분명했다.
마치며
Ambient가 명백히 좋은 영역(L4 중심, 신규 클러스터)과 아직 사이드카가 더 안전한 영역(멀티클러스터, L7 무거운 namespace)이 갈린다는 게 이번 검토의 결론이었다. "전면 이전" 같은 통일된 답이 나올 거라 기대했는데 그건 아니었다.
다음에는 ztunnel 디버깅 흐름이랑 Gateway API로 VirtualService를 옮기면서 헤맸던 부분을 따로 정리해보려고 한다. 혹시 멀티클러스터 Ambient를 production에서 굴리고 계신 분 있으면 어떻게 운영하시는지 댓글로 알려주시면 감사하겠다.
'기타' 카테고리의 다른 글
| NodeLocal DNSCache 없이 버티다 conntrack에 발목 잡힌 새벽 (0) | 2026.04.26 |
|---|