Istio 서비스 메시 · 사이드카와 데이터플레인 개념 · 이론
사이드카 — 코드를 고치지 않고 네트워크를 바꾸는 법
한 줄 요약
서비스 메시는 새로운 네트워크가 아니라, 모든 파드에 프록시를 한 대씩 붙이고 그 프록시를 중앙에서 설정하는 구조다.
왜 이게 필요했나
마이크로서비스를 열 개쯤 만들고 나면 어느 팀에서나 같은 코드가 반복해서 나타난다. 재시도, 타임아웃, 서킷 브레이커, TLS 인증서 로딩, 상대방 검증, 요청 로깅, 트레이스 헤더 전파. 서비스가 Java·Go·Python·Node 로 흩어져 있으면 이 목록을 네 번 구현해야 하고, 네 구현의 동작이 미묘하게 다르다. 타임아웃 기본값 하나를 바꾸려면 네 개의 저장소에 PR 을 올리고 네 번 배포해야 한다.
메시의 발상은 단순하다. 그 공통 관심사를 애플리케이션 프로세스 밖으로 꺼내, 같은 파드 안의 프록시가 대신 처리하게 한다. 애플리케이션은 여전히 http://reviews:9080 으로 평문 요청을 보내지만, 실제로 그 요청을 상대방까지 나르는 것은 프록시다. 그래서 mTLS 를 켜는 일이 애플리케이션 배포가 아니라 설정 리소스 하나를 적용하는 일이 된다.
어떻게 동작하나
Istio 는 두 층으로 나뉜다. 컨트롤 플레인(istiod) 과 데이터 플레인(각 파드의 Envoy) 이다. istiod 는 1.5 에서 Pilot·Citadel·Galley 를 한 바이너리로 합친 것이고, 요청 경로에 끼어들던 Mixer 는 1.8 에서 완전히 제거됐다. 즉 요청 하나가 처리되는 동안 컨트롤 플레인에 물어보는 일은 없다. istiod 가 죽어도 이미 설정을 받은 Envoy 는 마지막 설정으로 계속 트래픽을 나른다.
설정은 xDS 라는 gRPC 스트림으로 흐른다.
| API | 무엇을 나르나 | Istio 쪽 입력 |
| --- | --- | --- |
| LDS | 리스너(포트, 프로토콜) | 포트 이름, Gateway |
| RDS | HTTP 라우팅 규칙 | VirtualService |
| CDS | 업스트림 클러스터 | DestinationRule |
| EDS | 클러스터의 실제 엔드포인트 | Kubernetes Endpoints |
| SDS | TLS 인증서와 키 | istiod CA |
Istio 는 이 모두를 ADS 라는 하나의 스트림으로 합쳐 보낸다. 클러스터 정의보다 엔드포인트가 먼저 도착해 설정이 순간적으로 깨지는 일을 막기 위해서다.
주입은 쿠버네티스의 MutatingAdmissionWebhook 이 한다. 네임스페이스에 istio-injection=enabled 라벨이 붙어 있으면, 그 네임스페이스에서 파드가 생성되는 순간 istiod 가 파드 스펙을 고쳐 컨테이너 둘을 끼워 넣는다.
istio-init(초기화 컨테이너):istio-iptables를 실행해 REDIRECT 규칙을 심는다. 인바운드는 15006, 아웃바운드는 15001 로 돌린다. UID 1337 로 나가는 트래픽만 예외로 두는데, 그게 프록시 자신이기 때문이다. 이 예외가 없으면 무한 루프가 난다.istio-proxy(사이드카): Envoy 와 istio-agent 가 함께 도는 컨테이너. 15090 에서 프로메테우스 메트릭을, 15021 에서 헬스 체크를 노출한다.
여기서 자주 사고가 나는 지점이 있다. 라벨은 파드 생성 시점에만 작동한다. 이미 떠 있는 파드에는 아무 일도 일어나지 않으므로, 라벨을 붙였으면 롤아웃을 걸어 파드를 새로 만들어야 사이드카가 들어간다. "라벨을 붙였는데 왜 메시에 안 들어오죠"의 답은 열에 아홉 이것이다.
현장에서 만나는 모습
첫째, 사이드카의 값을 청구서로 본다. 파드당 대략 100MB 안팎의 메모리와 시작 시간 몇 초가 추가된다. 파드가 100개면 10GB 다. 그래서 사이드카 없이 노드 단위 ztunnel 이 L4 를, 네임스페이스 단위 waypoint 가 L7 을 맡는 Ambient 모드가 나왔고, 아예 다른 방향으로 eBPF 데이터패스(Cilium 같은)를 택해 kube-proxy 조차 없애는 구성도 흔해졌다. 메시를 도입한다는 것은 "이 비용을 내고 무엇을 사는가"를 답할 수 있다는 뜻이어야 한다.
둘째, 업그레이드는 재시작이다. 사이드카 버전을 올리려면 모든 파드를 다시 만들어야 한다. 수천 파드 클러스터에서는 이게 몇 시간짜리 작업이고, 그래서 메시 업그레이드 계획에는 반드시 롤아웃 순서와 창구 시간이 들어간다.
셋째, istioctl kube-inject 는 웹훅의 오프라인 판이다. 웹훅이 파드 생성 때 하는 일을 매니페스트 파일에 미리 적용해 결과를 보여 준다. GitOps 로 주입 결과를 고정하고 싶을 때, 그리고 지금처럼 주입 결과의 해부를 눈으로 확인하고 싶을 때 쓴다.
다음 실습에서 할 것
istioctl manifest generate 로 설치 매니페스트를 만들어 무엇이 들어 있는지 세어 보고, 메시 API 타입(CRD)을 클러스터에 등록한다. mesh-lab 에는 주입 라벨을, legacy 에는 붙이지 않아 대조군을 만든다. 그다음 픽스처 워크로드에 istioctl kube-inject 를 돌려 컨테이너가 몇 개가 되는지, 초기화 컨테이너가 무엇을 하는지 JSON 으로 정리한다.
미리 밝혀 둘 것이 있다. 이 실습 환경에는 진짜 Envoy 가 트래픽을 나르지 않는다. 파드는 Running 이 되지만 패킷은 흐르지 않고, kubectl exec 나 포트포워딩도 없다. 그래서 이 코스의 채점은 전부 매니페스트 작성과 istioctl analyze/validate 의 정적 검증을 본다. 실제 핸드셰이크와 메트릭은 읽기와 퀴즈로 다룬다. 설정이 맞는지 판단하는 눈은 이 방식으로도 충분히 길러지고, 현업에서도 사고의 절반은 패킷이 아니라 설정에서 난다.