1P by GN⁺ 19일전 | ★ favorite | 댓글 1개
  • AWS Aurora RDS에서 발생한 경쟁 상태 버그를 실험적으로 확인하고 AWS로부터 원인 확인을 받은 사례
  • Hightouch는 이벤트 처리 시스템 확장 중 Aurora의 failover(장애 조치) 과정에서 쓰기 인스턴스 전환이 실패하는 현상을 발견
  • 로그 분석 결과, 두 인스턴스가 동시에 쓰기 작업을 수행해 스토리지 계층 충돌과 프로세스 종료가 발생한 것으로 확인
  • AWS는 내부 신호 처리 문제로 인해 이전 writer의 강등이 완료되지 않은 상태에서 새 writer가 승격된 것이 원인이라 공식 확인
  • 이 사례는 대규모 분산 시스템에서의 동시성 제어 중요성과, 장애 조치 시 쓰기 중단 절차의 필요성을 강조

배경

  • 2025년 10월 20일, AWS us-east-1 리전에 DNS 관리 시스템의 경쟁 상태 버그로 인한 장애 발생
  • Hightouch는 이로 인해 이벤트 처리 백로그가 급증해 시스템 한계에 도달
  • 처리량 확보를 위해 10월 23일 Aurora RDS 인스턴스 업그레이드를 진행했으며, 이 과정에서 새로운 경쟁 상태 버그를 발견

Hightouch 이벤트 시스템 구조

  • 이벤트 수집 및 전송을 담당하는 시스템은 Kubernetes, Kafka, Postgres(Aurora) 로 구성
  • Postgres는 배치 메타데이터 큐로 사용되며, 초당 50만 건 이벤트를 1초 내 처리
  • Aurora PostgreSQL은 쓰기 전용(primary) 인스턴스와 읽기 전용(replica) 인스턴스, 그리고 공유 스토리지 계층으로 구성

업그레이드 계획

  • 읽기 인스턴스 추가 → 기존 리더 업그레이드 및 failover 우선순위 부여 → failover 실행 → 기존 writer 업그레이드 → 임시 리더 제거
  • 이 절차는 AWS 문서에 명시된 방식이며, 스테이징 환경에서 부하 테스트를 통해 검증된 절차였음

업그레이드 시도와 문제 발생

  • 10월 23일 16:39 EDT, failover 실행 후 기존 writer가 다시 primary로 복귀하는 현상 발생
  • 두 차례 시도 모두 동일한 결과로, 쓰기 불가 오류(DatabaseError: cannot execute UPDATE in a read-only transaction) 가 일부 서비스에서 발생
  • 로그 분석 결과, 두 인스턴스가 동시에 쓰기 작업을 수행하다 스토리지 충돌로 종료된 로그 확인

경쟁 상태의 원인

  • Aurora의 failover 과정 중 3단계(기존 writer 강등)와 4단계(새 writer 승격) 사이에 경쟁 상태 발생
  • 이로 인해 두 인스턴스가 동시에 쓰기 권한을 가지며 충돌
  • 쓰기 트래픽을 제거한 상태에서 재시도하자 failover가 정상 완료되어 경쟁 상태 가설이 입증

AWS의 확인 및 대응

  • AWS는 내부 검토 후, writer 강등 신호 처리 오류가 원인이며 Hightouch의 설정이나 트래픽 패턴과 무관하다고 확인
  • 수정이 로드맵에 포함되어 있으며, 임시 대응책으로 failover 중 쓰기 중단을 권장

최종 조치

  • Hightouch는 클러스터 업그레이드를 완료하고,
    • 의도적 failover 전 쓰기 중단 절차 추가
    • writer 역할 변경 감시 모니터링 강화
    • 운영 매뉴얼(playbook) 업데이트를 수행

주요 교훈

  1. 마이그레이션 중 예기치 않은 상태 전환에 대비한 복구 준비 필요
  2. 관측성(observability) 확보가 문제 탐지의 핵심
  3. 분산 시스템 구성요소 간 영향 최소화 설계의 중요성
  4. 테스트 환경과 실제 운영 환경의 차이를 인식해야 함

원문에 추가 정보 없음

Hacker News 의견
  • 이 글을 보면 수동 장애 조치(failover) 중에도 애플리케이션이 평소처럼 쓰기 트래픽을 유지하려 하면 항상 실패하는 것처럼 보임
    하지만 몇 가지 의문이 생김. 다른 Aurora 사용자들은 왜 이런 문제를 항상 겪지 않는지, AWS가 모를 리가 있는지, 만약 알고 있다면 왜 P0급 긴급 이슈로 다루지 않는지 궁금함
    혹시 진행 중인 트랜잭션 상태나 타임아웃 같은 미묘한 조건이 작용하는 걸지도 모른다는 생각이 듦

    • Azure에서 비슷한 문제를 다뤄본 경험상, 많은 사람들이 겪지만 재시작으로 해결되니 그냥 넘어가는 경우가 많음. 근본 원인을 찾기 어렵고, 벤더와 함께 분석하는 과정이 너무 고통스러워서 대부분 포기함
    • 우리도 AWS와 협업하면서 같은 문제를 확인했음. 트래픽 패턴이 특별하지 않았고, 다른 리전에서는 재현되지 않았음. 이건 Aurora의 근본적인 장애 조치 메커니즘 결함일 가능성이 높음
    • 예전에 Python + MySQL 조합에서 SELECT ... FOR UPDATE가 조용히 실패하고 트랜잭션이 autocommit 모드로 전환되는 버그를 겪은 적이 있음. 아무도 관심을 안 가져서 혼자 떠들었는데, 몇 달 뒤 다른 사람도 같은 문제를 겪었다고 연락이 옴. 결국 수정되긴 했지만 이미 관심을 끊은 뒤였음
      관련 링크: Stack Overflow 질문
    • AWS는 내부 정보를 거의 공개하지 않음. API 수준 이상의 세부 내용을 알려주지 않기 때문에, 이런 문제를 희귀 케이스로 치부하고 넘어가는 듯한 느낌을 받음
    • 문제의 일부는 애플리케이션이 되돌려진 장애 조치(reverted failover) 에 반응하는 방식 때문일 수도 있음. 캐시가 깨져 잘못된 프라이머리로 계속 쓰기를 시도한 듯함. 이런 실패가 종종 일어나도, 재시도하면 성공하니 사용자들이 AWS에 신고하지 않아 AWS가 인지하지 못했을 가능성도 있음
  • Aurora PostgreSQL에서 예상치 못한 동작을 여러 번 봤음
    특히 Zero Downtime Patching(ZDP) 중 세션 상태가 잘못 유지되어, 간단한 쿼리조차 statement_timeout보다 훨씬 빨리 취소되는 현상을 겪었음
    내 추측으로는 클라이언트가 재연결될 때, Aurora가 이전 세션의 오래된 타이머 상태를 그대로 이어받아 쿼리가 즉시 취소되는 것 같음

  • 우리도 쓰기 트래픽이 매우 높은 환경에서 정기적으로 장애 조치를 수행하지만, AWS JDBC wrapper를 사용해 자동화된 프로세스로 안정적으로 운영 중임

    • 실제로는 Aurora의 스토리지 계층이 ACID 위반을 막아줬음, 즉 데이터 무결성은 지켜졌음
  • Aurora가 이런 기본적인 불변성을 유지해줄 거라 믿고 돈을 내는 건데, 이런 문제가 생기다니 놀라움

    • 하지만 스토리지 계층 자체는 동시 쓰기를 차단해 올바르게 동작했음
  • 로그와 AWS의 설명을 보면, 원글 작성자의 가설은 틀린 듯함
    프로모션 실패 후 외부 감시 프로세스가 클러스터 상태 불일치를 감지하고 강제 종료(kill -9) 한 것으로 보임. 스토리지 서브시스템 관련 메시지는 그 이후에 발생한 것임

  • Aurora와 RDS Postgres의 성능 비교에 대해 묻고 싶음.
    멀티 AZ나 빠른 장애 조치가 필요 없다면, RDS에서 gp3 64k IOPS 구성으로 더 나은 성능을 낼 수 있을까? Aurora는 특히 insert 성능이 느리고 비용이 높아 보임. 벤치마크들도 RDS 설정을 명확히 밝히지 않아 신뢰하기 어려움

    • 우리는 Aurora PG 14에서 1 writer + 1~2 reader 구성으로 더 나은 성능과 낮은 비용을 얻었음. Aurora는 인스턴스별이 아닌 클러스터 단위 스토리지 과금이라 유리함.
      또한 IOPS를 직접 프로비저닝할 필요가 없고 약 80k IOPS를 제공함.
      IO 과금 방식도 두 가지가 있는데, pay-per-IO는 저부하 환경에, 고정 요금 모드는 IO가 많은 워크로드에 유리함.
      참고로 Serverless는 거의 항상 비경제적이었음. 짧은 피크 타임이 있는 경우에만 유용함
    • 우리 팀은 Aurora Postgres RDS에서 I/O 비용 폭증을 겪었음. 단 몇 개의 fuzzy query로 월 $3,000 이상이 나왔고, 원래는 $100 이하였어야 했음
    • Aurora의 비용, 성능, 지연시간 모두 실망스러워 결국 온프레미스 PostgreSQL로 이전했음
    • Aurora MySQL 기준으로는, 같은 IOPS를 RDS에서 맞추려면 훨씬 비싼 비용이 들었음
    • Aurora는 EBS를 사용하지 않으며, 스토리지 타입이나 지연시간을 선택할 수 없음. 단지 IO 과금 방식을 고를 수 있을 뿐임
  • AWS 엔지니어들이 말하는 “레고 블록 모델” 이 잘 드러남
    스토리지 계층을 완전히 독립적으로 설계해, 상위 서비스가 실패해도 데이터 일관성은 보장되었음. AWS 엔지니어링의 좋은 사례라고 생각함

  • AWS가 “장애 조치 중에는 쓰기를 멈추라”는 권고를 했다고 하는데, 관련 케이스 번호를 공유받을 수 있는지 궁금함

    • 우리도 Aurora MySQL을 쓰고 있어서, 이 권고가 MySQL에도 적용되는지 확인하고 싶음
  • 이런 문제를 겪은 게 나만이 아니라는 걸 알아서 다행임

    • AWS Support는 처음엔 복제 지연(replication lag) 때문이라며 반박했지만, 24시간 전의 오래된 메트릭을 보고 판단했음. 어떤 실패를 겪었는지, 다른 리전에서는 왜 재현되지 않았는지 정말 알고 싶음
  • Aurora의 컴퓨트-스토리지 분리 아키텍처가 흥미로움
    MSSQL의 Hyperscale도 비슷한 구조인데, Azure 서비스 중 내가 실제로 써볼 만하다고 생각하는 거의 유일한 제품임