2025년 11월 18일, 인터넷에서 운영되는 가장 큰 네트워크 중 하나인 Cloudflare에서 심각한 운영 이벤트가 발생해 광범위한 액세스 문제를 야기했습니다. 직접적인 원인은 내부 시스템 장애였지만, 그 기술적 메커니즘으로 작용한 잠복 버그(latent bug)는 복잡한 분산 시스템을 운영하는 모든 조직에게 커다란 교훈을 주었습니다.
이 글에서는 인시던트 자체가 아니라 모든 조직이 겪는 엔지니어링 도전과제에 초점을 맞춰, 이전에 발생한 적이 없는 중대한 소프트웨어 장애를 어떻게 선제적으로 식별할 수 있을 것인가?하는 질문에 대한 답을 알아봅니다. Cloudflare 인시던트를 연구 사례로 삼아, 엔지니어가 시스템 붕괴 이전의 미묘하고 비정상적인 상태를 감지하기 위해 어떤 고급 옵저버빌리티 옵션을 도입할 수 있는지 자세히 살펴보겠습니다.
잠복 버그로 인한 중단 해부
잠복 버그는 코드에 내장된 오류 조건의 하나로, 휴면 상태로 유지되다가 일상적인 조치로 트리거 됩니다. 트리거되는 조건이 드물거나 운영 환경에 한하기 때문에 표준 테스트 중에는 감지되지 않습니다. Cloudflare 인시던트의 경우 장애가 발생하려면 특정 조건들이 모두 부합해야 했습니다. (이 메커니즘의 기술적 세부 사항은 Cloudflare의 사후 분석에서 확인하실 수 있습니다.)
- 휴면 결함(시스템 제한): 코어 프록시 시스템(FL2)은 봇 관리 모듈 내에 메모리 사전 할당 제한(200개 기능으로 설정)이 하드 코딩되어 있었습니다. 이 제한은 복원력 경계가 아니라 성능 최적화의 일부로 의도되었습니다.
- 루틴 트리거(11:05 UTC): 일상적인 데이터베이스 액세스 제어 변경 사항이 배포되었습니다. 이로 인해 기본 ClickHouse 데이터베이스의 쿼리 동작이 변경되었고, Bot Management 구성 파일을 생성하는 데 사용되는
SELECT쿼리가 r0 스키마에서 중복 열 메타데이터를 반환했습니다. - 대재앙: 불량 쿼리 결과로 인해 기능 수가 크게 증가하여 구성 파일의 크기가 두 배로 증가했습니다. 이 파일이 전파될 때, 프록시의 고정된 200개 기능 제한을 초과하여 Rust 코드 검사가 실패하고 시스템이 패닉
(Result::unwrap() on an Err value)상태에 들어가 HTTP 500 에러가 전역적으로 확산되기 시작했습니다.
트래픽을 처리할 때 발생하는 코딩 오류가 아니라, 사전 할당 제한을 위반한 테스트되지 않은 구성 엣지 케이스로 인해 시스템 전반에서 충돌이 일어나면서 장애가 발생했습니다.
선제적 엔지니어링: 잠복 버그 탐지
비정상적인 시스템 상태가 치명적인 오류로 전환되기 전에 감지하도록 설계된 고급 옵저버빌리티 기술을 사용하면 잠복 버그에 맞설 수 있습니다. 다음은 메트릭, 로그, 트레이스를 사용해 옵저버빌리티 전략을 강화하는 몇 가지 방법입니다.
예측 메트릭 및 사용률 검사 활용
엔지니어는 오류가 나타나길 기다리는 대신, 리소스 한도를 모니터링하여 잠복 버그의 활성화 여부를 예측할 수 있습니다. 4가지 골든 시그널 중 하나인 사용률은 강력한 사전 조치를 제공합니다.
- 구성 입력에 대한 임계값 설정. 제한값을 두고 구성 파일을 로드하는 서비스의 경우 고정된 시스템 제한을 기준으로 입력 크기를 추적할 수 있습니다.
- 애플리케이션: 읽혀지는 기능 수에 대한 예측 임계값 알림(예: 80% 사용률)을 설정하면 구성이 치명적인 한계에 도달하여 개입이 필요할 때 조기 알림을 받을 수 있습니다.
- 메모리 사용률 모니터링. 메모리 사용률 또는 프로세스 힙 크기를 모니터링합니다. 특히 구성 로드 직후에 이 메트릭이 예기치 않게 급증하면 갑작스럽게 비정상적인 워크로드가 처리되고 잠복 버그가 활성화되어 공식적인 충돌이 임박했음을 알 수 있습니다.
변경 사항과 시스템 행동의 상호 연관
장애는 배포의 직접적인 결과였습니다. 엔지니어는 변경 이벤트와 런타임 데이터를 긴밀하게 연관시켜 이러한 간극을 줄일 수 있습니다.
- 변경 추적과 자동화된 로그의 상호 연관. 심각도가 높은 내부 예외 사항을 파이프라인에서 가장 가까운 이전변경 이벤트(예: 11:05 UTC 데이터베이스 배포)와 자동으로 연결하도록 옵저버빌리티 플랫폼을 구성합니다. 이러한 직접적인 연결은 트리거 동작의 평균 식별 시간(MTTI)을 크게 줄여줍니다.
- 변경으로 트리거되는 조기 경보. 중요한 구성의 일부인 데이터 소스에 영향을 미치는 배포의 경우 파일이 전역으로 배포되기 전에 출력 구조와 크기를 검사하는 신세틱 검사를 실행할 수 있습니다.
종속성 및 격리를 위한 분산 추적
분산 추적은 요청 흐름에 대한 가시성을 제공해 팀이 문제의 원인을 격리하고 부차적인 영향을 완화할 수 있도록 합니다.
- 트랜잭션 스팬 레이턴시 파악. 추적을 활용해, 구성 파일을 읽거나 구문 분석하는 내부 트랜잭션 스팬에서 국지적으로 발생한 레이턴시 급증을 파악합니다. 이는 시스템이 완전히 충돌하기 전에 문제에 대한 직접적이고 낮은 수준의 신호가 될 수 있습니다.
- 영향 반경 격리. 추적은 서비스 간 종속성을 시각적으로 매핑해줍니다. 장애의 원인(프록시 서비스)을 식별함으로써 팀은 Workers KV와 Cloudflare Access 같은 종속 시스템에 프록시 바이패스를 구현하는 등 목표에 맞는완화 전략을 명확하게 실행하여, 중단의 영향을 대폭 줄일 수 있습니다.
아키텍처 및 운영 복원력
Cloudflare 인시던트는 잠복 버그가 원치않게 활성화되는 일이 발생하지 않도록 적절한 안전 장치를 갖춘 시스템을 구축해야 한다는 사실을 상기시켜 줍니다. 아키텍처 측면의 이는 코드가 실패할 경우에 대비한 안전망이 되어줍니다.
1. 입력 강화(구성 검증)
구성이 트리거하는 장애를 방지하는 데 효과적인 방안은 입력 강화(Input Hardening)입니다. 내부 시스템에서 생성한 구성 파일을 포함해 모든 구성 파일을 사용자가 생성한 데이터와 동일하게 조사 및 검증합니다. 이렇게 하면 허용 전에 핵심 프로세스에서 구성의 크기, 구조 및 내용에 대한 런타임 검사를 수행해야 합니다.
- 작동 방식: Cloudflare의 경우 검증 단계에서 구성 파일의 기능 수가 $200$을 초과하는 순간 구성 파일을 거부하도록 되어 있었습니다. 이렇게 하면 사이즈를 초과하는 파일이 취약한 코드에 도달하는 것을 방지할 수 있기 때문입니다. 안정성의 토대로서, Google SRE의 운영 서비스 모범 사례는 엔지니어에게 "구성 입력에서 악의적 코드를 검증 및 제거하고 이전 상태에서 계속 운영하며 잘못된 입력이 수신되면 알림이 뜨도록 함으로써 불가능한 입력에 대응할 것"을 권장하고 있습니다.
2. 벌크헤드 패턴
벌크헤드 패턴(Bulkhead Pattern)은 국지적 패닉이 전역으로 하향 확산되는 장애가 되는 것을 방지하는 데 효과적인 아키텍처입니다. 이 패턴은 중요한 시스템을 격리하여 한 구성 요소에서 장애가 발생할 경우 해당 구성 요소에 할당된 리소스만 소비하도록 하여 나머지 애플리케이션을 보호합니다.
- 작동 방식: 여러 다른 다운스트림 서비스에 대한 호출을 처리하기 위해 별도의 스레드 풀을 할당하는 애플리케이션을 생각하면 됩니다. 한 서비스의 레이턴시가 길어지면 벌크헤드가 해당 연결 풀에 할당된 리소스를 제한하여 비즈니스에 핵심적인 구성 요소가 필요한 스레드를 계속 사용할 수 있도록 합니다. 이 설계는 널리 검증되었으며, 애저 아키텍처 센터(Azure Architecture Center)는 소비자와 서비스를 격리하는 경우 하향식 장애를 방지할 수 있다는 이점을 뒷받침해주는 세부적인 근거를 제공합니다.
이번 인시던트는 옵저버빌리티 전략이 자체 검사에서 드러나지 않는 이상 징후를 얼마나 효과적으로 식별할 수 있는지에 따라 사소한 시스템 장애와 전역적 운영 중단의 차이가 생겨난다는 사실을 확인시켜 주었습니다.
잠복 버그에 대적할 준비가 되셨나요?
이 글에서 설명한 예측 메트릭을 구현하려면 코드 배포, 사용률 메트릭 및 분산 추적을 상호 연관시킬 수 있는 통합 풀스택 옵저버빌리티 플랫폼이 필요합니다.
뉴렐릭 플랫폼이 지원하는 엔지니어링 우수성에 대한 문서를 확인해보시기 바랍니다.
이 블로그에 표현된 견해는 저자의 견해이며 반드시 New Relic의 견해를 반영하는 것은 아닙니다. 저자가 제공하는 모든 솔루션은 환경에 따라 다르며 New Relic에서 제공하는 상용 솔루션이나 지원의 일부가 아닙니다. 이 블로그 게시물과 관련된 질문 및 지원이 필요한 경우 Explorers Hub(discuss.newrelic.com)에서만 참여하십시오. 이 블로그에는 타사 사이트의 콘텐츠에 대한 링크가 포함될 수 있습니다. 이러한 링크를 제공함으로써 New Relic은 해당 사이트에서 사용할 수 있는 정보, 보기 또는 제품을 채택, 보증, 승인 또는 보증하지 않습니다.