Incident Library

IL-0455 Woowa Brothers · 2020-11-11 (게시일)networkingaws

AWS 의 A 서비스가 NAT Gateway 와 IDC L4 를 거쳐 온프레미스 B 서비스를 부를 때 주말마다 5xx 오류가 늘었다

우아한형제들에서 AWS EC2 에 있는 웹 애플리케이션 A 서비스는 온프레미스 환경의 웹 애플리케이션 B 서비스와 REST API 로 통신한다. 요청은 A 서비스에서 NAT Gateway, 인터넷, IDC, 방화벽, L4 를 차례로 거쳐 B 서비스로 간다. 트래픽이 많은 주말마다 A 서비스의 5xx 오류와 B 서비스의 L4 세션 카운트가 함께 올라 사용자 요청이 실패했다. 팀은 매번 A 서비스 인스턴스를 늘리고 교체해 장애를 넘겼지만 원인은 몰랐다. 근본 원인을 찾으려고 SRE 팀, 클라우드인프라개발팀, 도메인팀, 정보보안팀이 함께 나섰다.

B 서비스의 패킷 덤프에는, NAT Gateway 가 보낸 SYN 에 B 서비스 서버가 잘못된 sequence number 의 ACK 만 보내고 요청자가 SYN 을 다시 보내는 흐름이 있었다. 팀은 출발지, 목적지, 네트워크 구간에 가설을 세워 차례로 시험했다. 커널 튜닝과 서버 증설로는 증상이 그대로였다. 반면 A 서비스가 connection pool 을 쓰거나, VPN 으로 NAT 와 인터넷 구간을 빼거나, L4 를 빼면 재현되지 않았다. L4 는 DAM, 곧 Direct access mode 가 켜져 있으면 Client Port 를 변환하는데, 실제로 쓰는 포트 범위가 알고 있던 2000~65000 과 달랐다.

팀은 AWS 가용 영역 A, B, C 를 NAT Gateway 와 1:1 로 짝지어 부하 테스트를 했다. B 서비스 테스트 서버에 TIME_WAIT 가 약 42,000개 쌓이자 A 서비스에서 5xx 오류가 났다. L4 는 NAT Gateway IP 하나당 약 14,000개의 포트만 할당했고, NAT Gateway 3개에서는 14,000 × 3 = 42,000 이 한계였다. 팀은 재발을 막으려고, A 서비스와 NAT Gateway 를 거쳐 AWS 와 IDC 사이를 오가는 다른 서비스들이 connection pool 을 쓰도록 바꾸기로 했다.

심각도
–
영향 범위
API requests from service A in AWS to on-premises service B failed with 5xx errors during weekend traffic, and user requests failed
영향 사용자
–
지역
–
감지까지
–
복구까지
–

증상

AWS 에 있는 A 서비스가 온프레미스 환경의 B 서비스로 보내는 API 요청에서 5xx 오류가 늘고 사용자 요청이 실패했다. 같은 때 B 서비스 앞단 L4 의 세션 카운트도 올라갔다.

A 서비스 인스턴스를 늘리자 5xx 오류와 L4 세션 카운트는 줄었지만 평소 수치로 돌아가지는 않았다. 인스턴스를 교체하고 나서야 평소로 돌아왔다. 원인을 모르는 채로 장애는 트래픽이 많은 주말마다 되풀이됐고, SRE 팀과 개발팀은 주말마다 같은 조치로 장애를 넘겼다.

B 서비스 서버에서 뜬 패킷 덤프에는 정상과 다른 흐름이 있었다. 정상일 때는 AWS NAT Gateway 의 13.125.xx.xx 에서 B 서비스 서버 443 포트로 3way-handshake, 데이터 전송, 4way-handshake 가 이어졌다. 비정상일 때는 같은 출발지 포트 10141 에서 SYN 이 왔는데, B 서비스 서버는 SYN,ACK 대신 sequence number 가 2812932054 로 잘못된 ACK 만 보냈다. 요청자는 SYN 을 3회 다시 보냈다.

팀은 포트 재사용이 반복되다가 B 서비스 서버에서 TCP 소켓이 제대로 닫히지 않았다고 의심했다. 그리고 출발지, 목적지, 그 사이 네트워크 구간에 가설을 하나씩 세워 시험했다. 출발지에서는 인스턴스 수, 타임아웃, AWS 가용 영역 A 와 C 를 보았다. 목적지에서는 서버 수와 net.core.somaxconn=16384, net.ipv4.tcp_fin_timeout=5 같은 커널 튜닝을 보았다. 네트워크 구간에서는 NAT 증설, IDC 방화벽, L4 를 보았다. 커널 튜닝과 서버 증설로는 같은 증상이 그대로 났다.

구간을 나눠 재현해 보니 세 경우에는 증상이 나지 않았다. A 서비스가 connection pool 을 쓸 때, VPN 으로 NAT 와 인터넷 구간을 뺐을 때, L4 를 뺐을 때였다. 그래서 의심 범위를 IDC 의 L4 로 좁혔다. L4 부하 테스트 중에 /i/slb/sess/du 로 Session table 을 보니, 알고 있던 포트 범위 2000~65000 과 달리 2048~16383 만 보였다. TEST VIP 의 세션이 약 28,000 을 넘자 AUX Table 의 Allocation fail 수치가 올라갔다.

증상 오류율 상승아웃바운드 연결 고갈

원인

촉발
트래픽이 많은 주말에 connection pool 을 쓰지 않는 A 서비스가 NAT Gateway 를 거쳐 B 서비스로 새 TCP 연결을 계속 열었다.

감지

A 서비스의 5xx 오류 증가와 B 서비스의 L4 세션 카운트 증가로 알아챘다.

조치

후속 조치

교훈

장애를 해결하는 방법은 원인을 분석하다 보면 쉽게 보일 때가 많다. 그러나 원인을 정확히 확인하지 않으면 잠재적인 위험을 안은 채 서비스를 운영하게 된다. 우아한형제들은 장애 해결을 최우선으로 다루면서도, 재발을 막으려고 근본 원인을 찾아내는 과정을 중요하게 여긴다.

출처

관련 사례

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

kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이 사례와 같은 상태를 점검합니다. 이 사례의 구성 요소: NAT 게이트웨이, 온프레미스 로드 밸런서. 점검 항목의 근거는 이 사례 같은 공개 보고서입니다.

AI 도구와 스크립트용

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