grpc

8 개의 포스트

모델 서빙의 라우팅 현황 (새 탭에서 열림)

넷플릭스는 대규모 개인화 경험을 제공하기 위해 수백 개의 모델과 초당 100만 건의 요청을 처리하는 중앙 집중식 머신러닝(ML) 모델 서빙 플랫폼을 운영하고 있습니다. 이 플랫폼은 'Switchboard'라는 라우팅 계층을 통해 클라이언트 마이크로서비스와 복잡한 ML 모델 인프라를 분리하여, 클라이언트의 수정 없이도 새로운 모델을 신속하게 실험하고 배포할 수 있는 환경을 구축했습니다. 이를 통해 넷플릭스는 모델 추론뿐만 아니라 데이터 전처리 및 특징 추출을 포함한 전체 워크플로우를 표준화된 API로 추상화하여 혁신의 속도를 높이고 있습니다. ### 넷플릭스의 워크플로우 중심 모델 정의 * 넷플릭스에서 모델은 단순한 추론 함수(`score(features)`)를 넘어, 입력 데이터 변환, 특징(feature) 계산, 추론, 후처리를 모두 포함하는 독립적인 '워크플로우'로 정의됩니다. * 클라이언트는 사용자 ID나 국가와 같은 최소한의 컨텍스트만 제공하며, 모델 서빙 플랫폼이 필요한 데이터를 다른 마이크로서비스에서 가져와 직접 특징을 계산합니다. * 이러한 구조 덕분에 클라이언트는 모델의 내부 로직이나 데이터 의존성을 알 필요가 없으며, 모델의 아키텍처가 변하더라도 클라이언트 코드를 수정할 필요가 없습니다. ### 중앙 집중형 라우팅 엔진, Switchboard * 넷플릭스는 표준 API 게이트웨이나 서비스 메시가 제공하지 못하는 실험 플랫폼과의 통합, gRPC 지원, 도메인 특화 라우팅을 구현하기 위해 자체 프록시 서비스인 'Switchboard'를 개발했습니다. * Switchboard는 클라이언트 요청을 적절한 모델 인스턴스와 클러스터 샤드로 전달하는 역할을 수행하며, 초당 100만 건 이상의 요청을 처리하면서도 높은 가용성을 유지합니다. * 모델 배포 시 섀도 모드(Shadow mode), 카나리 배포(Canary), 롤백 등을 클라이언트 모르게 수행할 수 있어 안전한 운영이 가능합니다. ### 인프라 복잡성을 감추는 모델 샤딩 분리 * 모델은 트래픽 패턴, SLA, CPU/메모리 요구사항에 따라 여러 연산 클러스터 샤드(VIP 주소)에 분산 배치됩니다. * 서빙 플랫폼은 이러한 물리적 배치 상태를 클라이언트로부터 은폐하여, 인프라의 변경이나 모델의 샤드 이동이 클라이언트 서비스에 영향을 주지 않도록 설계되었습니다. * 이를 통해 ML 연구자는 인프라 제약 없이 자유롭게 실험을 설계하고 모델을 배포할 수 있습니다. ### 'Objective' 기반의 추상화 계층 * 플랫폼은 'Objective'라는 열거형(Enum) 단위를 통해 모든 요청을 관리하며, 이는 비즈니스 목적(예: 콘텐츠 추천, 결제 사기 탐지)을 나타냅니다. * Objective는 요청이 전달될 특정 서빙 클러스터와 모델 유형/버전을 결정하는 기준이 됩니다. * 또한, 각 Objective는 고유한 API 규격을 정의하여 서로 다른 도메인의 클라이언트가 동일한 방식으로 플랫폼과 통신할 수 있도록 표준화합니다. 성공적인 대규모 ML 시스템을 구축하려면 모델의 생명주기를 클라이언트 애플리케이션으로부터 완전히 격리해야 합니다. 넷플릭스의 사례처럼 워크플로우 단위의 모델 정의와 'Objective' 중심의 라우팅 추상화를 도입함으로써, 인프라의 복잡성을 관리하면서도 머신러닝 혁신의 속도를 극대화할 수 있습니다.

Evolving our real-time timeseries storage again: Built in Rust for performance at scale (새 탭에서 열림)

데이터독(Datadog)은 급증하는 데이터 볼륨과 고카디널리티(high-cardinality) 워크로드를 처리하기 위해 Rust 기반의 6세대 실시간 시계열 데이터베이스 엔진을 새롭게 설계했습니다. 기존 시스템의 한계를 극복하기 위해 인제스션(Ingestion), 저장, 쿼리 실행 구조를 근본적으로 재구성함으로써 수집 성능은 60배, 쿼리 속도는 최대 5배까지 향상시키는 성과를 거두었습니다. 이 글은 지난 15년간 데이터독이 카산드라에서 시작해 Rust 기반의 전용 엔진에 이르기까지 거쳐온 기술적 진화 과정과 그 과정에서 얻은 교훈을 다룹니다. ### 데이터독 시계열 저장소의 아키텍처 데이터독의 메트릭 플랫폼은 데이터의 효율적인 처리를 위해 실시간 저장소와 인덱스 데이터베이스를 분리하여 운영합니다. * **RTDB (Real-time DB):** `<timeseries_id, timestamp, value>` 형태의 원시 메트릭 데이터를 저장하고 집계하며, 최신 데이터를 실시간으로 서빙합니다. * **인덱스 데이터베이스:** 메트릭 식별자와 태그 정보를 `<timeseries_id, tags>` 형태로 관리합니다. * **데이터 흐름:** 쿼리가 발생하면 상위 서비스가 RTDB와 인덱스 노드에 각각 접속하여 결과를 가져오고, RTDB 노드 내부는 인테이크(Intake), 스토리지 엔진, 스냅샷 모듈, gRPC 쿼리 실행 계층 등으로 구성되어 유기적으로 동작합니다. ### 1세대부터 3세대: 확장성과 운영 효율의 탐색 초기 데이터독은 기성 솔루션을 활용하며 실시간 쿼리 성능과 운영 편의성을 확보하는 데 집중했습니다. * **Gen 1 (Cassandra):** 뛰어난 쓰기 확장성을 제공했으나, 알람 및 분석에 필요한 복잡한 실시간 쿼리를 지원하기 어렵고 대규모 데이터셋 반환 시 효율이 떨어지는 한계가 있었습니다. * **Gen 2 (Redis):** 빠른 읽기 속도와 운영 가시성을 제공했지만, 싱글 스레드 특성상 라이브 트래픽 처리 중 스냅샷 작업이 어려웠고 데이터 직렬화/역직렬화에 따른 CPU 및 메모리 비용이 증가했습니다. * **Gen 3 (MDBM):** `mmap`을 통해 OS 페이지 캐시를 활용하는 메모리 맵 방식의 키-값 저장소를 도입했으나, 대규모 워크로드에서 성능과 정확성 이슈가 발생하며 명시적인 I/O 관리의 필요성을 체감했습니다. ### 4세대와 5세대: 커스텀 엔진과 기능 확장 성능 한계를 돌파하기 위해 범용 DB를 벗어나 전용 스토리지 엔진을 직접 구현하기 시작했습니다. * **Gen 4 (Go 기반 B+ Tree):** Go 언어로 구현된 커스텀 B+ 트리 엔진을 도입하여 '코어당 스레드(thread-per-core)' 모델의 기초를 닦았으며, 처리량과 지연 시간 면에서 큰 진전을 이루었습니다. * **Gen 5 (RocksDB 통합):** 분포 메트릭(distribution metrics)과 DDSketch 타입을 지원하기 위해 RocksDB를 병행 도입했습니다. 하지만 기존 Go 엔진과 RocksDB가 공존하는 구조는 관리가 복잡하고 효율성이 분산되는 결과를 낳았습니다. ### 6세대: Rust 기반의 통합 엔진으로의 전환 파편화된 엔진을 통합하고 성능을 극대화하기 위해 Rust를 선택하여 차세대 시스템을 구축했습니다. * **통합 및 최적화:** 스칼라 값과 스케치 데이터를 모두 처리할 수 있는 단일 엔진을 Rust로 구축하여 언어 차원의 안정성과 고성능 I/O 제어권을 확보했습니다. * **성능 성과:** 이 구조적 변화를 통해 데이터 수집 성능을 60배 높였으며, 피크 시간대 쿼리 속도를 5배 향상시켜 전례 없는 규모의 트래픽을 효율적으로 수용하게 되었습니다. **결론 및 추천** 시스템 규모가 커짐에 따라 범용 데이터베이스나 `mmap`과 같은 추상화 계층은 오히려 성능 병목이 될 수 있습니다. 데이터독의 사례처럼 워크로드의 특성에 맞춰 I/O와 메모리 레이아웃을 직접 제어할 수 있는 전용 엔진을 구축하는 것이 기술적 부채를 해결하고 폭발적인 성장을 뒷받침하는 핵심 전략이 될 수 있습니다. 특히 Rust와 같은 시스템 프로그래밍 언어는 고성능 실시간 시스템을 재설계할 때 강력한 도구가 됩니다.

일 평균 30억 건을 처리하는 결제 시스템의 DB를 Vitess로 교체하기 - 2. 개발 및 운영기 (새 탭에서 열림)

LINE Billing Platform 팀은 일 평균 30억 건의 요청을 처리하는 대규모 결제 시스템을 운영하기 위해 기존 Nbase-T에서 Vitess로 성공적인 데이터베이스 마이그레이션을 수행했습니다. 이 글에서는 성능 문제와 개발 편의성을 고려해 gRPC 대신 MySQL 프로토콜을 선택한 과정과 효율적인 데이터 처리를 위한 샤딩 전략을 상세히 다룹니다. 또한 VTOrc와 Prometheus를 활용한 자동 복구 및 모니터링 체계를 구축하여 분산 데이터베이스 환경에서도 높은 안정성을 확보한 실무 노하우를 공유합니다. ### 프로토콜 선정 및 개발 환경 구축 * VTGate는 gRPC와 MySQL 프로토콜을 모두 지원하지만, gRPC 사용 시 `http2: frame too large` 에러와 CPU 오버헤드가 발생하여 최종적으로 MySQL 프로토콜을 채택했습니다. * Java 클라이언트 사용 시 gRPC 프로토콜은 쿼리 결과를 객체로 변환하는 과정이 번거롭고 Vitess 측에서도 현재 MySQL 프로토콜 사용을 권장하고 있습니다. * 익숙한 MySQL 프로토콜을 사용함으로써 기존 개발 경험을 유지하면서도 Vitess의 샤딩 기능을 안정적으로 활용할 수 있게 되었습니다. ### 키스페이스 설계 및 데이터 처리 방식 * 시스템은 크게 두 개의 키스페이스로 분리되어 있습니다. '글로벌 키스페이스'는 단일 샤드로 구성되어 자동 증가(Auto-increment)하는 샤딩 키를 관리합니다. * 실제 데이터가 저장되는 '서비스 키스페이스'는 N개의 샤드로 분산되어 있으며, 코인 잔액 및 충전/사용 내역 등의 데이터를 저장합니다. * 서비스 키스페이스는 'Hash Vindex'를 사용하여 데이터를 균등하게 분산하며, 애플리케이션이 쿼리에 샤딩 키를 포함하면 VTGate가 해당 샤드를 자동으로 특정해 효율적인 요청 처리가 가능합니다. ### MySQL 호환성 및 주요 기능 활용 * 트랜잭션 격리 수준은 단일 샤드일 경우 `REPEATABLE READ`, 다중 샤드일 경우 `READ COMMITTED`가 적용됩니다. * Vitess는 MySQL 프로토콜을 지원하지만 일부 쿼리 제약 사항이 존재하므로, `unsupported_cases.json`을 통해 사전에 호환성을 확인해야 합니다. * 분산 샤드 간 트랜잭션을 지원하는 'Two-Phase Commit(2PC)' 기능과 쿼리 실행 계획을 분석하는 'VEXPLAIN/VTEXPLAIN' 등을 통해 분산 환경의 제약을 보완하고 있습니다. ### 안정적인 운영을 위한 모니터링 및 장애 복구 * 자동 복구 도구인 'VTOrc'를 도입하여 토폴로지 서버와 VTTablet의 데이터를 기반으로 문제를 자동 감지하고 복구합니다. * Prometheus를 통해 VTOrc의 지표(Metrics)를 수집하며, 장애 발생 시 이메일과 Slack으로 알람이 전달되도록 구성했습니다. * VTAdmin 웹 UI를 활용해 복구 내역을 시각적으로 확인하고, `tablet_alias`를 통해 문제가 발생한 MySQL 노드를 즉각적으로 식별하여 운영 효율성을 높였습니다. 대규모 분산 환경에서 Vitess를 도입할 때는 성능과 유지보수를 위해 gRPC보다는 MySQL 프로토콜 사용을 우선적으로 고려하는 것이 좋습니다. 또한 단일 샤드와 다중 샤드 간의 트랜잭션 격리 수준 차이 및 쿼리 제약 사항을 면밀히 검토하여 애플리케이션 로직을 설계해야 하며, VTOrc와 같은 도구를 적극 활용하여 고가용성 운영 체계를 구축하는 것이 중요합니다.

DDD를 Merchant 시스템 구축에 활용한 사례를 소개합니다 (새 탭에서 열림)

기존의 음식 배달 중심 시스템에서 벗어나 소매 상품 판매에 최적화된 새로운 Merchant 시스템을 구축하기 위해 도메인 주도 설계(DDD)를 도입했습니다. 이번 프로젝트는 DDD가 단순히 코드 구현 기술이 아니라, 도메인의 역할과 책임을 명확히 정의하고 이를 바탕으로 조직 구조와 협업 방식을 설계하는 방법론임을 보여줍니다. 클린 아키텍처와 비동기 이벤트 기반의 모듈 구성을 통해 시스템의 확장성을 확보하고, 글로벌 팀 간의 원활한 협업 체계를 마련하며 성공적으로 시스템을 론칭했습니다. **소매 플랫폼으로의 전환과 도메인 정의** * 기존 시스템의 '음식점 기반 소매 판매' 한계를 극복하기 위해 독립적인 Merchant 시스템을 설계했습니다. * Merchant 시스템은 점포, 상품, 재고 등의 정보를 제공하고, 실제 판매는 '소비자 플랫폼'에서 담당하는 구조로 역할을 분리했습니다. * 핵심 도메인을 점포(shop), 상품(item), 카테고리(category), 재고(inventory), 주문(order)의 다섯 가지로 정의하여 복잡도를 낮추었습니다. **클린 아키텍처를 활용한 시스템 설계** * 도메인 엔티티가 외부 환경의 변화에 영향을 받지 않도록 클린 아키텍처를 채택했습니다. * 모든 팀원이 쉽게 이해하고 따를 수 있는 명확한 계층 구조를 통해 유지보수 편의성을 높였습니다. * 의존성 방향을 내부(도메인)로만 허용하여 비즈니스 로직의 순수성을 유지했습니다. **비동기 기반의 모듈 및 통신 구조** * 시스템을 외부 요청을 받는 'API' 모듈과 비즈니스 로직을 처리하는 '엔진' 모듈로 분리하여 가용성을 높였습니다. * gRPC를 통한 API 제공과 Apache Kafka 기반의 내부 통신을 결합했으며, Decaton 라이브러리를 사용해 파티션 대비 높은 처리량을 확보했습니다. * 플랫폼 특성을 고려하여 즉각적인 응답보다는 최종 일관성(Eventual Consistency)과 빠른 API 응답 능력에 초점을 맞춘 비동기 구조를 설계했습니다. **글로벌 협업과 조직의 일치(Conway's Law)** * 한국 팀은 핵심 도메인(Core)을, 일본 팀은 현지 시스템 연계(Link, BFF)를 담당하도록 조직을 구성해 콘웨이의 법칙을 실천했습니다. * 의사결정 과정과 논의 배경을 기록하는 ADR(Architectural Decision Record)을 활용해 조직 간의 공감대를 형성하고 불필요한 재논의를 방지했습니다. * 추상화된 연계 계층을 통해 새로운 소비자 플랫폼이 추가되더라도 핵심 도메인의 변화는 최소화되는 유연한 구조를 만들었습니다. 성공적인 DDD 적용을 위해서는 헥사고날 아키텍처와 같은 기술적인 구현에만 매몰되지 않는 것이 중요합니다. 도메인의 역할과 책임을 먼저 명확히 정의하고, 그 경계에 맞춰 팀 조직과 소통 구조를 설계할 때 진정한 설계의 이점을 얻을 수 있습니다. 시스템의 아키텍처가 조직의 소통 구조를 반영한다는 점을 인지하고, 기술과 조직 관리의 균형을 맞추는 접근이 권장됩니다.

Breaking up a monolith: How we’re unwinding a shared database at scale (새 탭에서 열림)

Datadog은 성장에 따라 대규모 공유 관계형 데이터베이스가 초래하는 관리 복잡성과 운영 리스크를 해결하기 위해, 공유 데이터베이스를 독립적인 인스턴스로 분리하는 전략을 채택했습니다. 이를 위해 서비스 구축 프레임워크인 'Rapid'와 관리형 Postgres 플랫폼인 'OrgStore'라는 두 가지 핵심 플랫폼에 투자하여, 개별 팀이 운영 부담 없이 직접 데이터베이스를 소유하고 관리할 수 있는 환경을 조성했습니다. 결과적으로 이러한 플랫폼 기반의 접근 방식은 복잡한 데이터베이스 분리 과정을 안전하고 확장 가능한 구조로 전환하는 데 성공했습니다. ### 공유 데이터베이스의 한계와 분리 신호 * **운영 효율의 역설:** 초기에는 단일 데이터베이스가 조인(Join)의 용이성과 낮은 오퍼레이션 비용으로 빠른 제품 출시를 돕지만, 규모가 커지면 데이터베이스 스키마 자체가 API 역할을 하게 되어 변경 시 다른 팀에 미치는 영향을 파악하기 어려워집니다. * **성능 및 안정성 저하:** 단일 머신의 한계를 넘어서는 데이터 크기, 느린 복제 속도, 그리고 특정 서비스의 부하가 전체에 영향을 주는 '노이즈 네이버(Noisy Neighbor)' 문제로 인해 사용자 장애와 성능 저하가 빈번해집니다. * **취약한 스키마 관리:** 한 팀의 스키마 변경이 예상치 못하게 다른 팀의 시스템을 중단시키는 등 데이터 모델 진화가 극도로 위험해지는 시점이 분리의 적기입니다. ### 분리를 가로막는 현실적인 장벽 * **높은 기회비용:** 새로운 서비스를 구축하고 데이터베이스를 이전하는 작업은 분기별 제품 목표 달성을 방해할 만큼 많은 시간을 소요합니다. * **운영 부담의 전이:** 데이터베이스 인스턴스를 직접 소유하게 될 팀에게는 데이터베이스 관리, 백업, 보안 등 추가적인 운영 업무가 큰 부담으로 작용합니다. * **마이그레이션의 난이도:** 기존의 공유 데이터베이스에서 새로운 인스턴스로 데이터를 옮기는 과정이 수동적이고 숙련된 기술을 요하는 '예술적 작업'에 가깝기 때문에 팀들이 선뜻 시작하기 어렵습니다. ### 플랫폼 투자를 통한 해결책: Rapid와 OrgStore * **Rapid 프레임워크:** Datadog 내에서 API 및 gRPC 서비스를 신속하게 구축할 수 있는 표준 프레임워크입니다. 서비스 생성 및 유지보수 비용을 획기적으로 낮춰, 팀이 반나절 만에 새로운 서비스를 배포하고 관리할 수 있게 지원합니다. * **OrgStore 플랫폼:** Postgres 데이터베이스를 관리형으로 제공하는 플랫폼입니다. 팀들이 직접 인프라를 관리하지 않고도 독립적인 데이터베이스 인스턴스를 소유할 수 있게 하여 운영 부담을 제거했습니다. * **구조적 변화:** 이러한 도구들은 "데이터베이스 직접 쿼리"에서 "서비스 API를 통한 데이터 접근"으로의 패러다임 전환을 가능하게 하며, 도메인 간 경계를 명확히 설정할 수 있는 기술적 토대가 되었습니다. ### 성공적인 데이터 분리를 위한 전략 * **기능적 경계 식별:** 데이터베이스를 나누기 전, 기능적 단위로 명확한 도메인 경계를 정의하는 것이 최우선입니다. * **추상화 계층 도입:** 다른 도메인의 데이터가 필요한 경우 데이터베이스에 직접 접근하는 대신, 해당 도메인의 서비스를 통해서만 데이터를 가져오도록 강제하여 의존성을 해소해야 합니다. * **자동화된 마이그레이션:** 수동 작업을 최소화하고 위험을 줄이기 위해 표준화된 마이그레이션 도구와 절차를 구축하여 안전하게 데이터를 이전해야 합니다. 공유 데이터베이스에서 벗어나는 과정은 단순한 기술적 이전을 넘어 플랫폼 공학적인 접근이 필요합니다. 서비스 구축과 데이터베이스 운영 비용을 플랫폼 차원에서 낮추어 주는 것이 팀들이 자발적으로 마이그레이션에 참여하게 만드는 가장 강력한 동기부여가 됩니다.

How we use formal modeling, lightweight simulations, and chaos testing to design reliable distributed systems (새 탭에서 열림)

분산 시스템의 복잡성으로 인해 발생하는 시스템 수준의 설계 오류를 해결하기 위해, 데이터독(Datadog)은 차세대 메시지 큐 서비스인 'Courier'의 설계 과정에서 포멀 모델링(Formal Modeling)과 경량 시뮬레이션을 도입했습니다. 이 방식은 전통적인 단위 테스트나 카오스 테스트가 발견하기 어려운 고차원적인 설계 결함을 설계 단계에서 미리 검증하고, 시스템의 성능 특성을 통계적으로 예측할 수 있게 해줍니다. 결과적으로 이러한 접근법은 가용성과 신뢰성이 필수적인 핵심 인프라 서비스가 복잡한 실패 모드에서도 안정적으로 동작함을 확인하는 강력한 도구가 되었습니다. **포멀 모델링과 경량 시뮬레이션의 도입** - **포멀 모델링(Formal Modeling):** 고수준의 명세 언어를 사용해 시스템의 속성을 기술하고, 모델 체커를 통해 발생 가능한 모든 상태를 전수 조사함으로써 설계상의 논리적 결함이 없는지 검증합니다. - **경량 시뮬레이션(Lightweight Simulation):** 포멀 모델링이 확인하기 어려운 지연 시간(Latency), 비용, 확장성 등의 통계적 성능 지표를 실제 부하 환경과 유사한 조건에서 실행하여 분석합니다. - **도입 배경 및 트레이드오프:** 구현 자체를 검증하지는 못하고 모델 유지 보수의 오버헤드가 발생하지만, 대규모 장애(2023년 3월 사례)를 방지하고 설계의 정확성을 보장하기 위해 도입되었습니다. **차세대 메시지 큐 서비스: Courier** - **배경:** 기존 Redis 기반 시스템의 처리량 및 확장성 한계를 극복하기 위해 설계된 멀티테넌트 메시지 큐 서비스입니다. - **최소 1회 전달(At-least-once delivery):** 메시지 손실 없이 전송을 보장하며, 실패 시 데드 레터 큐(DLQ)로 이동하여 알림 누락을 방지합니다. - **점진적 성능 저하(Graceful Degradation):** 가용 컴퓨팅 자원이 줄어들더라도 처리량이 급격히 추락하지 않고 선형적으로 감소하도록 설계하여 전체 서비스 마비를 방지합니다. - **수평적 확장성:** 컴퓨팅 자원 추가에 따라 처리량이 선형적으로 증가하는 구조를 목표로 합니다. **멀티테넌시 및 고가용성을 위한 아키텍처** - **FoundationDB 기반 샤딩:** 여러 개의 FoundationDB 클러스터를 구축하고, 각 테넌트를 특정 클러스터 조합(예: 8개 중 4개 선택)에 샤딩하여 테넌트 간 간섭을 최소화합니다. - **폭발 반경(Blast Radius) 제어:** 특정 테넌트가 4개의 클러스터에 부하를 주더라도, 다른 테넌트는 최소 25% 이상의 가용 용량을 확보할 수 있도록 격리 수준을 높였습니다. - **브로커 레이어(Broker Layer):** gRPC API를 통해 샤딩 로직을 처리하고, 백엔드 클러스터의 상태 점검(Health Check)을 수행하며 3개의 가용 영역(AZ)에 분산 배치되어 고가용성을 유지합니다. 이러한 포멀 모델링과 시뮬레이션 기법은 복잡한 분산 시스템을 구축할 때 직관에 의존하는 대신 수학적·통계적 근거를 바탕으로 의사결정을 내릴 수 있게 합니다. 특히 Courier와 같이 신뢰성이 최우선인 기반 시스템을 설계할 때, 초기 단계에서의 철저한 검증은 추후 발생할 수 있는 막대한 수정 비용과 대규모 장애 위험을 줄이는 데 매우 효과적인 투자입니다.

How we built the Datadog heatmap to visualize distributions over time at arbitrary scale (새 탭에서 열림)

단순한 백분위수(Percentile) 선 그래프는 데이터의 전체적인 형상과 그 안에 숨겨진 다양한 패턴(Mode)을 왜곡하거나 가릴 수 있습니다. Datadog은 DDSketch 알고리즘을 활용한 히트맵(Heatmap) 시각화를 통해 수조 개의 데이터 포인트를 성능 저하 없이 고해상도로 구현하여, 집계된 지표 뒤에 숨겨진 시스템의 실제 동작을 명확하게 드러냅니다. 이를 통해 엔지니어는 단순 수치 이상의 풍부한 컨텍스트를 파악하고 대규모 인프라의 복잡한 성능 문제를 효과적으로 해결할 수 있습니다. **집계 데이터 시각화의 한계와 히트맵의 이점** * 선 그래프(p50, p99 등)는 수많은 이벤트를 단일 값으로 집계하여 특정 시점의 성능은 보여주지만, 데이터 분포의 전체적인 모습은 설명하지 못함. * 히트맵은 데이터를 과도하게 집계하지 않고 시각화하여, 서로 다르게 동작하는 여러 시스템 그룹(Modes)을 시각적 아티팩트로 분리해 보여줌. * 이를 통해 특정 벤치마킹 서비스로 인한 주기적 지연이나 헬스 체크 요청의 패턴 등 백분위수 그래프에서는 노이즈로 보일 수 있는 현상을 직관적으로 식별 가능함. **무한한 확장을 위한 엔지니어링: DDSketch** * DDSketch를 사용하여 정밀도를 미세하게 희생하는 대신, 방대한 양의 데이터를 '실제 값에 충분히 가까운' 형태로 효율적으로 표현함. * 프론트엔드 전송 시 전체 포인트 목록 대신 '빈(bin)과 카운트(count)' 구조를 사용하여 데이터 페이로드 크기를 일정하게 유지함. * 각 빈의 카운트 저장에 `float32` 타입을 채택하여, 이론적으로 수조 년 동안 매초 발생하는 호출도 수용할 수 있는 수치적 확장성을 확보함. **고해상도 구현 및 데이터 정렬 기술** * 수백조 개의 데이터 포인트를 시각화하기 위해 각 시간 범위(Time bucket)의 경계 값을 일렬로 정렬하고 저장 구조를 최적화함. * 데이터 보고 주기와 히트맵의 시간 버킷 간격이 일치하지 않을 때 발생하는 에일리어싱(Aliasing) 현상을 방지하기 위해 데이터 정렬 알고리즘을 적용함. * 선형 스케일 외에도 로그 스케일을 지원하여 소스 데이터의 해상도에 근접한 시각적 정밀도를 제공함. **색상 설계와 인지적 다이내믹 레인지 유지** * 색상 팔레트는 가독성을 위해 연한 파란색에서 보라색을 거쳐 주황색(Hot)으로 전환되도록 설계하며, 경고 느낌을 주는 빨간색은 의도적으로 배제함. * 인간의 시각이 밝기 차이를 비선형적으로 인지한다는 '스티븐스의 멱법칙(Stevens' Power Law)'을 시각화 로직에 반영함. * 데이터가 멱법칙 분포(롱테일)를 따를 때 선형 색상 보간을 사용하면 정보가 손실되므로, 비선형 보간법을 통해 미세한 빈도의 차이도 눈으로 식별할 수 있게 함. **실용적인 제언** 성능 분석 시 단순히 선 그래프의 추세에만 의존하기보다는 히트맵을 병행하여 사용하는 것이 권장됩니다. 특히 대규모 분산 시스템에서 발생하는 간헐적인 지연이나 특정 노드 그룹의 이상 행동은 히트맵을 통해서만 명확한 '시각적 패턴'으로 드러나기 때문에, 근본 원인 분석(RCA) 시간을 획기적으로 단축할 수 있습니다.

It's always DNS . . . except when it's not: A deep dive through gRPC, Kubernetes, and AWS networking (새 탭에서 열림)

데이터독(Datadog)의 엔지니어들이 서비스 업데이트 중 발생한 원인 불명의 DNS 에러를 추적하며, 쿠버네티스 네트워킹과 AWS VPC 환경의 복잡한 상호작용을 해결해 나가는 과정을 다룬 글입니다. 로그상으로는 단순한 DNS 문제처럼 보였으나, 실제 원인은 AWS VPC의 연결 추적(conntrack) 한계와 하위 네트워크 레이어의 패킷 드랍에 있었습니다. 이 글은 고도화된 인프라 환경에서 단순히 리소스를 증설하는 것보다 커널 수준의 메트릭과 VPC 플로우 로그를 통한 심층 분석이 왜 중요한지를 잘 보여줍니다. **DNS 오류의 표면적 원인과 NodeLocal DNSCache** * 서비스 배포 시마다 DNS 에러가 발생하여 쿼리 지연과 모니터링 성능 저하가 나타났습니다. * 쿠버네티스의 `node-local-dns`가 메모리 부족(OOM) 및 최대 동시 요청 수(`max_concurrent`) 제한인 1,000개에 도달하여 요청을 거부하는 현상이 발견되었습니다. * 하지만 실제 초당 쿼리 수(QPS)는 예상 용량보다 훨씬 낮았으며, 이는 상위 DNS 리졸버와의 TCP 연결 실패로 인해 타임아웃이 발생하면서 동시 요청 슬롯이 빠르게 점유되었기 때문임이 밝혀졌습니다. **AWS VPC 연결 추적(conntrack)과 패킷 드랍** * 네트워크 성능을 정밀하게 확인하기 위해 AWS ENA(Elastic Network Adapter) 메트릭을 분석한 결과, `conntrack_allowance_exceeded` 수치가 급증한 것을 확인했습니다. * VPC 수준의 연결 추적 테이블(Hypervisor 레벨)이 포화 상태에 도달하면 보안 그룹 등의 상태 저장을 위한 연결 생성이 불가능해져 패킷이 드랍됩니다. * 특이하게도 인스턴스 내부의 리눅스 conntrack 엔트리는 6만 개 미만으로 안정적이었으나, VPC 레벨의 conntrack은 이미 한계에 도달하여 두 레이어 간의 가시성 차이가 존재함을 발견했습니다. **VPC 플로우 로그를 통한 심층 분석** * 인스턴스 유형을 상위 모델로 변경하여 임시적으로 문제를 해결할 수 있었으나, 근본 원인 파악을 위해 VPC 플로우 로그 분석을 병행했습니다. * Cilium, 쿠버네티스, AWS 네트워킹이 결합된 환경에서는 역경로 필터링(Reverse Path Filtering)이 정상적인 패킷을 'Martian packet'(출처가 불분명한 패킷)으로 오인하여 드랍하는 등 복잡한 문제가 발생할 수 있음을 시사했습니다. * DNS 전파 시간과 네트워크 마이크로버스트(Traffic Spikes) 역시 이러한 연결 추적 테이블 포화에 기여하는 핵심 요소임을 확인했습니다. **실용적인 결론** 단순히 로그에 나타나는 "DNS 에러"에만 집중하기보다, AWS ENA 메트릭의 `conntrack_allowance_exceeded`나 VPC 플로우 로그와 같은 하위 레이어의 지표를 함께 모니터링해야 합니다. 특히 대규모 쿠버네티스 클러스터를 운영한다면, 인스턴스 크기에 따른 VPC 수준의 conntrack 제한 수치를 미리 파악하고 적절한 인프라 사이징과 네트워크 정책 설정을 검토해야 합니다.