사례4건
4건 중 1~4번째
IL-0574운영 환경의 DB 접속 경로를 Amazon RDS Proxy로 바꾼 지 몇 분 만에 Aurora MySQL writer CPU가 100%에 이르고 에러가 났다Safie2026- 증상
운영 환경의 엔드포인트를 RDS Proxy로 바꾸고 몇 분 뒤 사내 알림 모니터링 시스템에서 에러 알림이 울렸다. Aurora writer의 CPU 사용률은 거의 100%에서 내려오지 않았다.
- 촉발
운영 환경의 Aurora MySQL 접속 엔드포인트를 RDS Proxy로 바꿨다. Proxy는 MaxConnectionsPercent 21%로 Aurora에 커넥션을 약 3,360개만 열 수 있었고, ConnectionBorrowTimeout은 애플리케이션 소켓 타임아웃과 같은 7초였다.
- 원인
- 구성 요소
- 기여 요인
- 감지
운영 환경의 엔드포인트를 RDS Proxy로 바꾸고 몇 분 뒤 사내 알림 모니터링 시스템이 에러 알림을 냈다.
- 조치
- 그 자리에서 되돌리기로 하고, RDS Proxy를 보는 애플리케이션 서버인 ECS Fargate 태스크를 이전 버전으로 되돌렸다.
- 후속 조치
- 검증 환경에서 설정 값만으로 장애가 재현되고 해소되는 것을 확인한 뒤 MaxConnectionsPercent를 62%로, MaxIdleConnectionsPercent를 31%로 바꿨다.
- 애플리케이션 안에서 피처 플래그를 평가해 Aurora 직결과 Proxy 경유 중 어디로 접속할지 요청마다 정하게 했다. 플래그는 ECS 태스크 ID의 해시로 태스크 단위로 나눠 한 태스크 안에서 접속 대상이 섞이지 않게 했다.
- 트랜잭션 중간에 커넥션이 끊길 때 영향이 큰 쓰기 요청은 뒤로 미루고, 조회용 GET 요청부터 옮긴다.
- 옮기는 비율은 1%, 10%, 25%, 50%, 75%, 100%로 단계적으로 올린다. 단계마다 Proxy의 대기 시간과 새 백엔드 커넥션 수, Aurora의 커넥션 수와 CPU와 지연, 애플리케이션 에러 수를 보고 다음 단계로 간다.
- 교훈
이번 장애와 이후의 문제는 RDS Proxy의 버그가 아니었고, Proxy를 끼우면서 애플리케이션 커넥션 풀의 구현과 설정에 있던 문제가 드러난 것이었다. Proxy를 끼우면 백엔드 커넥션을 여러 클라이언트가 나눠 쓰므로, 세션 상태가 같은지, 트랜잭션이 닫혔는지, 커넥션이 DB 쪽 수명 안에 있는지가 모두 재사용 조건이 된다. 도입 전에는 Proxy 설정 값보다 애플리케이션 커넥션 풀이 커넥션을 반납할 때 무엇을 실행하는지, 커넥션 수명을 어떻게 정하는지, 접속할 때 무엇을 보내는지를 확인했어야 했다. 타임아웃과 상한은 애플리케이션, Proxy, 데이터베이스 순으로 아래 계층일수록 같거나 길게 맞춘다. 엔드포인트만 바꾸는 한 번의 전환은 실패하면 모든 서비스에 한꺼번에 번지므로 단계적으로 옮겨야 한다.
IL-0368AWS us-east-1 장애 동안 PlanetScale 컨트롤 플레인이 멈추고, 이어 일부 데이터베이스 브랜치가 네트워크 분할로 쿼리에 실패했다PlanetScale2025- 증상
7:13 UTC 에 프로덕션에서 계속 도는 PlanetScale 테스트가 실패하기 시작했다. 테스트는 새 데이터베이스 브랜치를 만들지 못하고 있었다. 데이터베이스 브랜치를 만들고 크기를 바꾸고 설정하는 서비스가 응답하지 않았다.
- 촉발
PlanetScale 의 서비스 제공자 한 곳에서 DNS 설정 오류가 났고, 이어서 AWS us-east-1 에 몇 시간 동안 용량 제약과 네트워크 불안정이 이어졌다.
- 원인
- 구성 요소
- 기여 요인
- –
- 감지
첫 단계는 7:13 UTC 에 프로덕션에서 계속 도는 테스트가 실패하면서 엔지니어들에게 알림이 갔다. 둘째 단계는 10:05 UTC 에 한 고객 환경의 Kubernetes operator 가 쓸 수 있는 자원을 모두 쓰고 있다는 알림으로 알았다.
- 조치
- us-east-1 에 새 데이터베이스를 만드는 것을 잠시 막고, 새 데이터베이스의 기본 리전을 AWS us-east-2 로 바꿨다.
- 추가 백업 예약을 미루고, EC2 인스턴스를 띄우려고 기다리던 백업을 취소했다. PlanetScale 의 표준 백업은 백업 동안 데이터베이스의 용량과 장애 내성이 줄지 않도록 복제본을 하나 더 띄워 이전 백업을 복원하고 복제를 따라잡은 뒤 새 백업을 뜬다.
- vtgate 자동 확장을 쓰는 PlanetScale Managed 고객에게 큐 처리를 미루거나 ETL 작업을 멈추는 식으로 줄일 수 있는 부하를 줄이라고 권했다.
- 30일이 넘은 EC2 인스턴스를 비우고 종료하던 상시 작업을 멈췄다.
- 비게 된 EC2 인스턴스를 종료하지 않고 다시 쓰려고 남겨 뒀다.
- 자동 확장을 설정한 고객의 vtgate 프로세스를 평소보다 빽빽하게 배치해 CPU 용량에 더 가깝게 돌리면서, 미국 업무 시간 동안 쓸 용량을 넉넉히 확보했다.
- 가능한 곳에서는 손으로 reparent 요청을 보내 프라이머리 데이터베이스를 더 건강하다고 알려진 가용 영역이나 고객 애플리케이션과 같은 영역으로 옮겼다.
- 네트워크 분할이 풀린 뒤 스스로 복구하지 못한 엣지 로드 밸런서와 vtgate 프로세스를 재시작해 서비스를 되살렸다.
- 후속 조치
- CI/CD, SSO, 웹 애플리케이션 호스팅, 장애 공지에 쓰는 SaaS 의 장애 양상을 더 잘 이해하고, 그 장애에 버틸 수 있게 한다.
- 런타임에 내부 서비스와 AWS 서비스에 기대는 정도를 더 크게 줄이는 방법을 조사한다.
- AWS us-east-1 에 있는 가용 영역 여섯 개를 모두 더 잘 써서, 영역 장애와 영역 사이의 네트워크 분할에 더 잘 버티는 방법을 살핀다.
- 교훈
PlanetScale 은 컨트롤 플레인과 데이터 플레인을 확실히 나눠 둔 덕분에 컨트롤 플레인 장애가 고객 데이터베이스에 번지지 않았다고 봤다. 중복 구성과 자동 장애 조치로 프라이머리 데이터베이스 서버가 네트워크 분할의 다수 쪽으로 옮겨 갔고, 영역을 고려한 트래픽 라우팅이 분할의 영향을 최대한 줄였다. 네트워크 분할은 장애 양상 가운데 따져 보기도, 시험하기도, 견디기도 가장 어려운 편이다. 가용 영역 세 개를 쓰면 하나가 망가져도 버틸 수 있지만, 나머지 두 영역 사이의 네트워크 연결이 믿을 만할 때만 그렇다.
- 증상
2025년 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다. 그 뒤 9월 18일까지 고객 트래픽에서 요청 실패와 지연 급증이 간헐적으로 이어졌다.
- 촉발
2025년 9월 14일 클라우드 사업자가 Clerk 의 Postgres 데이터베이스를 마이너 버전으로 자동 업그레이드했다. 이 업그레이드에는 Postgres 가 연결 잠금을 다루는 방식의 큰 내부 변경이 들어 있었다.
- 원인
- 구성 요소
- 기여 요인
- 감지
9월 14일 업그레이드 직후 내부 모니터링이 데이터베이스 부하 증가를 잡았지만 견딜 만한 수준이었고 지연에는 영향이 없었다. 9월 15일 13:08 UTC에 내부 모니터링이 요청 실패가 크게 늘고 지연이 늘었다고 알렸다.
- 조치
- 비용이 큰 쿼리 여러 개를 최적화해 데이터베이스의 기본 부하를 영구히 줄였다. 주요 인덱스를 다듬고 전체 재색인을 해 데이터베이스 오버헤드도 줄였다.
- 안정성을 지키려고 남용 트래픽 차단을 잠시 강화했다. 효과는 있었지만 정상 요청 일부가 HTTP 429 로 거부됐을 수 있다.
- 9월 17일 07:15 UTC부터 08:10 UTC까지 수동 마이너 버전 업그레이드를 하고 데이터베이스 용량을 늘렸다. 데이터베이스 상태가 눈에 띄게 나아졌고 지연 급증이 다시 사라진 듯했다.
- 연결 재생성 시각이 서로 맞춰지지 않도록 연결 풀링 전략에 지터를 넣었다. 배포 직후 데이터베이스 부하가 장애 전보다 낮아졌고 지연 급증이 사라졌다.
- 후속 조치
- 업그레이드와 다운그레이드를 더 통제할 수 있고 지금 사업자보다 성능이 나은 데이터베이스 솔루션을 검토한다.
- 가입과 로그인 인프라를 시스템의 다른 부분에서 떼어 내는 식으로 서비스 격리를 넓힌다.
- 비용이 큰 쿼리 목록을 계속 따라가며 데이터베이스 성능을 더 끌어올린다.
- 애플리케이션 하나를 다른 애플리케이션과 격리하는 테넌트 격리 방법을 검토한다. 이 작업은 샤딩과 멀티테넌트 인프라의 최신 방식을 살펴보는 일이라 다른 개선보다 오래 걸릴 가능성이 크다.
- 교훈
Clerk 는 돌아보면 원인이 단순해 보이지만 여러 요인이 겹쳐 찾기 어려웠다고 밝혔다. 첫째, 연결 지표를 60초 간격으로 수집해 15분마다 몇 초 안에 일어나는 재생성 주기가 대시보드에 드문드문한 급증으로만 보였다. 둘째, 같은 시기의 사기 가입 공격이 약 10분 주기로 부하를 만들어 원인을 그쪽으로 의심하게 했다. 셋째, 10분, 15분, 30분 간격의 정기 작업과 예약 쿼리가 급증 시각과 맞아떨어져 조사를 흩뜨렸다. 넷째, 같은 연결 풀링 로직을 쓰는 Backend API 에는 급증이 잘 보이지 않았는데, Clerk 는 Backend API 가 관리하는 연결 수가 훨씬 적어 재생성이 맞춰져도 데이터베이스가 감당했기 때문으로 봤다. 다섯째, 장애 중에 건 배포 동결은 평소 배포가 연결 생성 시각을 흩어 주던 효과를 없애 문제를 키웠다. 이 관계가 직관적이지 않아 연결 동기화를 가리키는 가장 분명한 신호가 가려졌다.
- 증상
2022년 3월 16일 14:09 UTC, 최대 부하 시간대에 mysql1 데이터베이스의 부하가 늘면서 데이터베이스 프록시가 최대 연결 수에 닿았다. GitHub 의 모든 쓰기 작업이 동작하지 않았다.
- 촉발
최대 부하 시간대에 공용 MySQL 클러스터 mysql1 의 부하가 늘어 데이터베이스 프록시가 최대 연결 수에 닿았다.
- 원인
- 구성 요소
- 기여 요인
- 조치
- 정상인 복제본으로 페일오버해 3월 16일 장애에서 복구했다.
- 3월 17일 미리 한 페일오버 뒤 새 주 노드에 생긴 연결 문제를 풀려고 연결을 재설정했다.
- 3월 17일 장애 중에 부하 패턴을 찾아 인덱스를 추가해 주된 성능 문제를 고쳤다.
- 3월 22일 클라이언트 연결이 실패하자 다시 주 노드를 페일오버해 복구했다.
- 3월 23일 같은 부하 특성으로 클라이언트 연결이 실패하자 다시 주 노드를 페일오버해 복구했다.
- 3월 23일 부하를 줄이려고 웹훅 트래픽을 제한했다.
- 후속 조치
- 다른 대책을 더 찾는 동안 최대 부하 시간대에 웹훅 트래픽 제한을 계속 써서 같은 장애가 다시 나지 않게 한다.
- 최대 부하 시간대의 mysql1 부하 패턴을 점검하고, 그 결과에 따라 성능 수정을 차례로 한다.
- 부하를 줄이고 페일오버 시간을 줄이려고 mysql1 의 트래픽을 다른 데이터베이스로 옮긴다.
- 변경 관리 절차를 검토한다. 특히 운영 환경에 부하가 높을 때의 모니터링과 변경을 살핀다.
- 플랫폼 성장에 맞춰 데이터베이스 샤딩과 하드웨어 확장을 비롯한 인프라 확장을 이어 간다.
이 4건에서 가장 많이 나오는 구성 요소: 데이터베이스, 데이터베이스 프록시와 커넥션 풀러. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.