Istiod xDS API 흐름

[ 순서 ]
- 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 정의가 없는 타이밍 이슈가 발생 가능

xDS API → Envoy Proxy

그림 설명(API 요청 → Envoy Proxy 설정)

image.png

요약

[ 한 문장 정의 ]
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 전달