IL-0290 GitLab · 2026-05-12databasegcp
GitLab.com 의 Redis Sidekiq 클러스터에서 노드 여러 대가 메모리를 다 써 멈추고 쿼럼을 잃어, 웹과 Git 과 CI 전반에서 500 오류가 늘었다
2026-05-12 GitLab.com 에서 같은 날 앞선 장애 inc-10084 를 완화하면서 감사 이벤트 작업을 지연 처리로 돌렸다. 지연된 작업이 쌓여 Redis Sidekiq catchall-b 클러스터의 메모리를 모두 차지했고, 메모리가 바닥나자 Redis 호스트에서 커널 오류가 나며 노드 여러 대가 멈췄다. 정상 노드가 하나만 남아 클러스터는 쿼럼을 유지하지 못했다. 17:12 UTC 부터 web, CI 러너, Git, API, Sidekiq 을 포함한 GitLab.com 의 주요 서비스 전반에서 오류율이 올랐고, 100만 건이 넘는 요청이 영향을 받았다. Sidekiq 대기열이 1,200만 개를 넘으며 파이프라인 생성과 작업 처리가 멈췄고, 영향받은 파이프라인은 1만 개가 넘는 것으로 추정됐다. 장애는 Severity 1 로 올라갔다.
대응한 엔지니어들은 트래픽 급증을 원인에서 빼고 catchall-b 노드들이 응답하지 않는다는 것을 확인한 뒤, 응답 없는 노드 두 대를 재시작하고 강제로 리셋했다. 18:00 UTC 에 세 노드가 모두 올라오고 O2 가 primary 가 됐지만 노드들은 곧 다시 오류를 냈다. 엔지니어는 VM 을 한 대씩 멈추고 메모리와 CPU 를 두 배로 늘린 머신 타입으로 바꿨고, 18:40 UTC 에 세 노드의 교체가 끝나며 오류율이 떨어졌다. 영향은 18:43:44 UTC 에 끝나 1시간 31분 이어졌다. 대기열 비우기처럼 되돌릴 수 없는 선택은 미루고 안전한 완화부터 했다. Sidekiq 대기열은 최대 1,220만 개에서 19:10 UTC 에 700만 개 아래로 줄었고, 장애는 21:30:57 UTC 에 사후 처리 단계로 넘어갔다.
문제의 워커인 AuditEvents::AuditEventStreamingWorker 는 2025년 3월부터 장애를 거듭 일으켰고 그때마다 심각도가 올랐다. 2025-03-24 의 INC-310 은 PGBouncer 포화였고, 다음 날 INC-311 은 같은 일이 되풀이된 것이었다. 2025-04-15 의 INC-489 는 잘못된 스트리밍 대상 때문이었다. 셋 다 S2 였다. 이번 INC-10096 은 S1 이었다. 장애 중에 한 엔지니어는 이 워커가 얽힌 S2 장애가 이번 달에만 두 번째라고 짚었다. 앞선 것은 INC-8169 였고, 12월에는 S3 장애도 있었다.
- 심각도
- sev1
- 영향 범위
- All major GitLab.com services, including web, Git, API, CI runners and Sidekiq: more than 1 million requests affected, a Sidekiq backlog of over 12 million jobs and an estimated more than 10,000 pipelines affected
- 영향 사용자
- All GitLab.com customers active during the impact period
- 지역
- –
- 감지까지
- 3m
- 복구까지
- 1h 31m
증상
2026-05-12 17:15 UTC 에 Prometheus Alertmanager 알림으로 장애가 접수됐다. 플랫폼 대시보드에서 web, Git, API, CI 러너, Sidekiq 의 오류율이 한꺼번에 올랐고, 사용자는 잦은 500 오류와 인증 실패, CI 파이프라인 실패를 겪었다.
CI 러너의 오류율은 최대 5% 까지 올랐고 git workhorse API 와 web 서비스도 영향을 받았다. 파이프라인이 created 상태에 멈춰 있었고 파이프라인 생성이 오랫동안 0 에 가깝게 떨어졌다. 엔지니어는 이 증상을 실시간으로 세고 확인하기 어려웠고, 맞는 대시보드와 SLI 를 온콜이 바로 찾지 못했다.
Redis 호스트 redis-sidekiq-catchall-b-01-db-gprd 의 커널 로그에는 "INFO: task kcompactd0:67 blocked for more than 120 seconds." 가 찍혔다. redis-sidekiq-catchall-b-02-db-gprd 에서는 systemd 가 "redis-server.service: Found left-over process 2516163 (redis-server) in control group while starting unit. Ignoring." 을 남겼고, redis_exporter 는 "Couldn't connect to redis instance (redis://localhost:6379)" 를 거듭 기록했다. 호스트 자체가 응답하지 않아 SSH 로그인이 멈췄다.
엔지니어는 처음에 Redis 연결 문제를 의심했고, 이어서 DNS 서비스 디스커버리 문제나 US East 리전 전체의 장애일 가능성도 살폈다. 운영 환경에서 진행 중인 롤아웃은 없었고 최근 변경은 스테이징의 레지스트리 관련 롤아웃뿐이었다. 외부 DNS 전문가의 도움도 구했다. 대시보드와 로그에서 초당 요청 수가 평탄하거나 줄고 있음을 보고 트래픽 급증은 원인에서 뺐다.
18:00 UTC 에 Redis 노드 세 대가 모두 다시 올라왔지만 노드들은 곧바로 다시 오류를 냈다. Sidekiq 대기열은 최대 1,220만 개까지 쌓였다.
원인
- 촉발
- 같은 날 앞선 장애 inc-10084 를 완화하려고 감사 이벤트 작업을 지연 처리로 돌려 두었고, 지연된 작업이 Redis Sidekiq 클러스터에 쌓였다.
감지
17:12 UTC 에 영향이 시작됐고 17:15:10 UTC 에 Prometheus Alertmanager 알림이 incident.io 에 장애를 트리아지 상태로 올렸다. 온콜이 17:16:59 UTC 에 Severity 2 로 받아들였고 17:32:49 UTC 에 Severity 1 로 올렸다. redis-sidekiq 메모리 알림은 온콜을 호출하지 않았고, 다른 신호들도 라벨과 라우팅의 틈 때문에 맞는 온콜에게 제대로 닿지 않았다.
조치
- 응답하지 않는 Redis 노드 두 대를 골라 재시작하고 강제로 리셋했다. 18:00 UTC 에 세 노드가 모두 올라왔고 O2 가 primary 가 됐다.
- Redis VM 을 한 대씩 멈추고 메모리와 CPU 를 두 배로 늘린 c2-standard-16 머신 타입으로 바꿨다. 18:40 UTC 에 세 노드의 교체가 끝났다.
- AuditEventStreamingWorker 를 다시 켜고 더는 지연 처리로 돌리지 않았다. 앞서 지연시킨 탓인지 이 워커의 대기열이 계속 늘어 지켜봤다.
후속 조치
- redis-sidekiq 메모리 알림이 왜 온콜을 호출하지 않았는지 조사한다.
- WebHookWorker poison pill 문제의 근본 원인과 실패 양상, 해결 진행 상황을 정리한다.
- 안전 한도를 끄는 완화 조치에는 담당자와 재검토 기한을 분명히 정하도록 절차를 고친다.
- AuditEvents::AuditEventStreamingWorker 가 장애를 되풀이해 일으키지 않도록 고친다.
- AuditEventStreamingWorker 의 런북을 만든다.
- PG 연결 풀 포화 문제를 후속 작업으로 다룬다.
교훈
web, Git, 인증, CI 러너, Sidekiq, 내부 API 가 한꺼번에 나빠져 원인 하나로 좁히고 그것을 짧게 전하기가 어려웠다. created 상태에 멈춘 파이프라인처럼 고객이 겪는 증상을 실시간으로 세고 확인할 방법이 부족했고, 관련 대시보드와 SLI 를 온콜이 찾기 어려웠다. 호스트가 응답하지 않아 SSH 로그인이 멈추면서 진단이 늦어지고 변경할 때의 위험도 커졌다. 신호가 있어도 라벨과 라우팅의 틈 때문에 맞는 온콜에게 닿지 않았다. redis-sidekiq 의 메모리가 포화되자 엔지니어는 장애 한가운데서 가용성과 데이터 손실 사이의 어려운 선택을 해야 했다. 이 부분에는 안전장치와 설계 개선이 필요했다. 대시보드와 로그로 트래픽 급증을 먼저 배제한 덕분에 공용 의존성과 인프라 쪽 원인에 집중할 수 있었다. 대기열 비우기처럼 되돌릴 수 없는 선택을 미루고 안전한 완화부터 한 것도 도움이 됐다.
출처
참고 문서
관련 사례
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
IL-0067Redis 마스터의 50Mi 영구 볼륨이 가득 차 AOF 가 깨졌고, Redis 파드가 크래시 루프에 빠져 Klamm 운영 서비스가 멈췄다BC Government · 2025 · sev1같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
IL-0202갑자기 몰린 쿼리와 데이터베이스 쓰기로 Honeycomb 수집 호스트가 메모리 부족으로 죽었고, 쿠버네티스 CrashLoopBackOff 가 용량 회복을 막아 US1 이벤트 수집이 한 시간 넘게 불안정했다Honeycomb · 2023 · sev1같은 원인 · 공통 인메모리 캐시
IL-0386Google Cloud 로 옮긴 뒤 GKE 노드에서 Postgres 연결 타임아웃과 memcached i/o timeout 이 간헐적으로 튀었다incident.io · 2023같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
같은 원인 · 공통 인메모리 캐시
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0290
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0290/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.