Incident Library

IL-0361 SEEK · 2021-12-10 (게시일)awsnetworking

VPC 피어링을 Transit Gateway 로 옮기던 중 seek.com.au 의 구직 검색이 16분 동안 오류를 냈다

SEEK 는 AWS 의 VPC 사이 트래픽 흐름을 바꾸는 마이그레이션을 하고 있었다. VPC 피어링은 VPC 쌍마다 연결이 하나씩 필요해서 VPC 가 늘면 연결 수가 n² 으로 늘어난다. SEEK 는 모든 VPC 를 Transit Gateway 하나에 붙여 연결 수를 n 으로 줄이려 했다. 중단 없이 옮기려고 세 단계를 짰다. 두 VPC 를 경로 없이 Transit Gateway 에 붙이고, 첫 VPC 의 라우팅 테이블을 Transit Gateway 로 바꾸고, 그다음 둘째 VPC 의 라우팅 테이블을 바꾸는 순서였다. 둘째 단계와 셋째 단계 사이에는 VPC 를 나가는 경로와 들어오는 경로가 달라진다.

SEEK 가 마이그레이션 전에 몰랐던 것은 두 경로의 MTU 가 다르다는 점이었다. MTU 는 네트워크 장비가 다룰 수 있는 가장 큰 IP 패킷의 바이트 크기다. 같은 리전 안 피어링 연결의 MTU 는 9001 이고 Transit Gateway 의 MTU 는 8500 이며, AWS 의 ENI 도 기본 MTU 가 9001 로 보였다. Transit Gateway 는 8500 바이트보다 큰 패킷을 버린다. FRAG_NEEDED ICMP 응답을 만들지 않으므로 경로 MTU 탐색을 지원하지 않고, 모든 패킷에 MSS 클램핑을 강제한다. MSS 는 TCP 연결의 양쪽이 각자 받고 싶은 가장 큰 TCP 세그먼트 크기를 알리는 헤더 값이다. MSS 클램핑은 중간 장비가 SYN 이나 SYN ACK 의 MSS 를 자기 MTU 에 맞게 고쳐 써서 상대가 작은 패킷을 보내게 하는 방식이다.

TCP 는 항상 'Don't Fragment' 비트를 켜므로 라우터가 패킷을 쪼갤 수 없었다. Transit Gateway 는 ICMP 'Fragmentation Needed' 를 보내지 않으므로 경로 MTU 탐색도 동작하지 않았다. MSS 는 협상이 아니라 양쪽이 각자 알리는 값이어서, 클램핑은 연결 양쪽의 패킷이 모두 클램핑될 때만 통한다. 이번에는 VPC A 가 보낸 SYN 이 피어링 연결을 지나 MSS 9001 그대로 VPC B 에 닿았고, VPC B 가 보낸 SYN ACK 만 Transit Gateway 에서 8500 으로 클램핑됐다. 그래서 VPC A 는 8500 바이트 이하로 보냈지만 VPC B 는 9001 바이트 패킷을 보냈고, Transit Gateway 가 이 패킷을 버렸다. 이때 옮기던 것이 seek.com.au 검색 트래픽을 처리하는 피어링 연결이었고, 결과가 많은 검색은 큰 패킷 여러 개를 보내야 했다. SEEK 는 검색이 동작하지 않는 것을 꽤 빨리 알아채고 마이그레이션을 롤백했으며, 장애는 16분 이어졌다. 그 뒤 같은 구성을 다시 만들고 패킷을 캡처해 원인을 확인했다.

심각도
–
영향 범위
Job searches on seek.com.au returned errors
영향 사용자
some users searching for jobs on seek.com.au
지역
–
감지까지
–
복구까지
16m

증상

2021년 5월 seek.com.au 에서 구직 검색을 하던 일부 사용자가 오류를 받았고, 장애는 16분 이어졌다. SEEK 는 검색 트래픽을 처리하던 피어링 연결을 Transit Gateway 로 옮기던 중이었고, 검색이 동작하지 않는다는 것을 꽤 빨리 알아챘다.

‘멜버른의 모든 일자리’ 같은 검색은 결과가 많아서 응답을 9001 바이트 단위의 큰 패킷 여러 개로 나눠 보내야 했다. 이런 큰 패킷이 상대에게 닿지 않았다.

Transit Gateway 는 MTU 8500 보다 큰 패킷을 조용히 버리고 ICMP 'Fragmentation Needed' 패킷을 보내지 않는다. 버려진 패킷을 보여 주는 지표도 없었다. SEEK 는 한 VPC 쪽 Transit Gateway 어태치먼트의 'packets in' 수가 다른 VPC 쪽 어태치먼트의 'packets out' 수의 약 두 배인 것을 Transit Gateway 지표에서 보고서야 패킷이 버려지고 있음을 알았다.

SEEK 는 EC2 인스턴스, Transit Gateway, 피어링 연결 구성을 똑같이 만들어 원인을 확인했다. VPC A 에서 VPC B 의 머신이 http 로 제공하는 큰 파일을 요청하면 요청이 멈췄다. 양쪽에서 패킷을 캡처해 보니 VPC B 의 머신이 보낸 9001 바이트 패킷은 VPC A 의 머신에 끝내 도착하지 않았고, TCP 재전송이 끝없이 이어졌다.

증상 오류율 상승패킷 손실간헐적 타임아웃

원인

촉발
SEEK 는 VPC 피어링 연결에서 Transit Gateway 로 옮기는 절차의 둘째 단계로 첫 VPC 의 라우팅 테이블만 Transit Gateway 를 쓰게 바꿨다. 이 상태에서는 VPC A 에서 나가는 패킷은 피어링 연결로, VPC B 에서 나가는 패킷은 Transit Gateway 로 가서 오가는 경로가 달라졌다.

감지

마이그레이션 도중 SEEK 는 검색이 동작하지 않는다는 것을 꽤 빨리 알아챘다.

조치

후속 조치

교훈

SEEK 는 피어링 연결과 Transit Gateway 의 MTU 가 다르다는 중요한 정보를 마이그레이션 전에 알지 못했다. Transit Gateway 가 큰 패킷을 알리지 않고 버린다는 사실은 AWS 의 Transit Gateway 할당량 문서에 적혀 있었지만, SEEK 는 이것이 할당량이라기보다 더 찾기 쉬운 곳에 있어야 할 기본 정보라고 봤다. SEEK 는 이 장애로 MTU, MSS, AWS 관리형 네트워크 장비의 세부 동작을 많이 배웠다. 장애에서 얼마나 배우는지는 장애의 심각도보다 근본 원인을 이해하려는 호기심과 의지에 달려 있다고 보았다.

출처

관련 사례

–

내 클러스터에도 있는지 확인하기

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: 트랜짓 게이트웨이와 네트워크 연결 장비. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.