ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 디스크리스 카프카(Diskless Kafka): 브로커가 데이터를 소유하지 않을 때 일어나는 분산 아키텍처의 전환 — KIP-1150과 객체 스토리지 기반 스트리밍

    ARCHIVE 2026. 10. 31. 09:06
    반응형

    아파치 카프카(Apache Kafka)는 지난 15년간 대규모 분산 스트리밍의 표준으로 군림했다. 2011년 링크드인(LinkedIn)의 NetDB 논문에서 제시된 설계 철학은 명확했다. 디스크의 순차 I/O(Sequential I/O), OS 페이지 캐시(Page Cache), 커널 공간에서 네트워크 소켓으로 버퍼를 직접 전달하는 sendfile 제로 카피(Zero-copy)다. 이 구조에서 브로커는 파티션 로그 파일(partition-N.log)을 로컬 디스크에 직접 저장하고, 복제본 상태를 스스로 관리했다.

    온프레미스 베어메탈 서버를 위해 태어난 이 설계는 퍼블릭 클라우드 환경에서 막대한 인프라 비용과 운영 마찰을 일으킨다. 3개 가용 영역(AZ)에 걸쳐 복제본을 유지하는 클러스터는 기가바이트(GiB)당 매겨지는 크로스 AZ 네트워크 전송료를 쏟아낸다. 트래픽 확장을 위해 브로커를 추가하거나 장애 노드를 교체할 때마다 대용량 파티션 데이터를 네트워크로 복사하는 리밸런싱 지옥이 펼쳐진다.

    이 구조적 한계를 깨기 위해 등장한 패러다임이 '디스크리스 카프카(Diskless Kafka)'다. 아파치 카프카 커뮤니티의 KIP-1150(Diskless Topics)을 비롯해 WarpStream, AutoMQ, Redpanda Cloud, Aiven Inkless 같은 차세대 구현체들은 브로커에게서 데이터 소유권을 완전히 박탈했다. 메시지 바이트를 S3 같은 공유 객체 스토리지로 밀어내고 브로커를 계산 전용 계층으로 전환한 디스크리스 아키텍처의 동작 원리와 트레이드오프를 살펴본다.

    🔍 클릭하여 확대
    flowchart TD
        subgraph Classic["클래식 Kafka (KIP-405 Tiered Storage 포함)"]
            direction TB
            P1[Producer] -->|Write| B1[Leader Broker]
            B1 -->|Local Write| L1[(로컬 NVMe / EBS)]
            B1 -->|Cross-AZ 복제| B2[Follower Broker 1]
            B1 -->|Cross-AZ 복제| B3[Follower Broker 2]
            B2 --> L2[(로컬 디스크)]
            B3 --> L3[(로컬 디스크)]
            L1 -.->|Closed Segment 오프로드| S3_Old[(S3 Cold Tier)]
        end
    
        subgraph Diskless["디스크리스 Kafka (KIP-1150 Architecture)"]
            direction TB
            P2[Producer] -->|Write| DB1[Stateless Broker / Agent]
            DB1 -->|L0 Inter-partition Batch| OBJ[(S3 / GCS Object Storage)]
            DB1 -->|좌표 커밋| COORD[Metadata Coordinator<br/>PostgreSQL / SQLite / KRaft]
            OBJ -.->|다중 AZ 자동 내구성 보장| OBJ
        end
      

    1. 기존 Kafka의 설계 한계와 클라우드 청구서의 현실

    클래식 카프카에서 브로커는 연산 노드이자 스토리지 노드다. 프로듀서가 메시지를 보내면 파티션 리더 브로커가 오프셋을 매기고 로컬 디스크의 활성 세그먼트(Active Segment)에 쓴다. 이후 ISR(In-Sync Replicas)에 속한 팔로워 브로커들이 네트워크를 통해 해당 데이터를 복제해 자신의 디스크에 쓴다. 모든 복제본 저장이 확인(acks=all)되어야 프로듀서에게 성공 응답이 반환된다.

    이 방식은 온프레미스 장비에서는 극상의 처리량을 보장했으나, 클라우드 인프라에서는 세 가지 치명적인 경제적/운영적 비용을 청구한다.

    1) 크로스 AZ 네트워크 복제 트래픽 비용

    고가용성을 위해 카프카 클러스터는 3개의 가용 영역(AZ)에 브로커를 분산 배치한다. 복제 계수(Replication Factor)를 3으로 설정하면 데이터는 여러 차례 AZ 경계를 넘는다.
    - 프로듀서가 다른 AZ의 리더 브로커로 전송 (AZ 경계 1회)
    - 리더 브로커가 다른 2개 AZ의 팔로워 브로커로 복제 (AZ 경계 2회)
    - 다른 AZ의 컨슈머가 리더로부터 데이터 수신 (AZ 경계 1회)

    AWS는 리전 내 AZ 간 트래픽에 GiB당 $0.02, GCP는 GiB당 $0.01를 부과한다. 초당 수십만 건의 메시지가 흐르는 엔터프라이즈 환경에서 데이터 인입/복제 네트워크 비용은 브로커 EC2 연산 비용의 2~3배를 훌쩍 넘어선다.

    2) 상태(State) 결합에 따른 확장 병목

    브로커가 디스크에 파티션 데이터를 쥐기 때문에 브로커 스케일아웃은 즉각 이루어지지 않는다. 새 브로커를 클러스터에 투입하면 기존 브로커로부터 대용량 데이터를 네트워크를 통해 복사해 파티션을 재분배(Partition Reassignment)해야 한다. 이 과정에서 대규모 디스크 I/O와 네트워크 대역폭이 소모되어 운영 중인 클러스터의 지연 시간이 치솟는다.

    3) 단일 AZ 블록 스토리지의 내구성 한계

    EBS 같은 클라우드 블록 스토리지는 기본적으로 단일 AZ 내부에서만 복제된다. 데이터센터 수준의 장애를 방어하려면 카프카 자체 소프트웨어 계층에서 AZ 간 복제를 강제해야만 한다. 스토리지가 이미 제공하는 복제 인프라와 카프카의 복제 로직이 중복으로 돌아가며 비용을 가중시킨다.


    2. Tiered Storage(KIP-405) vs Diskless Topics(KIP-1150)

    카프카 진영도 스토리지 비용 문제를 해결하기 위해 KIP-405(Tiered Storage)를 도입했다. 계층형 스토리지는 디스크리스 카프카와 지향점이 완전히 다르다.

    비교 항목 Tiered Storage (KIP-405) Diskless Topics (KIP-1150)
    활성 세그먼트 쓰기 브로커 로컬 디스크 + 팔로워 네트워크 복제 클라우드 객체 스토리지(S3 등) 직접 쓰기
    완료 세그먼트 보존 원격 객체 스토리지로 비동기 오프로드 동일 객체 스토리지에 유지
    복제 담당 주체 카프카 브로커 (ISR 프로토콜) 클라우드 객체 스토리지 인프라
    비용 절감 영역 오래된 데이터의 장기 보존 스토리지 비용 실시간 인입 데이터의 크로스 AZ 복제 네트워크 비용
    성공 응답(Ack) 조건 로컬 디스크 기록 + ISR 복제 완료 객체 업로드 완료 + 메타데이터 커밋 완료
    브로커 상태성 유상태(Stateful, 활성 파티션 디스크 보유) 무상태(Stateless, 연산/캐시)

    Tiered Storage는 이미 기록이 끝난 차가운(Cold) 데이터를 저렴한 S3로 넘겨 디스크 비용을 아끼는 기법이다. 방금 유입되는 뜨거운(Hot) 데이터의 활성 세그먼트는 여전히 브로커 로컬 디스크에 저장되며, 팔로워 브로커로의 크로스 AZ 복제 트래픽은 그대로 발생한다.

    Diskless Topics는 활성 세그먼트 자체를 객체 스토리지에 바로 기록한다. 브로커 간 복제 단계 자체가 제거된다. 데이터 내구성과 멀티 AZ 복제 책임을 S3, GCS 같은 객체 스토리지 엔진에 위임함으로써 크로스 AZ 트래픽 비용을 제거한다.


    3. 디스크리스 아키텍처의 내부 동작 원리

    디스크리스 환경에서 브로커는 데이터를 디스크에 영구 보관하지 않는다. 어떻게 카프카 고유의 오프셋 순서와 파티션 격리를 보장하는가? 핵심은 데이터 바이트와 메타데이터의 완전한 분리다.

    🔍 클릭하여 확대
    sequenceDiagram
        autonumber
        actor P as Producer
        participant B as Stateless Broker
        participant S3 as Object Storage (S3)
        participant C as Metadata Coordinator (SQLite/KRaft/PG)
        actor C_user as Consumer
    
        P->>B: Produce Request (Topic A, B, C 파티션 데이터)
        Note over B: 250ms or 4MiB 버퍼링<br/>(Inter-partition Batch)
        B->>S3: PUT L0 Segment Object (다중 파티션 통합)
        S3-->>B: 200 OK (ETag, Object ID)
        B->>C: Commit Metadata (Object ID, 파티션별 Byte Range, Base Offset)
        C-->>B: Commit Acknowledged
        B-->>P: Produce Response (Success)
    
        Note over C_user,B: 읽기 요청 처리
        C_user->>B: Fetch Request
        B->>C: Look up Offset -> Object ID & Range
        C-->>B: (Object ID, Offset 1024~4096)
        B->>S3: GET Range Request (또는 로컬 메모리 캐시)
        S3-->>B: Raw Bytes
        B-->>C_user: Fetch Response
      

    1) 파티션 간 배치(Inter-partition Batching)와 L0 세그먼트

    객체 스토리지는 파일 쓰기(PUT)와 읽기(GET) 요청마다 요금이 발생한다. AWS S3 표준 기준으로 PUT 요청 1,000건당 $0.005가 든다. 프로듀서가 개별 파티션에 메시지를 보낼 때마다 S3 객체를 생성하면 수천만 원의 API 요청 비용이 발생하고 지연 시간이 폭증한다.

    디스크리스 엔진은 여러 토픽과 파티션으로 유입된 데이터를 메모리에 모아 하나의 거대한 불변 객체(L0 WAL Segment)로 묶어 S3에 업로드한다.
    - WarpStream: 기본 250ms 타임아웃 또는 최대 4MiB 크기 기준으로 배치를 묶음
    - Redpanda Cloud Topics: L0 원시 객체 형태로 직접 플러시

    이 기법을 통해 물리 객체와 논리 파티션 사이의 1:1 대응이 해체된다. 하나의 S3 파일 안에 토픽 A 파티션 0, 토픽 B 파티션 2, 토픽 C 파티션 1의 바이트 스트림이 함께 담긴다.

    2) 메타데이터가 정의하는 논리 로그

    물리 파일이 뒤섞였으므로, 카프카의 파티션 순서와 오프셋은 메타데이터 계층이 정의한다.
    - 메시지 본문(MB 단위 페이로드): S3 객체 스토리지에 불변 저장
    - 논리적 인덱스(수십 바이트 좌표): 메타데이터 코디네이터에 커밋

    코디네이터는 "토픽 X의 오프셋 100~150번은 S3 객체 obj_98234의 4096바이트부터 8192바이트 사이에 위치한다"는 매핑 테이블을 관리한다. 네트워크 합의(Consensus) 대상이 메가바이트 단위의 무거운 메시지 본문에서 작은 메타데이터 좌표로 축소된다.

    메타데이터 코디네이터 구현체는 제품마다 나뉜다.
    - Aiven Inkless: 중앙 분산 PostgreSQL 클러스터를 Batch Coordinator로 채택
    - KIP-1164: 내부 __diskless_metadata 토픽을 원천으로 삼고, 브로커 로컬에 경량 SQLite 인덱스를 유지
    - AutoMQ: 기존 카프카의 KRaft 메타데이터 계층을 재사용하고 앞단에 공유 EBS WAL을 배치
    - Redpanda Cloud: 노드 내부의 경량 Raft 합의 엔진을 결합


    4. 지연 예산(Latency Budget)과 아키텍처 트레이드오프

    무상태성과 비용 절감은 공짜로 주어지지 않는다. 디스크리스 카프카를 도입할 때 반드시 지불해야 하는 대가가 쓰기 확인 지연(Produce Latency)과 읽기 증폭(Read Amplification)이다.

    1) 500ms 지연 예산의 정체

    로컬 NVMe 디스크와 OS 페이지 캐시를 활용하는 클래식 카프카는 acks=all 환경에서도 몇 밀리초(ms)에서 수십 밀리초 안에 쓰기 확인을 끝낸다. 반면 디스크리스 환경의 쓰기 지연은 S3의 네트워크 I/O 특성에 묶인다.

    KIP-1163이 제시한 지연 예산(Latency Budget) 목표치는 다음과 같다.

    [클라이언트 요청] 
          │ 
          ├─ 1. 버퍼링 대기 (경제적 배치 형성): 최대 250ms
          ├─ 2. S3 객체 멀티파트 업로드: P50 ~100ms / P99 200~400ms
          ├─ 3. Coordinator 메타데이터 커밋: P50 ~10ms / P99 20~50ms
          ▼
    [최종 응답 (Produce Ack)]: P50 ~500ms / P99 1~2초
    

    전체 지연 시간 중 절반 이상은 네트워크 병목이 아니라 API 요청 비용을 줄이기 위해 브로커가 데이터를 의도적으로 모으는 버퍼링 시간(250ms)이다. 주문 결제나 사용자 세션 처리처럼 서브세컨드(Sub-second) 응답이 강제되는 동기식 시스템에 디스크리스 카프카를 그대로 물리면 치명적인 지연이 발생한다.

    2) 읽기 증폭과 백그라운드 컴팩션(Reconciler)

    컨슈머가 데이터를 읽을 때, 서로 다른 파티션이 뒤섞인 L0 객체들을 무작정 S3에서 내려받으면 심각한 대역폭 낭비가 발생한다. 특정 파티션의 연속된 오프셋을 읽으려면 다수의 L0 파일에서 조각난 바이트 범위를 개별 HTTP Range GET 요청으로 긁어모아야 한다.

    이 문제를 해결하기 위해 백그라운드 리콘실러(Reconciler) 파이프라인이 동작한다.
    1. L0 단계: 실시간 유입된 다중 파티션 혼합 객체 (빠른 쓰기 우선)
    2. L1 단계: 백그라운드 작업자가 L0 객체들을 주기적으로 읽어 동일 파티션 데이터끼리 모아 단일 파일로 재작성(Compaction & Merge)
    3. 읽기 최적화: 컨슈머는 파티션 정렬이 끝난 L1 객체를 순차적으로 읽어 대규모 순차 I/O 성능을 회복


    5. 실무 도입 전략: 토픽별 하이브리드 패턴

    디스크리스 카프카는 클러스터 전체를 일괄 전환하는 올오어나싱(All-or-Nothing) 기술이 아니다. 아파치 카프카 KIP-1150과 상용 엔진들은 토픽 단위의 저장 모드 분리를 표준 전략으로 권장한다.

    🔍 클릭하여 확대
    graph LR
        subgraph Workloads["워크로드 성격"]
            W1["실시간 주문/결제/RPC<br/>(지연 < 10ms 필수)"]
            W2["사용자 행동 로그/클릭스트림<br/>(수백 ms 허용, 대용량)"]
            W3["DB CDC / 감사 로그<br/>(장기 보존, 비용 민감)"]
        end
    
        subgraph Cluster["단일 하이브리드 Kafka 클러스터"]
            T1["[로컬 토픽 (Local Topic)]<br/>브로커 NVMe + ISR 복제"]
            T2["[디스크리스 토픽 (Diskless)]<br/>S3 직접 기록 + 메타 커밋"]
            T3["[계층형 토픽 (Tiered)]<br/>로컬 활성 + S3 콜드 보존"]
        end
    
        W1 --> T1
        W2 --> T2
        W3 --> T3
      

    토픽별 저장 모드 선택 기준

    스토리지 모드 쓰기 지연 네트워크/스토리지 비용 권장 워크로드
    로컬 모드 (Local) 최저 (< 10ms) 높음 (크로스 AZ 복제 + 고성능 디스크) 금융 결제, 사용자 대면 이벤트, 마이크로서비스 RPC
    디스크리스 모드 (Diskless) 수백 ms ~ 1초 최저 (AZ 복제 없음, S3 직접 영속) 서버 로그, 클릭스트림, 메트릭 텔레메트리, AI 데이터셋 인입
    티어드 모드 (Tiered) 로컬과 동일 중간 (핫 데이터 복제 발생, 콜드 데이터 저렴) 7일 이상 장기 조회가 필요한 실시간 이벤트 스트림

    아키텍처 의사결정 체크리스트

    1. 클라우드 청구서의 크로스 AZ 항목 확인: 자사 인프라 비용에서 가용 영역 간 데이터 전송료가 실제 유의미한 비중을 차지하는지 점검한다. 마이크로소프트 애저(Azure)처럼 AZ 간 전송료가 무료인 환경에서는 디스크리스 카프카의 비용 절감 매력이 급감한다.
    2. 클라이언트 타임아웃 설정: 프로듀서의 delivery.timeout.ms와 request.timeout.ms가 P99 지연 시간(1~2초) 이상으로 넉넉히 잡혔는지 확인한다.
    3. 기능 제약 검증: 현재 상용 디스크리스 구현체들은 압축 토픽(Compacted Topics), 카프카 트랜잭션(Exactly-Once), Kafka Streams 내부 상태 토픽 지원에 기능적 제약을 갖는다. 분석 파이프라인의 단순 수집 경로에 먼저 적용하며 검증 범위를 넓히는 방식이 안정적이다.
    반응형
Designed by Tistory.