[ 순서 ]
- LDS : Envoy가 "어떤 IP:Port"에서 "어떤 프로토콜"로 트래픽을 수신할지 정의
- RDS : 수신된 "요청의 경로/헤더"를 보고 어떤 Cluster로 보낼지, "타임아웃/리트라이 등 라우팅 규칙" 정의
- CDS : 대상 Cluster의 "LB 알고리즘, 서킷 브레이커, 커넥션 풀 등" 정책 정의
- EDS : 해당 Cluster에 속하는 "실제 Pod의 IP:Port 목록"을 정의
- SDS : mTLS에 사용되는 "인증서"와 "private key"를 Envoy에 전달
[ 위 순서 보장 ]
- ADS : 위 xDS들을 하나의 gRPC 스트림으로 묶어서 "순서를 보장하며 전달"하는 통합 채널
ADS가 없으면 LDS, RDS, CDS, EDS가 "각각의 별도 gRPC 스트림"으로 전달되는데, 이러면 RDS가 CDS보다 먼저 도착해서 "이 요청을 order-svc cluster로 보내라"는 라우팅 규칙은 있는데 아직 해당 cluster 정의가 없는 타이밍 이슈가 발생 가능

[ 한 문장 정의 ]
istiod가 K8s 리소스를 읽어서 xDS 리소스를 만들고, xDS API를 통해 Envoy에 전달하면,
Envoy는 그 설정대로 트래픽을 전달함.
[ 전체 관계 ]
K8s/Istio Resource -> istiod(번역기) -> xDS(설정 전달 API) -> Envoy(실행기)
"무엇을 원하는지" "번역" "전달" 실행
(선언적 의도) (의도 -> 설정 변환) (설정 배달) (설정대로 트래픽 처리)
[ Control Plane - 설정 생정 & 배포 ]
1. K8s API Server
- 사용자 kubectl apply or Pod 스케일링 등
- "etcd"에 저장 후 watch 중인 컴포넌트에 이벤트 전파
- 전파 대상 :
|- (a) Istio CR - VirtualService, DestinationRule, Gateway ....
|- (b) K8s Native - Service, Endpoint, Pod, Node
|
| informer watch (병렬)
|
▼
2. Istiod 내부 - 두 갈래 수집
|
|- Config Controller ( <- 1-a Istio CR 담당 )
| - 스미카 검증
| - model.Config 내부 모델로 변환
| - (구 Galley 역할)
|
|- Service Discovery ( <- 1-b K8s Native 담당 )
| - 서비스 레지스트리 갱신
| - FQDN, 포트, 프로토콜, Pod IP 목록 관리
| - ServiceEntry 외부 서비스도 여기서 관리
|
|
|- 둘 중 어느 쪽이든 변경 감지 시
-> xDS Server에 PushRequest 발행 ("push 필요")
|
|
▼
3. Debounce (기본 100ms)
- 짧은 시간 내 여러 변경을 하나로 묶음
- 불필요한 중복 push 방지
|
|
▼
4. PushContext 생성 (설정 스냅샷, 이는 xDS Server가 "만듦")
- Config Controller 내부 모델 + Service Discovery 레지스트리
- 합쳐서 "이 시점 전체 메시 상태" 확정
|
|
▼
5. xDS Server - 변환 + Push
- PushContext 기반, 각 Envoy별(label 기준) 설정 생성
|
|
|- LDS <- VS의 hosts/port -> 리스너 규칙
|- RDS <- VS의 match/route -> 라우팅 규칙, weight 분할
|- CDS <- DR의 trafficPolicy -> LB, connection pool, circuit breaker
|- ECS <- Endpoints -> 실제 Pod IP:port 목록
|- SDS <- Citadel CA 인증서 -> mTLS용
|
|-> ADS gRPC 스트림으로 각 Envoy에 push
|-> Envoy는 hot reload (재시작 없음)
═══════════════════════════════════════════════
┌─────────────── Pod A (productpage) ───────────────┐
│ │
│ App Container Sidecar Container │
│ ┌───────────┐ ┌──────────────────┐ │
│ │ │ │ Envoy (15001) │ │
│ │ App │─ 요청 ─→│ │──────────→ 밖으로 (Pod B)
│ │ (8080) │ │ 6. Listener │ │
│ │ │ 실제로는│ 7. Route 매칭 │ │
│ │ │ 직접 안감│ 8. Cluster/LB │ │
│ └───────────┘ └──────────────────┘ │
│ │ ▲ │
│ └── iptables NAT ───────┘ │
│ (앱은 직접 보낸 줄 알지만 │
│ 실제로는 Envoy로 redirect됨) │
└─────────────────────────────────────────────────────┘
[ Data Plane - 실제 트래픽 처리 ]
1 단계. 앱 컨테이너가 요청 발생
- Pod A의 앱이 Pod B의 서비스로 "HTTP" 요청을 전송
EX) "<http://service-b:8080/api>"
2 단계. Source 측 Envoy가 가로챔(Outbound)
- Pod A 내부의 "iptables 규칙(init container인 istio-init이 설정)"이 아웃바운드 트래픽을
Envoy(15001 포트)로 리다이렉트
- 이 단계에서 Source Envoy가 하는 일은 아래와 같음.
1. Istiod로부터 받은 "xDS 설정"을 기반으로 "목적지 결정) - LDS
2. VirtualService, DestinationRule 적용 (라우팅, 재시도, 타임아웃, LB) - RDS & CDS
3. 해당 클러스터에 속한 Pod IP 목록을 확인하고, LB 정책에 따라 최종 목적지 정함 - EDS
4. 대상 Pod B의 Envoy와 mTLS 핸드셰이크 적용
5. 요청을 암호화해서 전송
3 단계. 네트워크 전송
- mTLS로 암호화된 트래픽이 "Pod A -> Pod B"로 전달
- 이 구간은 "SPIFFE 기반 인증서"로 양쪽 신원이 검증된 상태
4 단계. Destination 측 Envoy가 수신(Inbound)
- Pod B의 iptables가 인바운드 트래픽 Envoy(15006 포트)로 리다이렉트
- Destination Envoy가 하는 일은 아래와 같음.
1. mTLS 복호화
2. AuthorizaitonPolicy 평가 (요청 수락 & 거부)
3. 메트릭/트레이싱 데이터 수집
4. 허용된 요청을 localhost의 앱 컨테이너로 전달
5. 앱이 응답 처리
- Pod B의 앱이 응답을 보내면 역방향으로 동일한 과정
(B의 Envoy -> 암호화 -> A의 Envoy -> 복호화 -> A의 앱)
짧은 요약 - VirtualService 변경
[ Control Plane ]
Config Controller가 변경 감지
-> PushRequest 발행(각 Pilot이 발행)
-> Debouncd (100ms 대기, 추가 변경 있으면 합침)
-> xDS Server가 PushContext 생성 (두 쪽 데이터를 자기가 합침)
-> xDS 변환 -> Envoy Push (이때 각 DS는 "하나의 ADS gRPC 스트림으로 push")
[ Data Plane ]
요청 In
-> LDS: Listener가 IP:PORT 배칭
-> Filter Chain 선택
-> Network Filter (HCM(HttpConnectionManager) 실행)
-> RDS: Host/Path/Header 기반 Route 배칭
-> CDS: 선택된 Clutser의 정책 적용 (LB, circuit breaker, connection pool)
-> EDS: 실제 Pod IP:port 선택
-> mTLS면 SDS 인증서로 TLS 핸드셰이크
-> Target Pod의 inbound Envoy (15006)
-> AuthorizationPolicy 검사
-> App Container 전달