pile·
인프라 / DevOps·channel-talk채널톡·

Grafana Mimir에 Kafka를 도입하기 전 미리 알았다면

채널코퍼레이션 DevOps팀이 Grafana Mimir에 Kafka 기반 ingest-storage architecture를 도입하며 겪은 운영 포인트를 정리했다. distributor와 ingester 사이에 durable buffer가 없어 ingester 부하가 곧장 429와 metrics 유실로 번지던 구조를 Kafka로 흡수하려 했고, Mimir 3.0에서 이 구조가 stable·preferred가 된 것도 이유였다. 그런데 Mimir가 Kafka를 쓰는 방식이 일반적인 consumer group 모델과 달라, ingester pod의 ordinal이 곧 Kafka partition number가 되는 1:1 결합에서 예상 못 한 함정이 나왔다.

핵심 포인트
  • Mimir ingester는 정확히 하나의 partition만 consume하고, 어떤 partition을 읽을지는 instance ID 끝의 -숫자에서 결정된다. StatefulSet ordinal이 사실상 partition number다.
  • 같은 partition을 여러 zone의 ingester가 각자 offset을 갖고 동시에 읽는다. replica 설계는 consumer 수가 아니라 partition 수 × zone/owner 수로 생각해야 한다.
  • PoC에서 ingester 리소스가 크게 줄었는데 원인은 RF다. classic은 distributor가 RF=3으로 fan-out하지만 ingest-storage는 partition 하나에만 쓰고 durability는 Kafka topic replication이 담당한다.
  • zone-aware 전환으로 pod 이름이 바뀌자 consumer group이 새로 생겨 committed offset이 없었고, partition 처음부터 replay하며 MSK broker와 ingester가 함께 흔들렸다.
  • scale-in은 replicas만 줄이면 되는 일이 아니다. partition을 ACTIVE에서 INACTIVE로 바꿔 write를 멈추고 drain을 기다린 뒤 내려야 한다.
상세 정리
  • 도입 배경 1: classic pipeline에는 distributor와 ingester 사이 backpressure를 흡수할 durable buffer가 없어 ingester capacity 기준으로 distributor rate-limit을 잡았다. 운영 중 429가 몇 차례 발생해 그만큼 metrics 유실이 있었고, 반대로 limit을 느슨히 잡으면 ingester 자체가 흔들렸다.
  • 유실 경로 두 가지: write quorum 실패가 길어지면 Prometheus가 5xx를 재시도하는 동안 backlog가 쌓이고 2시간 뒤 WAL compaction에서 미전송분이 사라질 수 있다. 또 rate-limit을 넘긴 요청은 distributor가 429로 drop하는데 Prometheus는 기본적으로 429를 재시도하지 않아 retry_on_http_429를 켜지 않았다면 즉시 유실된다.
  • Loki도 유사한 문제를 안고 있었다. otel-collector-gateway의 sending_queue가 memory 기반이라 upstream 전송 성공 시점과 Loki 저장 시점이 다르고, gateway가 restart나 OOM되면 미전달 logs가 사라진다.
  • 구조 변화: write path의 1차 도착지가 Kafka가 되면서 distributor capacity를 ingester 즉시 처리량이 아니라 Kafka produce throughput·replication·broker capacity 기준으로 설계할 수 있게 됐고, 일시적 ingester 지연은 consumer lag로 흡수된다.
  • 리소스 측정: 같은 remote_write 트래픽을 dual-write해 비교했을 때 distributor ingestion rate는 classic 약 313k samples/s, Kafka PoC 약 308k samples/s로 거의 같았지만 ingester가 처리하는 양이 크게 달랐다. classic은 RF=3이라 ingester 전체 입장에서 약 941k samples/s를 받는다.
  • 다만 RF=1은 distributor write path와 ingester가 들고 있는 series 관점의 이야기다. zone-aware replication을 쓰면 같은 partition을 여러 zone owner가 consume해 S3 block은 owner 수만큼 생기고, 이 중복은 compactor의 vertical compaction이 정리한다. 진짜 이득은 ingester가 in-memory TSDB head와 local disk에 즉시 들고 있어야 할 부담이 줄어드는 데 있다.
  • partition 수 산정: topic partition 수가 최소 한 zone의 ingester 수 이상이어야 한다. ordinal이 partition number가 되므로 partition 6을 읽는 ingester를 만들려면 topic에도 partition 6이 있어야 한다.
  • PoC 구성: Kafka partition 7개에 3-zone zone-aware. Helm에서 ingester.replicas 21을 주면 zone별 StatefulSet이 replicas 7로 렌더링돼 총 21 pod, partition당 통상 owner 3이 된다.
  • 헷갈리기 쉬운 설정: ingester.partition_ring.min_partition_owners_count는 partition이 ACTIVE가 되기 전 최소 owner 수를 뜻할 뿐, partition 개수나 pod 배치를 만들어주지 않는다. single StatefulSet에 replicas 12와 min owners 2를 준다고 6 partition × 2 owner가 되지 않는다.
  • chart 제약: mimir-distributed 6.0.6에서 zoneAwareReplication.enabled=true면 zone을 최소 3개 정의하도록 template validation이 걸려 있어, 모델상 partition당 2 owner가 가능해도 chart values만으로는 2-zone 구성이 깔끔히 안 나와 3-zone으로 갔다.
  • 왜 이런 제약인가: ingester는 단순 consumer가 아니라 read path에도 관여하는 stateful component다. querier가 partitions ring으로 어느 partition에 series가 있는지 판단하고 ingesters ring으로 그 partition을 소유한 healthy ingester를 찾으므로, ownership이 rebalance로 자유롭게 옮겨 다니면 곤란하다. ownership을 ring과 ordinal로 명시해 운영 파라미터를 단순화한 선택이다.
  • 개수 불일치 시: partition이 ingester보다 많으면 남는 partition에 owner가 없어 사실상 안 쓰이고, ingester가 더 많으면 남는 pod가 자기 ordinal에 해당하는 partition을 못 찾아 startup에서 대기하거나 에러를 낸다.
  • backfill storm: 이름이 바뀌어 새 consumer group이 생기자 last-offset 설정에서 committed offset이 없어 partition start부터 읽기 시작했다. 로그의 starting consumption from partition start 메시지, MSK Fetch throttling, BytesOut 급증, receive delay와 lag 증가, lag 15초 초과 시 readiness false가 증상이었다. 목적이 backlog 재처리가 아니었으므로 startup position을 end로 명시해 replay를 건너뛰었다.
  • scale-in 실측: chart의 prepareDownscale는 당시 path가 ingester/prepare-shutdown으로 하드코딩돼 있었는데, ingest-storage에서 필요한 primitive는 /ingester/prepare-partition-downscale이었다. 이 endpoint가 partition을 ACTIVE에서 INACTIVE로 바꿔 distributor write를 멈춘다.
  • rollout-operator 함정: min-time-between-zones-downscale=12h는 대상 zone 자신의 마지막 downscale이 아니라 같은 rollout group 내 다른 StatefulSet들의 last-downscale을 본다. rollout-downscale-leader annotation 때문에 zone-a → zone-b → zone-c 체인이 생겨, zone-c만 수동으로 줄이면 controller가 leader 상태를 보고 replica를 되돌릴 수 있다.
  • 작성한 scale-in runbook: prepare-partition-downscale 호출 → distributor에서 해당 partition write 중단 확인 → reader request/offset/lag 정지 확인 → 충분한 시간 후 replicas 감소.
  • read consistency: distributor가 Kafka write 후 성공을 반환하고 ingester는 비동기 consume이라, write 직후 데이터가 query에서 즉시 보인다고 가정할 수 없다. read-after-write가 필요한 ruler 같은 곳은 X-Read-Consistency strong 헤더로 최신 offset까지 consume을 기다리게 할 수 있으나 lag가 크면 query latency 증가나 timeout으로 이어진다.
  • 새로 봐야 하는 지표: broker BytesIn/BytesOut, Fetch throttling, partition별 consumer lag, cortex_ingest_storage_reader_receive_delay_seconds, last_consumed_offset, ingester startup lag와 readiness 지연, distributor Kafka produce error와 latency.
  • 비용 관점 단서: PoC 수치는 ingester 계층 절감만 보여줄 뿐, Kafka/MSK broker·storage·network와 운영 비용이 새로 붙으므로 전체 스택 총비용 감소를 뜻하지 않는다고 명시했다.
왜 읽나Mimir나 Loki 계열 관측 스택에 Kafka ingest-storage를 도입하려는 인프라·SRE 엔지니어가 partition 설계, consumer group 전환, scale-in 절차에서 밟을 함정을 미리 확인할 수 있다.
channel-talk
채널톡 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 인프라 / DevOps·AWS KoreaAWS Korea Tech·

    엔터프라이즈 보안 요구사항을 충족하는 프라이빗 Amazon Bedrock AgentCore 구축하기

    Amazon Bedrock AgentCore의 VPC egress 기능(2026년 4월 추가)을 활용해 온프레미스 LLM·사내 IdP·사내 MCP 서버에 인터넷 노출 없이 연결하는 방법을 다룬다. 규제 산업 엔터프라이즈가 기존 사내 자산을 그대로 유지하면서 Bedrock AgentCore를 안전하게 구축하기 위한 구성 가이드다.

    요약 이어보기
    #mcp#amazon-bedrock#vpc+2
  2. 인프라 / DevOps·gitlab-engGitLab Blog·

    OpenTofu와 Argo CD로 구성하는 GitLab 기반 AWS 제어 플레인

    GitLab을 단일 제어 플레인으로 삼아 OpenTofu로 AWS 인프라를 프로비저닝하고, Argo CD로 GitOps 기반 애플리케이션 배포까지 자동화하는 엔드투엔드 튜토리얼이다. VPC·EKS 클러스터 구성부터 Helm 기반 툴 설치, 샘플 앱 배포까지 모든 과정이 GitLab CI/CD 파이프라인으로 연결된다.

    요약 이어보기
    #kubernetes#aws-eks#gitops+2
  3. 인프라 / DevOps·AWS KoreaAWS Korea Tech·

    Amazon Bedrock 기반 사내 LLM, 키 발급부터 비용 차단까지: F&F의 LiteLLM 게이트웨이 운영 사례

    패션 기업 F&F가 Amazon Bedrock과 LiteLLM 프록시를 결합해 구축한 사내 LLM 플랫폼 운영 사례다. API 키 셀프서비스 발급, 모델별 접근 승인 워크플로, 사용자·프로젝트별 예산 자동 차단까지 전 과정을 직접 구현한 아키텍처 결정과 운영 교훈을 공유한다.

    요약 이어보기
    #kubernetes#amazon-bedrock#litellm+2