Incident Library
적용된 필터 증상메모리 압박기여 요인재시도 폭주모두 풀기검색어 없이 필터만 적용한 목록입니다. 최근 사례부터입니다.
추천 필터 검색하면 검색어에서 찾은 분류 값이 여기에 나옵니다.

그래프

  • 원인
  • 구성 요소
  • 증상
  • 기여 요인
  • 사례

사례2건

2건 중 1~2번째

  1. 증상

    DNS 오류율과 서버 부하가 늘었다는 알림이 울렸다. 일부 AdGuard DNS 사용자는 DNS 조회가 느려지거나 실패했고, 타임아웃과 SERVFAIL 응답을 받았다.

    촉발

    AdGuard 는 11월 25일에 사용자 데이터 캐시 방식을 개선하려는 새 AdGuard DNS 버전을 배포했다. 버그 때문에 리졸버가 로컬 캐시 파일에 전체 사용자 데이터가 아니라 최근에 바뀐 일부만 저장했다. 다시 시도한 배포에서 많은 리졸버가 한꺼번에 전체 동기화를 시작했다.

    원인
    구성 요소
    기여 요인
    감지

    15시 30분에서 16시 UTC 사이, 두 번째 배포를 시작한 뒤 DNS 오류율과 서버 부하가 늘었다는 알림이 울렸다.

    조치
    • 버그가 있는 버전을 모든 서버에서 동시에 롤백했다. 롤백은 17시 30분에서 18시 UTC 사이에 끝났다.
    • 암스테르담의 트래픽 일부를 다른 유럽 거점으로 돌렸다. 암스테르담은 안정됐지만 프랑크푸르트와 런던의 부하가 늘었다.
    • 프랑크푸르트와 런던에서 실제 연결 동시성과 파이프라인 깊이를 줄였다. 프랑크푸르트에서 파이프라인 깊이를 5에서 1로 줄이자 매우 빨리 회복됐다.
    • 한도를 실제 하드웨어 용량에 맞게 조정했다.
    • 전체 동기화가 더 일어나지 않도록 손상된 캐시 파일과 사용자 데이터 스냅샷을 고쳤다.
    • 트래픽 분배를 정상으로 돌렸고 오류율이 평소 수준으로 내려왔다.
    후속 조치
    • 전체 사용자 데이터가 로컬 캐시 파일에 제대로 직렬화되고 그 파일에서 제대로 복원되는지 확인하는 자동 테스트를 넣는다. 캐시가 비었거나 잘린 것도 잡아내게 한다.
    • 실제와 비슷한 부하에서 빈 캐시나 손상된 캐시로 리졸버를 시작하는 통합 테스트를 넣어, 시스템이 무리 없이 동작하고 비즈니스 로직 서비스에 과부하를 주지 않는지 확인한다.
    • 거점마다 서버 하드웨어 사양을 하나로 맞춰 RAM 크기가 크게 다른 서버가 한 클러스터에 섞이지 않게 하거나, 하드웨어 종류마다 설정을 따로 관리한다.
    • 표준 노드 종류마다 connlimit, 캐시 크기, 연결 한도를 다시 살펴 조정해 32 GiB 노드와 64 GiB 노드가 모두 안전한 가비지 컬렉션과 메모리 범위 안에서 돌게 한다.
    • 최대 부하에서도 고루틴과 힙이 지나치게 늘지 않도록 파이프라이닝 깊이를 다시 따져 보고 필요한 곳은 낮춘다.
    • 연결 수와 고루틴 수를 제한하는 방식을 다시 따져 보고, 자원 사용을 적절히 제한하면서도 연결이 끊긴 뒤에도 처리량이 충분히 나오게 한다.
    • 모니터링이 CPU 와 전체 메모리뿐 아니라 Go 힙 크기, 가비지 컬렉션 시간, 초당 가비지 컬렉션 횟수, 클러스터별 요청 지연 분포도 보게 넓힌다.
    • 상위 DNS 가 정상인데 SERVFAIL 비율과 요청 처리 시간이 계속 오르면 울리는 알림을 따로 둬, 내부 경합과 가비지 컬렉션 문제를 사용자가 겪기 전에 잡는다.
    • DNS 리졸버의 배포와 롤백 절차를 다듬어 전체 서버의 큰 부분에서 캐시가 동시에 무효화되지 않게 한다.
    • 암스테르담과 프랑크푸르트에서 본 동작을 바탕으로, 사고 중에 파이프라인 깊이, 연결 한도, connlimit 을 빨리 조정하는 플레이북을 문서로 만들고 연습한다.
    교훈

    노드마다 다르게 움직인 데에는 사용할 수 있는 RAM, Go 가비지 컬렉터, connlimit 설정이 서로 맞물린 것이 컸다. 메모리가 큰 서버에서 connlimit 을 너무 높게 잡으면 힙이 크게 자란 뒤에야 가비지 컬렉션이 강하게 돈다. 그러면 메모리는 남아도 CPU 시간이 가비지 컬렉션에 점점 더 쓰여, 지연이 늘고 처리량이 준다. AdGuard 는 이것을 메모리를 많이 쓰는 애플리케이션에서 connlimit 이 만드는 알려진 최악의 경우라고 했다. 메모리가 작은 서버는 캐시 크기와 연결 한도를 RAM 에 맞춰 줄이지 않아서 더 일찍 실패했다. 여기에 높은 파이프라이닝과 많은 재시도가 겹쳐 가비지 컬렉션 압박, 연결 포화, 클라이언트 재시도가 서로를 키우는 고리가 생겼다.

  2. 증상

    10:08 CEST 에 모니터링에 메시징 플랫폼 연결 문제가 보였고, 10:09 에 엔지니어가 이벤트 버스에 데이터를 넣지 못하는 것을 확인했다. 하이퍼바이저의 에이전트, 로드 밸런서의 로그 전달기, 배포가 영향을 받기 시작했다.

    촉발

    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 에 이미 휴가 중인 사람들까지 불러 대응 인력을 빠르게 늘렸다.

내 클러스터에도 있는지 확인하기

이 2건에서 가장 많이 나오는 구성 요소: 자동 용량 관리 시스템, 언어 런타임 설정. kubegap 은 Claude Code 나 Codex 에서 쿠버네티스 클러스터를 읽기만 하며 이런 틈을 점검합니다. 점검 항목의 근거는 이 라이브러리와 같은 공개 보고서입니다.

원인별2