ICA — 이스티오 인증 어소시에이트 · 서비스 메시와 Istio 아키텍처 · 이론
istiod 는 왜 하나로 합쳐졌나
한 줄 요약
Istio 는 "설정을 만드는 쪽(istiod)"과 "패킷을 만지는 쪽(Envoy)"을 완전히 분리했습니다. 이 분리 덕분에 컨트롤 플레인이 죽어도 트래픽은 흐르고, 반대로 컨트롤 플레인만 고쳐도 전체 메시의 행동이 바뀝니다.
왜 이게 필요했나
Istio 1.5 이전에는 Pilot(트래픽), Citadel(인증서), Galley(설정 검증), Mixer(정책·텔레메트리)가 각각 별도 파드로 떠 있었습니다. 문제는 이 넷이 서로를 호출하면서 생기는 운영 비용이었습니다. 구성요소 하나가 죽으면 어느 기능이 멈추는지 파악하기 어려웠고, 특히 Mixer 는 요청마다 컨트롤 플레인을 호출하는 구조라 데이터 경로의 지연과 장애가 컨트롤 플레인에 직결됐습니다.
그래서 1.5 에서 Pilot·Citadel·Galley 가 istiod 라는 단일 바이너리로 합쳐졌고, Mixer 는 1.8 에서 아예 제거됐습니다. 텔레메트리는 Envoy 안의 필터가 직접 생성하는 방식으로 바뀌었습니다. 요점은 "컴포넌트를 줄였다"가 아니라 데이터 경로에서 컨트롤 플레인 호출을 완전히 걷어냈다는 것입니다.
어떻게 동작하나
istiod 는 쿠버네티스 API 를 감시해 Service·Endpoint·Pod 와 Istio CRD 의 변화를 읽고, 그것을 Envoy 가 이해하는 설정으로 번역해 gRPC 스트림으로 밀어 넣습니다. 이 프로토콜이 xDS 입니다.
| API | 무엇을 내려보내나 |
| --- | --- |
| LDS | 리스너 — 어떤 포트를 어떤 프로토콜로 듣는가 |
| RDS | 라우트 — 어떤 요청을 어떤 클러스터로 보내는가 |
| CDS | 클러스터 — 목적지 그룹의 정의(LB, 서킷브레이커, TLS) |
| EDS | 엔드포인트 — 그 클러스터에 실제로 들어 있는 파드 IP |
| SDS | 인증서와 키 |
Istio 는 이 다섯을 ADS(Aggregated Discovery Service) 라는 하나의 gRPC 스트림으로 묶어 보냅니다. 이유는 대역폭이 아니라 순서입니다. 클러스터(CDS)가 정의되기 전에 엔드포인트(EDS)가 도착하면 Envoy 는 갈 곳 없는 주소를 받게 되고, 라우트(RDS)가 리스너(LDS)보다 먼저 오면 붙일 곳이 없습니다. 스트림이 하나면 순서가 보장되고, 설정이 원자적으로 갈아 끼워집니다.
Envoy 안에서 목적지는 이런 이름으로 존재합니다.
outbound|9080|v2|reviews.default.svc.cluster.local방향 포트 subset FQDNistioctl proxy-config cluster 에서 이 문자열을 읽을 줄 알면 절반은 끝난 것입니다. subset 자리가 비어 있으면 DestinationRule 이 없다는 뜻이고, 이름이 아예 없으면 그 서비스가 이 프록시의 시야 밖이라는 뜻입니다.
파드 안에서는 istio-init 컨테이너가 iptables 규칙을 심어 트래픽을 프록시로 꺾습니다. 인바운드는 15006, 아웃바운드는 15001 로 갑니다. 이때 UID 1337 의 트래픽만은 리다이렉트에서 제외되는데, 그 UID 가 바로 istio-proxy 자신이기 때문입니다. 제외하지 않으면 프록시가 내보낸 패킷이 다시 프록시로 돌아와 무한 루프가 됩니다. 그 밖에 15008(HBONE 터널), 15020(에이전트 통합 헬스·메트릭), 15021(헬스 체크), 15090(프로메테우스 메트릭)을 외워 두면 시험에서 포트 문제를 놓치지 않습니다.
마지막으로 중요한 성질 하나. istiod 가 전부 죽어도 이미 떠 있는 Envoy 는 마지막으로 받은 설정으로 계속 트래픽을 처리합니다. 멈추는 것은 새 설정 전파와 인증서 갱신이지 데이터 경로가 아닙니다. 그래서 istiod 장애는 "즉시 전면 장애"가 아니라 "시한부 상태"이고, 인증서 수명(기본 24시간)이 실질적인 타이머가 됩니다.
현장에서 만나는 모습
저자의 홈랩은 7노드(cp-1/2/3 + gpu-a/b/c/d), 쿠버네티스 v1.34.10, containerd 1.7.27, 커널 6.14 위에 Cilium 1.20.1 로 서 있습니다. 사이드카 메시는 올라가 있지 않은데, 이 대비가 오히려 Istio 를 이해하는 데 도움이 됩니다.
이 클러스터는 kubeadm init --skip-phases=addon/kube-proxy 로 kube-proxy 를 처음부터 설치하지 않고 세웠습니다. 한 번이라도 돈 kube-proxy 는 노드에 KUBE-SERVICES / KUBE-SVC-* / KUBE-SEP-* 체인을 새겨 놓고, DaemonSet 을 지워도 그 규칙은 남아 eBPF 데이터패스와 충돌합니다. 실측 결과 kube-proxy 파드 0개, iptables KUBE- 체인 0개였습니다.
여기서 배울 점은 Istio 에도 똑같이 적용됩니다. 사이드카 주입은 파드 네트워크 네임스페이스 안에 iptables 규칙을 새기는 일이고, 주입 라벨을 나중에 지워도 이미 뜬 파드의 규칙은 파드를 재시작하기 전까지 그대로 남습니다. "라벨은 지웠는데 왜 아직 프록시를 타지?"라는 질문의 답이 이것입니다. 설정은 선언적이지만 노드와 파드에 남는 흔적은 명령적입니다.
다음 퀴즈에서 확인할 것
이 모듈은 개념만 다룹니다. 퀴즈로 아키텍처 감각을 점검한 뒤, 다음 모듈에서 VirtualService 와 DestinationRule 을 직접 써서 위에서 본 outbound|포트|subset|FQDN 이 어떻게 만들어지는지 손으로 확인합니다.