Istio 심화 — 왜 그렇게 흐르는가 · 네 리소스의 역할 · 이론
무엇이 무엇을 담당하나
한 줄 요약
VirtualService 는 "어디로 보낼지" 를, DestinationRule 은 "보낸 뒤 어떻게 다룰지" 를 정한다. 카나리 배포에 둘 다 필요한 이유가 이것이다.
왜 이게 필요했나
Istio 를 처음 쓰면 대부분 이 실수를 한다.
# VirtualService 만 쓴 카나리 — 동작하지 않는다http: - route: - destination: { host: shop, subset: v1 } weight: 90 - destination: { host: shop, subset: v2 } weight: 10subset: v1 이 무엇을 가리키는지 아무도 모른다. 서브셋은 DestinationRule 에서 정의한다.
# DestinationRule — 서브셋의 정의spec: host: shop subsets: - name: v1 labels: { version: v1 } - name: v2 labels: { version: v2 }이제야 v1 이 version: v1 라벨이 붙은 파드를 뜻하게 된다. 앞 코스에서 본 Envoy 용어로 옮기면 — DestinationRule 의 subset 이 클러스터를 만들고(outbound|8080|v1|shop...), VirtualService 의 weight 가 라우트의 가중치가 된다.
네 리소스
| 리소스 | 하는 일 | Envoy 로는 |
|---|---|---|
| Gateway | 메시 바깥에서 들어오는 트래픽의 입구(포트·호스트·TLS) | Listener |
| VirtualService | 어떤 요청을 어디로 보낼지(매칭·가중치·재시도·타임아웃) | Route |
| DestinationRule | 목적지를 어떻게 다룰지(서브셋·LB·커넥션풀·이상치·TLS) | Cluster |
| ServiceEntry | 메시가 모르는 외부 서비스를 목록에 등록 | Cluster + Endpoint |
Gateway 는 입구만 연다. Gateway 하나로는 트래픽이 흐르지 않는다 — 그 Gateway 를 gateways: 로 참조하는 VirtualService 가 있어야 비로소 라우팅이 생긴다. 이것도 흔한 함정이다.
mTLS 는 언제 걸리나
PeerAuthentication 이 mode 를 정한다.
| mode | 뜻 |
|---|---|
| PERMISSIVE | 평문도 mTLS 도 받는다 (기본값, 마이그레이션용) |
| STRICT | mTLS 만 받는다 |
| DISABLE | mTLS 안 씀 |
기본이 PERMISSIVE 인 이유는 사이드카가 없는 파드가 남아 있을 수 있어서다. 그래서 "Istio 를 깔았으니 암호화된다" 는 말은 틀렸다. STRICT 로 바꾸기 전까지는 평문도 그대로 통한다.
STRICT 로 바꿀 때 흔히 깨지는 것: 사이드카가 없는 파드(예: Job), 헬스체크를 보내는 kubelet, 그리고 메시 밖의 모니터링. kubelet 은 Istio 가 프로브 경로를 우회시켜 처리하지만, 직접 만든 체크 스크립트는 깨진다.
흔한 착각
"Istio 를 넣으면 관측성이 생긴다" — 사이드카가 내는 지표는 L7 요청 지표(요청 수·지연·상태코드)다. 애플리케이션 안에서 무슨 일이 있었는지는 여전히 모른다. 트레이스도 마찬가지로, 사이드카는 스팬을 만들지만 애플리케이션이 헤더를 이어 주지 않으면 체인이 끊긴다. 코드를 안 고쳐도 되는 것은 아니다.
실무에서 진짜 중요한 것
설정이 의도대로 갔는지는 프록시에게 묻는다.
istioctl analyze # 정적 검사 — 서브셋 미정의 같은 것을 잡는다istioctl proxy-status # 각 사이드카가 최신 설정을 받았나(SYNCED)istioctl proxy-config route <pod> # 실제로 받은 라우트istioctl proxy-config cluster <pod> --fqdn shop.default.svc.cluster.localproxy-status 가 STALE 이면 설정이 아직 안 갔다는 뜻이고, 그때 YAML 을 아무리 봐도 소용없다.