externalTrafficPolicy
Hermaeus Mora ·
외부 컨슈머가 istio ingress gateway를 통해 클러스터의 rabbitMQ에 붙는 상황을 가정해보자. ingress gateway 파드는 총 6개의 노드 중 nodepool-1, nodepool-2 2대에 떠 있다. 와중에 nodepool-6 노드가 다운되었다. 그런데 외부 컨슈머에서 ChannelInvalidStateError: No active transport in channel 에러가 발생한다. 왜 ingress gateway 파드가 떠있지도 않은 노드가 죽었다고 해서 컨슈머 에러가 날까?
externalTrafficPolicy가 Cluster로 되어 있기 때문이다. 이 경우 모든 워커 노드가 LB 타깃이 되고, 게이트웨이 파드가 없는 노드도 트래픽을 받아 파드가 있는 노드로 전달한다. 이때 외부 컨슈머의 AMQP 연결은 LB가 선택한 특정 노드를 계속 경유하는 장기 TCP 연결이다. 그래서 게이트웨이 파드와 무관한 노드가 죽어도, 그 노드를 경유하던 연결은 끊긴다.
이를 Local로 바꾸면 게이트웨이 파드가 실제로 떠 있는 노드만 트래픽을 받는다. 쿠버네티스가 healthCheckNodePort를 할당하고, 로컬 엔드포인트가 없는 노드는 이 포트에서 503을 반환해 LB 로테이션에서 제외되기 때문이다. 결과적으로 노드 장애나 축소의 영향 범위가 게이트웨이 노드로 한정된다.
추가적으로 Local로 바꿀 경우 반드시 hpa minReplicas를 2 이상으로 설정해야 한다. replica 1이면 파드 재배치 때 유효 타깃이 0이 되는 공백이 생긴다. 또한 파드가 한 노드에 몰리는 경우에도 노드 다운 시 공백이 생기므로 topologySpreadConstraints를 같이 설정해야 한다.