IL-0306 Neon · 2024-08-14databaseaws
Neon us-east-1 에서 pageserver 를 돌리던 EC2 인스턴스가 예고 없이 죽어 프로젝트 0.4% 의 Postgres 가 최대 2시간 동안 멈췄다
Neon 데이터베이스는 safekeeper 와 pageserver 서비스에 저장된다. pageserver 는 safekeeper 가 저장한 Postgres WAL 을 받아 8KiB 페이지 단위로 캐시하고 색인해, Neon 컴퓨트 인스턴스가 페이지를 마이크로초 안에 읽게 한다. 영구 저장은 S3 가 맡으므로 pageserver 를 잃어도 데이터는 사라지지 않지만, 그 pageserver 에 연결된 프로젝트는 Postgres 가 페이지를 요청할 때 쓸 수 없게 된다. 프로젝트를 다른 pageserver 에 연결하면 이 문제가 풀린다. pageserver 는 EC2 인스턴스에서 돌고, 보통은 하드웨어 장애 전에 AWS 가 미리 알려 준다.
2024년 8월 14일 17:28 에 pageserver-7.us-east-1.aws.neon.tech 를 돌리던 EC2 인스턴스가 경고 없이 응답을 멈췄다. 17:38 에 알림이 울렸고 17:41 에 장애가 선언되었으며, 17:45 에 팀이 이 노드를 원인으로 찾았다. 17:52 에 이 pageserver 에 연결된 프로젝트 17037개를 같은 리전의 다른 pageserver 로 옮기기로 했고, 17:58 에 이전을 시작했다. 반자동 스크립트로 약 40분에 걸쳐 18:40 까지 99.5% 를 옮겼다. 진행 중이던 작업에 막혀 이상한 상태로 남은 프로젝트 20개쯤은 손으로 처리했고, 여기에 한 시간쯤 더 걸렸다. 19:41 에 모든 프로젝트가 돌아오고 알림이 풀렸다. 영향받은 프로젝트는 us-east-1 고객 프로젝트의 약 0.4% 였다.
복구가 늦은 이유는 세 가지였다. 첫째, 노드 장애가 난 뒤 이전을 결정하기까지 사람이 판단해야 했다. 텔레메트리가 끊긴 것을 알림이 잡아 사람에게 알리는 데만 몇 분씩 걸려, 장애에서 이전 시작까지 30분쯤 걸렸다. 둘째, 반자동 이전 스크립트가 느렸다. 셋째, 일부 프로젝트는 손으로 풀어야 했다. 데이터 손실과 스플릿 브레인은 없었다. 모든 프로젝트에 보조 pageserver 위치가 미리 준비되어 있어 다른 노드의 용량이 넉넉했고, 옮긴 뒤에도 캐시가 이미 데워져 있었다. Neon 은 2024년 5월부터 운영 중인 Storage Controller 가 pageserver 를 관리하도록 옮기는 중이었다. 장애 당시 64GiB 넘는 프로젝트는 이미 Storage Controller 가 관리했지만, 더 작은 프로젝트는 대부분 아직 아니었다.
- 심각도
- –
- 영향 범위
- Postgres databases of affected projects stalled on reads not in their buffer cache; most affected customers lost access for about 30 to 60 minutes, a smaller number for about 2 hours
- 영향 사용자
- about 0.4% of customer projects in us-east-1
- 지역
- us-east-1
- 감지까지
- 10m
- 복구까지
- 2h 13m
증상
2024년 8월 14일 17:38 에 알림이 Slack 으로 오고 온콜 엔지니어에게 자동으로 호출이 갔다. us-east-1 의 pageserver 하나가 응답하지 않았고, 그 pageserver 에 연결된 고객 Postgres 데이터베이스는 버퍼 캐시에 없는 데이터를 읽으려 할 때마다 멈췄다.
알림은 여러 갈래로 울렸다. pageserver 가 지표 수집에 응답하지 않았고, 컨트롤 플레인 API 의 오류율이 올랐으며, 엔드포인트 시작과 타임라인 생성 같은 사용자 작업이 멈춰 있었다.
17:45 에 엔지니어링 팀은 pageserver-7.us-east-1.aws.neon.tech 노드가 문제라는 것을 찾았다. 지표도 로그도 나오지 않고 SSH 로도 접속되지 않아, 팀은 이 노드가 망가졌다고 판단했다. 이 EC2 인스턴스는 17:28 에 응답을 멈췄고, AWS 의 사전 경고는 없었다.
영향받은 고객 대부분은 30분에서 60분쯤 데이터베이스를 쓰지 못했고, 더 적은 수의 고객은 2시간쯤 쓰지 못했다. 장애가 난 pageserver 에 연결된 프로젝트는 17037개였지만, 대부분은 그 시각에 쓰이고 있지 않아 직접 영향을 받지 않았다.
원인
원인 하드웨어 고장
- 촉발
- us-east-1 에서 pageserver-7.us-east-1.aws.neon.tech 를 돌리던 EC2 인스턴스가 17:28 에 AWS 의 사전 경고 없이 응답을 멈췄다.
감지
17:38 에 여러 알림이 울렸다. 알림은 Slack 으로 팀에 전해졌고, 온콜 엔지니어가 자동으로 호출됐다. pageserver 가 지표 수집에 응답하지 않는 것, 컨트롤 플레인 API 오류율이 오르는 것, 엔드포인트 시작과 타임라인 생성 같은 사용자 작업이 멈추는 것이 각각 알림을 울렸다.
조치
- 반자동 스크립트로 pageserver 7 에 연결되어 있던 프로젝트 17037개를 같은 리전의 다른 pageserver 로 옮겼다. 약 40분 걸렸다.
- 진행 중이던 작업 때문에 이전이 막혀 이상한 상태로 남은 프로젝트 20개쯤을 손으로 처리해 되살렸다.
후속 조치
- 이번 장애를 보고 유료 고객 전부를 Storage Controller 로 옮기는 계획을 앞당긴다.
- 기존 pageserver 인프라를 Storage Controller 가 관리하도록 옮기는 작업을 이어 간다. Storage Controller 는 조정 루프로 프로젝트를 pageserver 에 배치하고, 자체 하트비트로 노드 장애를 판단해 사람 없이 몇 초 안에 작업을 다른 노드로 옮긴다.
교훈
Neon 은 장애 대응이 모든 프로젝트를 되살렸지만 너무 오래 걸렸다고 밝혔다. 노드 장애가 난 뒤 이전을 결정하기까지 사람이 판단해야 했고, 알림이 텔레메트리 손실을 잡는 데 몇 분이 걸렸으며, 반자동 이전과 손으로 푸는 작업이 느렸다. 컨트롤 플레인은 원래 작업 큐를 둔 CRUD API 로 설계되었고, 작업은 프로젝트마다 하나씩 돌며 늘 끝까지 실행된다는 전제였다. 이 설계는 아래에서 움직이는 시스템의 가용성이 높을 때는 잘 맞지만, 언제든 멈출 수 있는 EC2 인스턴스 같은 물리 자원에 기대는 작업에는 맞지 않았다. 한편 알림은 늦었지만 정확해서 원인을 빨리 찾을 수 있었다. 이전은 느렸지만 데이터 손실과 스플릿 브레인이 없었고, 미리 준비해 둔 보조 pageserver 덕분에 용량과 데워진 캐시가 있었다.
출처
관련 사례
IL-0289updown.io 의 주 MongoDB 서버가 쿼리에 평소보다 약 200배 느리게 응답해 사이트와 모니터링 데몬이 거의 멈췄는데 자동 페일오버가 일어나지 않았다updown.io · 2019같은 원인 · 공통 데이터베이스, 데이터베이스 장애 조치 관리자
IL-0219Postgres 프라이머리의 디스크 어레이가 망가진 뒤 Pacemaker 가 새 프라이머리를 승격하지 못해 GoCardless API 와 대시보드가 1시간 50분 멈췄다GoCardless · 2017같은 원인 · 공통 데이터베이스, 데이터베이스 장애 조치 관리자
같은 원인 · 공통 데이터베이스
IL-0370Frankfurt 에서 노드 하드웨어 장애 뒤 Render Postgres 데이터베이스가 다른 노드에서 시작하지 못해 최대 1시간 5분 멈췄다Render · 2022같은 원인 · 공통 데이터베이스
같은 원인 · 공통 데이터베이스
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0306
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0306/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.