Published on

EKS Pod간 통신만 실패? MTU·PMTUD 10분 진단

Authors

서로 다른 서비스의 Pod는 정상 기동인데 Pod 간 통신만 간헐적으로 끊기거나(특히 큰 응답/업로드/스트리밍), curl은 연결되지만 본문이 멈추거나, gRPC/HTTP2가 유독 취약하게 실패하는 경우가 있습니다. 이런 증상은 보안그룹/NetworkPolicy처럼 “아예 막힘”이 아니라 작은 패킷은 통과하고 큰 패킷에서만 깨지는 패턴을 띠는 경우가 많고, 그때 1순위로 의심해야 할 것이 MTU 불일치PMTUD(Path MTU Discovery) 실패입니다.

이 글은 “EKS에서 Pod간 통신만 실패” 상황을 10분 안에 진단하기 위한 절차를 정리합니다. VPC CNI(aws-node), 노드/ENI MTU, 터널/오버레이, ICMP 차단(Frag Needed) 등 실무에서 자주 만나는 원인과 즉시 적용 가능한 완화책까지 다룹니다.

> 참고: Pod가 뜨는데 트래픽이 0인 케이스(정책/보안그룹/CNI) 전반은 EKS Pod는 뜨는데 트래픽 0 - NetPol·SG·CNI 10분 진단도 함께 보면 교차검증에 도움이 됩니다.

1) MTU/PMTUD 문제의 전형적 증상

다음 패턴이면 MTU/PMTUD를 최우선으로 보세요.

  • 작은 요청은 성공: curl http://svc는 200 OK
  • 큰 응답/바디에서 멈춤: 파일 다운로드, JSON이 큰 응답, 업로드, gRPC streaming에서 hang/timeout
  • 간헐성: 어떤 노드 조합/가용영역/특정 경로에서만 재현
  • 재시도하면 성공: TCP 세그먼트 크기/경로 변화로 운 좋게 통과
  • 로그 단서
    • 애플리케이션: context deadline exceeded, upstream reset, connection timed out
    • 커널/노드: Frag needed and DF set(보이기도 하고 안 보이기도 함)

왜 Pod-to-Pod만? EKS에서 Pod 트래픽은 노드의 ENI/VPC 라우팅과 CNI 설정에 의해 경로가 결정됩니다. 특정 경로(노드 간, AZ 간, 특정 ENI/인스턴스 타입)에서만 실제 MTU가 줄어들거나, ICMP가 차단되어 PMTUD가 동작하지 않으면 “큰 패킷만” 깨집니다.

2) 10분 진단 플로우(요약)

아래 순서대로 하면 빠릅니다.

  1. 재현: Pod A → Pod B로 “큰 페이로드” 전송 테스트
  2. MTU 확인: Pod/노드의 인터페이스 MTU 확인(eth0, eni, veth)
  3. PMTUD 확인: DF(Do not fragment) 상태에서 ping으로 경로 MTU 탐색
  4. ICMP 차단 여부: Frag Needed(ICMP Type 3 Code 4) 드롭 여부 확인
  5. 즉시 완화: TCP MSS clamping 또는 MTU 조정(가능한 범위 내)

3) 1분 재현: “큰 패킷에서만” 실패하는지 확인

3.1 테스트용 Pod 실행

kubectl run -it --rm netshoot \
  --image=nicolaka/netshoot \
  --restart=Never -- bash

상대 Pod(B)의 IP를 확인합니다.

kubectl get pod -o wide
# 또는
kubectl get endpoints <svc-name>

3.2 큰 바디 전송 테스트(HTTP)

예: Pod B에 간단한 echo 서버가 있다면, Pod A에서 큰 바디를 보내봅니다.

# 200KB 전송(환경에 맞게 늘려보기)
head -c 200000 /dev/urandom | \
  curl -sS -m 5 -X POST --data-binary @- http://<POD_B_IP>:8080/echo -v
  • 작은 바디(1KB)는 성공, 200KB에서 hang/timeout이면 MTU/PMTUD 가능성이 큽니다.

3.3 TCP 레벨로 확인(iperf3)

서버 Pod(B):

kubectl run -it --rm iperf-s \
  --image=networkstatic/iperf3 --restart=Never -- \
  -s

클라이언트 Pod(A):

kubectl run -it --rm iperf-c \
  --image=networkstatic/iperf3 --restart=Never -- \
  -c <POD_B_IP> -t 5 -P 1

여기서도 연결은 되는데 throughput이 0에 가깝거나 중간에 멈춘다면 “경로 MTU 문제”일 수 있습니다.

4) MTU 확인: Pod/노드에서 어디가 1500/9001/1450인가

EKS 기본 VPC 네트워크는 보통 1500 MTU가 정상입니다. 하지만 다음 상황에서 MTU가 줄어들 수 있습니다.

  • 노드가 터널(예: VXLAN, WireGuard 등) 을 쓰는 CNI로 변경
  • 노드/ENI에 Jumbo frame(9001) 을 섞어 썼는데 경로 어딘가가 1500
  • 특정 보안장비/가상 어플라이언스 경유
  • 노드 OS/AMIs에서 MTU 설정이 일관되지 않음

4.1 Pod 내부에서 MTU 확인

ip link show eth0
ip route

4.2 노드에서 MTU 확인

노드에 접속(SSM 등) 후:

ip link | egrep -A2 'eth0|eni|cali|flannel|vxlan|geneve'

Bottlerocket처럼 SSH가 막힌 환경이라면 SSM으로 접근하는 방법을 정리한 글(EKS Bottlerocket 노드 SSH 없이 SSM으로 접속·디버깅)을 참고해 노드 네트워크를 직접 확인하는 것이 가장 빠릅니다.

4.3 aws-node(amazon-vpc-cni) 설정 확인

kubectl -n kube-system get ds aws-node -o yaml | sed -n '1,200p'
kubectl -n kube-system describe ds aws-node | sed -n '1,200p'

환경변수에 MTU 관련 설정이 들어간 경우가 있습니다(클러스터/버전에 따라 다름). 또한 CNI가 인스턴스 타입별 추천 MTU를 적용하는지, 커스텀 설정이 있는지 확인합니다.

5) PMTUD 확인: DF ping으로 “경로 MTU”를 찾아라

PMTUD는 “너무 큰 패킷이면 중간 라우터가 ICMP로 ‘더 작게 보내라(Frag Needed)’를 알려주고, 송신자가 MSS/세그먼트 크기를 줄이는” 메커니즘입니다.

문제는 ICMP Type 3 Code 4가 중간에서 차단되면, 송신자는 줄여야 한다는 신호를 못 받아서 큰 패킷을 계속 보내고, 결과적으로 TCP가 멈춘 것처럼 보입니다.

5.1 Pod에서 DF ping 테스트

리눅스 ping은 -M do로 DF를 강제할 수 있습니다.

# 1472 payload + 28(IP+ICMP 헤더) = 1500 MTU 가정
ping -c 3 -M do -s 1472 <POD_B_IP>
  • 성공하면 최소한 1500 경로 MTU는 통과 가능
  • 실패하면 값을 줄여가며 경로 MTU를 찾습니다.
for s in 1472 1464 1452 1440 1400 1360 1300 1200; do
  echo "== size $s =="
  ping -c 1 -M do -s $s <POD_B_IP> || true
done

어떤 지점부터 성공한다면 그 값+28이 대략적인 경로 MTU입니다.

5.2 실패 유형 해석

  • Frag needed and DF set가 뜨면: 경로 MTU가 더 작다는 뜻(원인: MTU 불일치)
  • 그냥 100% packet loss로만 보이면: ICMP 응답/에러가 차단됐을 가능성(원인: PMTUD 실패)

EKS/VPC 내부에서 ICMP가 일반적으로 완전히 막히는 경우는 드물지만, 노드 보안 정책(iptables/nftables), eBPF 정책, 서드파티 CNI/보안 에이전트, 중간 프록시/방화벽이 개입하면 충분히 발생합니다.

6) tcpdump로 3분 확정: “Frag Needed”가 오나, 드롭되나

Pod 또는 노드에서 tcpdump를 뜹니다(권한 필요).

6.1 Pod 네임스페이스에서 캡처(가능할 때)

tcpdump -ni any host <POD_B_IP> and \(icmp or tcp\)

6.2 노드에서 캡처(권장)

# 인터페이스는 환경에 맞게(eth0, eni+, vxlan 등)
tcpdump -ni eth0 host <POD_B_IP> and \(icmp or tcp\)

관찰 포인트:

  • 큰 전송 시도 시 ICMP Destination Unreachable (Fragmentation needed)가 돌아오는가?
  • 돌아오는데도 송신이 줄지 않는가(커널 설정/오프로드/정책 이슈)?
  • 아예 ICMP가 보이지 않는가(중간에서 차단)?

7) 원인별 해결책(안전한 순서)

7.1 (가장 흔함) 경로 MTU가 1500보다 작다 → MTU를 맞추거나 MSS를 clamp

근본 해결은 “경로에서 허용하는 MTU로 일관되게 맞추는 것”입니다. 다만 운영 중 즉시 조치가 필요하면 TCP MSS clamping이 빠른 완화책입니다.

옵션 A: MSS clamping(완화책)

노드에서 iptables로 SYN 패킷의 MSS를 경로 MTU에 맞게 낮춥니다.

# 예: 경로 MTU가 1450이라면 MSS는 대략 1410(=1450-40) 수준으로
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN \
  -j TCPMSS --set-mss 1410
  • 장점: 즉시 효과, 애플리케이션 수정 불필요
  • 단점: 노드 재부팅/업데이트 시 유지 필요, 성능 영향 가능

옵션 B: 실제 MTU 정합(근본)

  • 노드/ENI/오버레이/보안장비 포함 전체 경로에서 MTU를 일치
  • 특정 CNI(터널) 사용 시 오버헤드만큼 MTU를 낮춤(VXLAN/Geneve 등)

EKS 기본 VPC CNI라면 “갑자기 MTU가 줄어드는” 케이스는 보통 중간 경유 장비 또는 커스텀 네트워크 구성이 원인입니다.

7.2 PMTUD가 깨진다 → ICMP Type 3 Code 4 허용

PMTUD가 제대로 동작하려면 네트워크가 다음을 막지 않아야 합니다.

  • ICMP Destination Unreachable / Fragmentation Needed

점검 위치:

  • 노드의 iptables/nftables에서 ICMP drop 룰
  • eBPF/보안 에이전트 정책
  • (만약 있다면) 중간 방화벽/가상 어플라이언스의 ICMP 정책

운영 정책상 ICMP를 전부 막아야 한다면, 현실적인 대안은 MSS clamping 또는 애플리케이션 레벨에서 메시지 크기 제한(예: gRPC max message size)을 병행하는 것입니다.

7.3 “Pod는 뜨는데 트래픽이 0” 유형과 구분

MTU/PMTUD는 보통 “작은 건 되는데 큰 것만 안 됨”입니다. 반면 아래는 “아예 통신이 안 됨”으로 나타납니다.

  • NetworkPolicy
  • Security Group/NACL
  • CNI 초기화 실패
  • 라우팅/엔드포인트 문제

이 경우는 위에서 링크한 네트워크 10분 진단 글(EKS Pod는 뜨는데 트래픽 0 - NetPol·SG·CNI 10분 진단)의 체크리스트로 빠르게 갈라타는 것이 좋습니다.

8) 실전 체크리스트(복사해서 쓰기)

8.1 증상 확인

  • 작은 요청(1KB)은 성공, 큰 요청(100KB~수MB)에서 hang/timeout
  • 특정 노드/특정 AZ 조합에서 재현
  • gRPC/HTTP2 스트리밍에서 더 잘 터짐

8.2 MTU/PMTUD 테스트

  • ip link show로 Pod/노드 MTU 확인
  • ping -M do -s 1472 <peer> 성공/실패 확인
  • 실패 시 -s 값을 낮춰 경로 MTU 추정
  • tcpdump로 ICMP Frag Needed가 보이는지 확인

8.3 조치

  • ICMP Frag Needed 차단 해제(가능하면)
  • 임시로 MSS clamping 적용
  • 근본적으로 MTU 정합(터널 오버헤드 고려)

9) 마무리: “연결은 되는데 데이터가 안 온다”면 MTU부터

EKS에서 Pod-to-Pod 통신 장애를 볼 때, 보안그룹/NetPol만 먼저 의심하면 시간을 많이 씁니다. 연결은 성립하지만 큰 데이터에서만 멈춘다는 단서가 있다면, MTU/PMTUD는 가장 비용 대비 효과가 큰 1차 진단 포인트입니다.

추가로, 노드에 직접 들어가 패킷 캡처와 인터페이스 MTU를 확인하는 것이 가장 확실합니다. Bottlerocket 등 SSH가 제한된 노드라면 EKS Bottlerocket 노드 SSH 없이 SSM으로 접속·디버깅 방식으로 접근 경로를 먼저 확보해두면, 이런 네트워크 이슈를 “감”이 아니라 “증거”로 빠르게 끝낼 수 있습니다.