IL-0285 Clever Cloud · 2024-08-02databaseobservability
Clever Cloud 의 Apache Pulsar 메시징 클러스터가 멈추면서 EU-FR-1 리전의 배포 API 가 먹통이 되고 하이퍼바이저들이 커널 패닉으로 재부팅됐다
2024년 8월 2일 금요일, Clever Cloud 는 메시징의 기반인 Apache Pulsar 를 3.3.1 로 올리는 작은 롤링 업그레이드를 10:06 CEST 에 시작했다. 이 작업에서 기본 OverloadShedder 대신 TransferShedder 를 쓰고, 번들 unload 방식을 modular 에서 extensible 로 바꾸는 설정도 함께 켰다. 새 unload 방식은 브로커끼리 실시간으로 부하 메타데이터를 복제하는 시스템 토픽에 기댄다. 그런데 첫 브로커에서 이 확장 기능이 제대로 초기화되지 않아 시스템 토픽이 만들어지지 않았다. 브로커가 죽지 않아 모니터링이 이를 잡지 못했고 롤링 업그레이드는 이어졌다. 브로커들이 토픽 메타데이터를 찾느라 Lookup 요청 큐가 가득 찼다. 결국 어떤 토픽도 로드되지 않아 메시징이 멈췄다. 큰 릴리스에는 전체 환경을 흉내 낸 시뮬레이션 절차를 쓰지만, 작은 업그레이드나 작아 보이는 설정 변경에는 쓰지 않았다.
엔지니어들은 10:58 에 새 설정이 롤링 업그레이드와 충돌한다는 것을 알고 unload 방식만 되돌리고 3.3.1 은 유지했다. 그러나 새 방식이 만든 시스템 토픽이 메타데이터 충돌로 어느 브로커에도 배정되지 않아 브로커들이 시작하지 못했다. 팀은 클라이언트 프록시를 내리고, 배포 쪽은 알림 이벤트를 RabbitMQ 로 돌렸다. 팀은 모든 브로커를 멈추고 하나만 띄워 그 토픽을 로드한 뒤 지웠다. 12:28 에 모든 브로커가 올라왔고, 12:54 에 메시징 프록시를 재시작하자 메시징이 정상으로 돌아왔다. 11:10 부터 고객은 배포하지 못했다.
메시징이 멈춘 동안 고객 VM 의 관측 에이전트 Vector 가 로그를 메모리에 쌓았다. 메모리가 작은 VM 들은 커널 메모리 압박으로 디스크에서 다시 읽기 시작했고, 하이퍼바이저에 큰 I/O 와 CPU 부하가 걸렸다. 12:47 부터 하이퍼바이저들이 khungtaskd 가 일으킨 커널 패닉으로 재부팅했고, 주 API 구성 요소는 OOM 으로 죽었다. 모니터링은 도달 불가와 CPU 증가를 보고 평소의 거의 3배에 이르는 배포를 일으켰다. Clever Cloud 는 자기 플랫폼 위에서 돌기 때문에 대량 작업에 필요한 스케줄러와 컨트롤 플레인 자체가 제대로 돌지 못했다. 영향은 파리의 EU-FR-1 리전과 이 컨트롤 플레인에 기대는 OVHcloud, Scaleway, Oracle 원격 존에 미쳤다.
팀은 watchdog 을 멈추고 구성 요소를 하나씩 띄웠다. 관측 장기 저장소와 Metrics API 수집 같은 덜 중요한 서비스를 내리고, 모든 리전의 모니터링 인스턴스를 유지보수 모드로 돌렸다. 과부하를 일으키는 작은 VM 을 하나씩 죽이고 하이퍼바이저 12대에서 작업을 뺐다. 좀비 VM 을 정리하고 새 하이퍼바이저를 투입했으며, 과부하된 RabbitMQ 노드를 클러스터에서 뺐다. 로드 밸런서를 차례로 재시작했고, 18:20 에 모든 배포가 다시 나가기 시작했으며 18:36 에 모든 하이퍼바이저가 평소 부하로 돌아왔다. Metrics API 는 부하를 단계적으로 올리는 QoS 정책으로 수집을 다시 켰고, 22:53 에 모든 영향이 풀렸다. 데이터는 잃지 않았다.
- 심각도
- –
- 영향 범위
- The Deployment API was unreachable and deployments and scaling failed; applications and databases on impacted hypervisors were degraded or unavailable, some cluster services had issues, most VPN endpoints were unavailable and the observability service was down; no data was lost
- 영향 사용자
- many Clever Cloud customers
- 지역
- EU-FR-1 (PAR) and remote zones depending on the EU-FR-1 control plane (OVHcloud, Scaleway and Oracle)
- 감지까지
- 2m
- 복구까지
- 12h 47m
증상
10:08 CEST 에 모니터링에 메시징 플랫폼 연결 문제가 보였고, 10:09 에 엔지니어가 이벤트 버스에 데이터를 넣지 못하는 것을 확인했다. 하이퍼바이저의 에이전트, 로드 밸런서의 로그 전달기, 배포가 영향을 받기 시작했다.
모니터링 그래프에서 backlog 가 쌓이는 것이 보였고, 새 프로듀서와 컨슈머가 연결하지 못했다. 10:13 에 읽기가 잠깐 돌아오는 듯했지만 10:18 에는 쓰기가 전혀 없고 backlog 가 멈췄다. 엔지니어들은 10:20 에 클러스터를 고장 상태로 판단했다. 11:36 에는 모든 브로커에서 "Lookup request" 큐가 50k 대기 요청으로 가득 찼다.
브로커 로그에는 소유 브로커를 찾지 못한다는 failed to get active owner broker 와 java.lang.IllegalStateException: The new owner clevercloud-pulsar-broker-c3-n1:8443 is inactive. 오류가 찍혔다. 브로커 프로세스는 죽지 않았으므로 모니터링이 이를 잡지 못했고 롤링 업그레이드는 계속됐다.
브로커가 더 많이 올라올수록 토픽 메타데이터를 찾는 요청이 늘어 클라이언트 쪽에 {"errorMsg":"Failed due to too many pending lookup requests"} 가 담긴 TooManyRequestsException 이 쌓였다. 마지막에는 non-persistent://pulsar/system/loadbalancer-broker-load-data 토픽에서 Failed to get partition metadata 와 java.lang.IllegalStateException: The registry already closed. 가 나며 어떤 토픽도 로드되지 않았다. 엔지니어들은 플랫폼 대역폭이 떨어지는 것을 보고 이를 알아챘다.
설정을 되돌린 뒤에도 브로커가 다시 시작하지 못했다. 어느 브로커에도 배정되지 않은 시스템 토픽이 메타데이터 충돌로 로드되지 않았고, unloaded 상태라 관리 명령으로 지울 수도 없었다. 11:10 부터 고객은 애플리케이션을 배포하지 못했다.
메시징이 멈춘 동안 고객 VM 안의 관측 에이전트 Vector 가 로그를 메모리에 버퍼링했다. 메모리가 작은 VM 은 한도에 닿아 커널에 메모리 압박이 걸렸다. 커널은 디스크 캐시를 비우고 프로세스를 메모리에서 내려 디스크에서 다시 읽었고, 하이퍼바이저 디스크에서 약 25Gbps 의 I/O 가 관찰됐다. 13:35 에 엔지니어들은 하이퍼바이저의 디스크 읽기가 대부분 pico, nano 같은 작은 VM 에서 나오는 것을 봤다. 엔지니어들은 Vector 가 VM 로그를 Pulsar 로 보내지 못해 이 VM 들이 스왑에 들어간 것일 수 있다고 생각했다. 12:30 에는 모든 리전의 거의 모든 하이퍼바이저에서 CPU 부하가 크게 올랐다.
12:35 에 "HV Agent has too many tasks" 모니터링 알림이 올라오기 시작했고, 하이퍼바이저들이 VM 관리 프로세스를 무작위로 죽였다. 일부 로드 밸런서도 죽은 VM 에 포함됐고, 12:38 에 주 API 구성 요소가 OOM 으로 죽었다. 13:05 에는 Clever Cloud API 와 관리 도구가 내려갔다.
12:47 부터 하이퍼바이저들이 커널 패닉으로 재부팅했다. KVM API 와 주고받거나 ext4 디스크에 쓰던 VM 작업이 TASK_UNINTERRUPTIBLE 상태로 기본값 120초를 넘겨 멈추자 khungtaskd 가 패닉을 일으켰다. 사설 네트워크가 끊겼다 붙었다 하며 관측 플랫폼이 몇 분씩 사라졌다. 13:30 에는 관측 클러스터의 핵심 노드 몇이 "the database may have data loss and availability loss" 를 보고하며 잠긴 상태가 됐다.
모니터링은 인프라와 고객 서비스 양쪽에 이벤트를 쏟아 냈고, 그날 배포는 평소의 거의 3배였다. 커널 패닉으로 사라진 인스턴스, 메모리 압박으로 응답하지 않는 VM, CPU 를 덜 받아 load average 가 오른 VM, 늦은 점검으로 데이터가 빠져 도달 불가로 판정된 VM 이 모두 배포나 업스케일을 일으켰다. 서비스가 멈춘 고객들도 다시 배포를 시도했다. 모니터링 인스턴스를 유지보수 모드로 둔 뒤에도 모니터링 작업이 계속 들어와 오케스트레이터 명령 큐가 잘 처리되지 않았고, 16:00 에는 오케스트레이터 작업 일부가 30초 넘게 걸렸다.
원인
원인 설정 변경
- 촉발
- 10:06 CEST 에 데이터 팀이 Apache Pulsar 를 3.3.1 로 올리는 작은 롤링 업그레이드를 시작하면서, 번들 배치를 최적화하는 새 로드 밸런서 TransferShedder 와 extensible unload 전략도 함께 켰다. 첫 브로커가 업그레이드될 때 새 로드 매니저 확장 기능이 제대로 초기화되지 않았고, 브로커들은 부하 메타데이터를 맞추는 시스템 토픽을 만들지 못했다.
감지
10:08 CEST 에 모니터링이 메시징 플랫폼 연결 문제를 보여 줬고, 10:09 에 엔지니어가 이벤트 버스에 데이터를 넣지 못하는 것을 확인했다. 시스템 토픽이 만들어지지 않은 첫 브로커는 죽지 않아 모니터링에 정상으로 보였고, 엔지니어들은 플랫폼 대역폭이 떨어지는 것을 보고 어떤 토픽도 로드되지 않았다는 것을 알았다.
조치
- 엔지니어들이 플랫폼 대역폭이 떨어지고 어떤 토픽도 로드되지 않았다는 것을 알고 unload 방식 변경을 되돌렸다. Pulsar 3.3.1 릴리스는 그대로 유지했다.
- 11:36 CEST 에 메타데이터 충돌로 브로커가 다시 시작하지 못하자 엔지니어링 팀이 클라이언트 프록시를 내려 브로커에 걸린 부담을 덜었다.
- 11:50 CEST 에 배포 담당 팀이 메시징 문제를 피하려고 알림 이벤트를 RabbitMQ 로 보내도록 바꿨다.
- 모든 브로커를 멈추고 하나만 띄워 브로커 사이의 메타데이터 충돌을 막았다. 그 브로커가 배정되지 않은 시스템 토픽을 로드하자 토픽을 지웠고, 모든 브로커가 다시 시작해 10분이 안 되어 평소 상태로 돌아왔다.
- 12:54 CEST 에 메시징 프록시를 재시작했다. 연결이 돌아오고 메시지 생산과 소비가 정상이 됐다.
- 12:39 CEST 에 watchdog 이 실패한 구성 요소를 한꺼번에 다시 띄우지 못하게 멈추고, 상황을 파악하며 구성 요소를 하나씩 시작했다.
- 12:50 CEST 에 저장소 클러스터를 지키려고 Metrics API 수집을 껐다. 버퍼링 덕분에 수집은 계속 받을 수 있었다.
- 자원을 확보하려고 관측 지표의 장기 저장소인 Warp10/FoundationDB 클러스터를 비롯한 덜 중요한 서비스를 멈췄다. 핵심 서비스는 메모리 안의 Warp10 단독 인스턴스로 관측을 이어 갔다.
- 13:35 CEST 에 모든 리전의 모니터링 인스턴스를 전역 유지보수 상태로 돌려 업스케일, 다운스케일, 도달 불가, 디스크 같은 모니터링 작업을 오케스트레이터로 보내지 않게 했다.
- 과부하를 일으키는 VM 을 모아 정렬해 보니 메모리가 작은 VM 이었고, SRE 팀이 이 VM 을 하나씩 죽여 하이퍼바이저를 다시 통제했다.
- 13:50 CEST 에 하이퍼바이저 12대에 작업 일부를 빼내라는 표시를 했고, 아직 자원이 필요한 다른 인스턴스를 위해 일부 로드 밸런서를 내려 CPU 와 메모리를 확보했다.
- 14:08 CEST 에 복구를 앞당기려고 좀비 VM 일부를 정리했다.
- 15:45 CEST 에 모니터링 인스턴스의 알림 큐를 비워 아직 쌓여 있던 모니터링 이벤트가 오케스트레이터 명령 사이로 쏟아져 들어가지 않게 했다.
- 16:05 CEST 에 업그레이드를 위해 비워 두고 세워 둔 EU-FR-1 리전의 새 하이퍼바이저를 투입해 과부하된 하이퍼바이저를 도울 용량을 더했다.
- 16:15 CEST 에 과부하된 하이퍼바이저 위에서 함께 과부하되어 오케스트레이션을 방해하던 RabbitMQ 노드를 클러스터에서 뺐다. 그 뒤 오케스트레이터가 제대로 돌았다.
- 17:06 CEST 까지 모든 리전 L7LB 를, 17:30 까지 모든 L4LB 와 전용 L7LB 를 차례로 재시작했다.
- 18:40 CEST 에 하이퍼바이저 에이전트와 컨트롤 플레인 사이의 통신 오류를 의심해 인프라의 모든 HV 에이전트를 재시작했다. 컨트롤 플레인 이벤트 버스와 통신하지 못하는 것으로 보이는 애드온 공급자 API 도 재시작했다.
- 18:53 CEST 에 stopping 상태로 남은 VM 을 모두 없앴고 애플리케이션 배포가 이어졌다.
- 20:51 CEST 에 Metrics API 수집을 부하를 단계적으로 올리는 QoS 정책과 함께 다시 켰다. 22:53 에 이 정책을 끄고 클러스터가 완전히 정상으로 돌아왔다.
후속 조치
- Pulsar 브로커와 클러스터 상태, 하이퍼바이저 부하와 I/O, 커널 패닉으로 인한 하이퍼바이저 재부팅, 좀비 VM, RabbitMQ 브로커와 클러스터 상태, 배포 큐 소비를 지표로 잡는다. 각 지표를 사건 시각, 감지 시각, 결정 시각, 해결 시각으로 따져 운영이 잘 돌아간 곳과 가시성이나 대응이 모자란 곳을 가려낸다.
- 너무 많은 모니터링 알림을 다루는 방법을 정한다.
- 리전 bastion 하나가 취약하므로 백업 bastion 을 검토한다.
- 컨트롤 플레인 복구 절차를 다시 세운다.
- 모니터링과 오케스트레이션의 연관 관계를 다시 따진다.
- 장애 도메인 분리와 멀티 테넌시의 관계를 다시 검토한다.
- 런타임 이미지와 하이퍼바이저의 역할을 다시 생각한다.
- Pulsar 처럼 여러 차례에 나눠 내보내는 릴리스 업그레이드를 격리한다.
- 런타임 이미지를 다시 설계하고 하이퍼바이저와 더 잘 통합한다.
- 관측 서비스를 리전별로 나눠 이중화한다.
- 작은 VM 의 Vector 설정에서 buffer.max_events 와 buffer.max_size 를 정한다. type=disk 이면 buffer.max_size 는 적어도 256Mo 여야 한다.
- Vector 의 buffer.type 을 기본값 memory 에서 disk 로 바꾼다.
- Vector 의 buffer.when_full 을 기본값 block 에서 drop_newest 로 바꾼다.
- Journald 의 로그 상세 수준과 SystemMaxUse 를 조정한다.
- Cgroups 제한을 걸어 프로세스를 더 잘 통제한다.
- VM 관리자에 I/O 제한을 건다.
- 좀비 VM 을 더 잘 찾아낸다.
교훈
작은 릴리스나 작아 보이는 설정 변경은 큰 릴리스에 쓰는 시뮬레이션 절차를 거치지 않았고, 이번 장애는 그 변경에서 시작됐다. 브로커가 살아 있으면 정상으로 보는 모니터링은 확장 기능의 초기화 실패를 잡지 못했다. Clever Cloud 가 자기 플랫폼 위에서 도는 구조는 평소 이점이 많지만, 이번에는 복구에 필요한 스케줄러와 컨트롤 플레인이 같은 장애에 묶였다. 모니터링이 도달 불가와 CPU 증가에 반응해 배포를 크게 늘렸고, 이 배포가 과부하된 컨트롤 플레인과 인프라를 더 눌렀다. Clever Cloud 는 Pulsar 와 RabbitMQ 의 브로커 상태와 클러스터 상태, 하이퍼바이저 부하와 I/O, 커널 패닉 재부팅, 좀비 VM, 배포 큐 소비를 지표로 삼아 사건 시각, 감지 시각, 결정 시각, 해결 시각으로 따졌다. Clever Cloud 는 이 방식으로 기존 규칙을 다시 따져 볼 수 있었고, 인프라 일부를 고치거나 다시 설계할 수 있다는 것을 알게 됐다고 밝혔다. 여름 휴가철이었지만 Clever Cloud 는 13:00 CEST 에 이미 휴가 중인 사람들까지 불러 대응 인력을 빠르게 늘렸다.
출처
관련 사례
IL-0179DEBUG 로그가 쏟아지자 동기 로깅을 하던 요청 스레드들이 가득 찬 stdout 파이프에서 멈춘 채 DB 커넥션을 쥐고 있어, HikariCP 커넥션 풀이 고갈되고 요청이 30초 주기로 한꺼번에 실패했다.MUSINSA · 2026같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 메시지 브로커
IL-0005새 텔레메트리 서비스가 모든 노드에서 무거운 쿠버네티스 API 요청을 보내 대형 클러스터의 컨트롤 플레인이 무너졌고, DNS 기반 서비스 디스커버리가 깨져 OpenAI 의 모든 서비스가 멈췄다OpenAI · 2024같은 원인 · 공통 텔레메트리 에이전트
IL-0407정리 자동화가 Azure OpenAI 의 GPU VM 과 모델 엔드포인트를 지워 28개 지역 중 14곳에서 5xx 오류가 났다Microsoft Azure · 2024같은 원인 · 공통 자동 용량 관리 시스템
IL-0153DOKS 1.27.6-do.0 과 1.28.2-do.0 워커 노드에서 매일 아침 도는 apt 자동 업그레이드가 15분 타임아웃에 걸려 강제 종료되면서 노드 네트워킹이 망가지고, 노드가 사흘 연속 NotReady 가 됐다.DigitalOcean · 2023같은 원인 · 공통 리눅스 커널
IL-0109로그 수집을 고치려던 EKS 노드 롤오버가 꼬이면서 Auto Scaling 그룹이 정상 워커 노드를 모두 종료해 클러스터에 노드가 하나도 남지 않았다.DFDS · 2023 · sev1같은 원인 · 공통 텔레메트리 에이전트
같은 원인 · 공통 리눅스 커널
내 클러스터에도 있는지 확인하기
AI 도구와 스크립트용
- 이 사례의 JSON: https://incidentlib-api.benchlet.com/cases/IL-0285
- 가장 비슷한 사례들: https://incidentlib-api.benchlet.com/cases/IL-0285/similar
- MCP 서버(Streamable HTTP, 키 없음):
https://incidentlib-mcp.benchlet.com/mcp
API 는 키가 필요 없습니다. MCP 서버는 search_incidents, get_incident, list_incidents, get_topic, vocab 도구를 내놓습니다. 사용법은 API 와 MCP.