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 세션 카운트 증가로 알아챘다.
조치
- A 서비스 인스턴스를 늘렸다.
- 5xx 오류와 L4 세션 카운트가 평소 수치로 돌아오지 않자 A 서비스 인스턴스를 교체했다.
후속 조치
- A 서비스 팀과 함께 A 서비스가 connection pool 을 쓰도록 바꾼다.
- AWS 와 IDC 사이에서 NAT Gateway 를 쓰는 서비스를 조사해 connection pool 을 쓰도록 바꾼다.
교훈
장애를 해결하는 방법은 원인을 분석하다 보면 쉽게 보일 때가 많다. 그러나 원인을 정확히 확인하지 않으면 잠재적인 위험을 안은 채 서비스를 운영하게 된다. 우아한형제들은 장애 해결을 최우선으로 다루면서도, 재발을 막으려고 근본 원인을 찾아내는 과정을 중요하게 여긴다.
출처
관련 사례
같은 원인 · 공통 온프레미스 로드 밸런서
IL-0037imagePullPolicy가 Always인 DaemonSet이 크래시 루프를 돌며 이미지를 계속 받아, NAT 세 대를 같이 쓰던 리전 전체가 이미지 레지스트리에서 429로 막혔다Datadog · 2019같은 원인 · 공통 NAT 게이트웨이
IL-0492AWS 연결 문제로 느려진 연결이 연결 한도를 다 차지해 AWS 밖에 있는 Hosted Graphite 로드 밸런서에 새 연결이 붙지 못했다Hosted Graphite · 2018같은 원인 · 공통 온프레미스 로드 밸런서
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0455
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0455/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.