본문으로 건너뛰기
스택 토폴로지 — 4컴포넌트 배치·데이터 흐름·MongoDB 최소 배포

스택 토폴로지 — 4컴포넌트 배치·데이터 흐름·MongoDB 최소 배포

스택 토폴로지 — 4컴포넌트 배치·데이터 흐름·MongoDB 최소 배포

한눈에

  • ClickStack은 HyperDX(app+api) · OTel Collector · ClickHouse · MongoDB 4컴포넌트를 2개 Helm 차트(clickstack-operatorsclickstack)로 얹는다. 차트 기본은 모든 스테이트풀 컴포넌트가 단일 인스턴스(PoC용) 이지 HA가 아니다 .
  • operator 분기(중요): 표준 차트가 딸려오는 ClickHouse operator는 ClickHouse Inc. 공식 operator(ClickHouseCluster/KeeperCluster CRD)다. 우리는 이걸 그대로 쓰지 않고 clickhouse.enabled: false(자체(self-hosted) ClickHouse에 연결하는 ‘HyperDX Only’)로 CH/Keeper를 Altinity CHI/CHK로 분리 운영한다 → /hyperdx/04-operator-topology-downtime/.
  • RUM 인제스트 경로에 MongoDB는 없다. 브라우저 → OTLP/HTTP :4318 → Collector → ClickHouse. MongoDB는 UI에서 대시보드/알럿/소스를 만들 때만 쓰인다 — 이게 “MongoDB를 아주 작게 돌려도 되는” 구조적 근거다.
  • MongoDB 최소 배포 형상: 메타데이터 전용이라 단일 멤버 실효 바닥 0.4 vCPU / 0.751.25Gi / gp3 10Gi. 다만 prod는 members:3(≈1.2 vCPU/3Gi, 값싼 보험)에 SCRAM + mongodump CronJob이 실전 권고다.

이 페이지는 HyperDX ClickStack을 실제 K8s에 조립하는 배치 청사진을 다룬다. 4컴포넌트의 정체성·배포 6모드·HyperDX Only 개념은 HyperDX / ClickStack 심층 분석이, 로그 스토어로서의 요약 판단은 로깅 챕터가 이미 다뤘으므로 재나열하지 않는다. 여기서는 각 컴포넌트를 어느 파드로 어디에 얹고, 데이터가 어디로 흐르며, MongoDB를 얼마나 작게 배포할 수 있는지에 집중한다.

1. 배포 토폴로지 개관 — 2 Helm 차트, 그리고 operator 분기

ClickStack 공식 Helm 경로(v2.x)는 순서가 있는 2개 차트로 나뉜다 . operator/CRD를 먼저 깔고, operator가 Ready된 뒤 본체를 올린다.

차트설치물비고
clickstack-operatorsMongoDB Kubernetes Operator(MCK) + ClickHouse Operator 컨트롤러/CRD먼저 설치 필수. CRD: MongoDBCommunity, ClickHouseCluster, KeeperCluster
clickstackHyperDX(UI+API), OTel Collector(공식 OTel Helm 차트를 subchart로), 위 operator가 소비할 CRoperator Ready 이후 설치

차트 기본값의 핵심 관찰은 모든 스테이트풀 컴포넌트가 단일 인스턴스라는 것이다 — CH replicas:1, Keeper replicas:1, MongoDB members:1(2026-07 시점 main 브랜치 기준) . 즉 차트 기본은 PoC/단일노드형이지 HA가 아니다. (rum/07이 짚은 “Helm 기본이 이미 multi-node HA"라는 통념 기각과 정합.) 프로덕션은 스테이트풀 3종을 전부 수동으로 올려야 한다. helm uninstall 시 operator가 만든 PVC는 삭제되지 않으므로(데이터 유실 방지 설계) 제거는 역순 + PVC 수동 정리다 .

operator 분기 — “표준 install ≠ Altinity”

여기서 이 카테고리 전체에 공통되는 분기를 못박는다. 표준 ClickStack 차트가 쓰는 ClickHouse operator는 Altinity operator(ClickHouseInstallation/CHI)가 아니라 ClickHouse Inc.의 신규 공식 operator(ClickHouseCluster/KeeperCluster CRD)다 . 우리 카테고리는 EBS-first + 범용분석 CH 일원화 + 7년+ 트랙레코드의 Altinity operator를 전제하므로(operator 선택 근거 참조), 실제 배치는 표준 차트를 그대로 쓰지 않는다.

# clickstack 차트 values — 우리 케이스: CH/Keeper를 차트 밖으로 분리(HyperDX Only)
clickhouse:
  enabled: false      # ★ 표준 공식 operator를 쓰지 않음. Altinity CHI로 외부 운영
otel-collector:
  enabled: true       # 게이트웨이는 차트로 유지(또는 별도 관리)
# hyperdx api는 MONGO_URI / CLICKHOUSE_* 시크릿으로 외부 CH·Mongo를 참조

clickhouse.enabled: false로 두면 HyperDX는 CLICKHOUSE_*·MONGO_URI 시크릿으로 외부 CH/Mongo를 참조만 하고, ClickHouse/Keeper는 Altinity CHI/CHK로 별도 운영한다. 이 분기를 흐리면 독자가 “표준 install = Altinity"로 오해해 뒤 페이지의 CHI 매니페스트와 어긋난다. CHI/CHK 매니페스트·다운타임 시나리오는 /hyperdx/04-operator-topology-downtime/, hot 스토리지는 /hyperdx/02-hot-storage-ebs/, S3 cold는 /hyperdx/03-s3-cold-tiering/, Keeper 상세는 /hyperdx/05-keeper/에서 이어진다.

왜 표준 차트를 안 쓰나: 공식 operator를 쓰면 우리 클러스터에 CH operator 2종(공식 + Altinity)이 공존하게 되고, 범용분석용으로 이미 운영 중인 Altinity CH와 관측성용 CH의 운영 표면이 갈라진다. enabled:false로 CH를 하나의 Altinity 운영 체계로 일원화하는 편이 운영 부담이 낮다 .

2. 컴포넌트 역할·포트·의존

컴포넌트프로세스/역할리슨 포트의존 방향스테이트
HyperDX appNext.js UI(브라우저 대면)3000(내부; local/compose는 8080)→ api무상태
HyperDX apiNode.js 백엔드(쿼리 오케스트레이션·알럿 평가·OpAMP 서버)8000, OpAMP 4320→ CH(쿼리), → Mongo(메타), ← Collector(OpAMP)무상태
OTel Collector인제스트 게이트웨이(OTLP 수신 → CH export)4317(gRPC), 4318(HTTP), 13133(health), 8888(metrics)→ CH(insert), ← api(OpAMP 4320)무상태(단, in-flight 배치는 메모리 큐)
ClickHouse모든 텔레메트리 저장·쿼리 원천8123(HTTP), 9000(native), 9009(interserver)← Collector, ← api, ↔ Keeper스테이트풀(EBS)
Keeper복제 메타데이터 합의(ZooKeeper 대체)2181(client), 9444(raft) — Altinity CHK 기본(독립형 Keeper 기본값 9181/9234 아님)↔ ClickHouse스테이트풀(gp3) — /hyperdx/05-keeper/
MongoDB앱 메타데이터(user/team/dashboard/alert/source…)27017← HyperDX api스테이트풀(gp3, 소용량)
  • HyperDX는 app(UI) + api(백엔드) 2 프로세스다. local/all-in-one은 단일 컨테이너에 함께 패키징되지만, Helm에서는 app/api 포트가 분리 노출된다 .
  • OpAMP(4320): HyperDX api가 OpAMP 서버로 동작해 Collector 파이프라인 설정을 원격 관리한다. Collector는 OPAMP_SERVER_URL로 api의 /v1/opamp에 붙는다 . 커스텀 Collector config는 CUSTOM_OTELCOL_CONFIG_FILE베이스에 병합되며 신규 receiver/processor 추가만 되고 기존 오버라이드는 안 된다(상세는 rum/01 위임).

아래는 위 표의 역할·의존 관계를 공식 아키텍처 그림으로 정리한 것이다.

HyperDX ClickStack 공식 아키텍처 다이어그램 — App/Infra → OTel Collector → ClickHouse ← HyperDX API ← HyperDX UI·MongoDB, OpAMP 폴링 구조 HyperDX ClickStack 공식 아키텍처 다이어그램 — Your App/Infra(OTel Collector·SDK·FluentBit)가 otel-collector(OpenTelemetry Collector + OpAMP Supervisor)로 텔레메트리를 보내면 otel-collector가 ch-server(ClickHouse)에 적재하고, api(HyperDX API)는 ch-server를 조회·db(MongoDB)에서 메타데이터를 읽으며 Poll OpAMP Configuration으로 otel-collector 설정을 원격 관리한다. app(HyperDX UI)은 api를 거쳐 조회한다. 이 그림은 4컴포넌트 관계의 전체 그림이고, 위 표(역할·포트·의존)와 아래 §3 mermaid(포트·의존을 데이터 흐름으로 구체화)가 그 상세를 잇는다. 출처: hyperdxio/hyperdx — © DeploySentinel, Inc., MIT License

3. 데이터 흐름 — RUM은 MongoDB를 거치지 않는다

RUM 인제스트(쓰기) vs 운영자 조회(읽기) 경로 — MongoDB는 메타데이터 전용

핵심 팩트(집필 시 강조점):

  • 브라우저 RUM SDK는 HyperDX api가 아니라 OTel Collector(4318)로 직접 텔레메트리를 보낸다 . 세션 리플레이(rrweb)는 ClickHouse hyperdx_sessions 테이블로 적재된다 — “MongoDB에 세션이 저장된다"는 통념은 rum/07에서 이미 기각.
  • RUM 인제스트 경로에 MongoDB는 전혀 없다. MongoDB는 사용자가 UI에서 대시보드/알럿/소스를 만들 때만 쓰인다. 이것이 MongoDB를 아주 작게 돌려도 되는 구조적 근거다.
  • 쓰기 경로(Collector → CH)와 읽기 경로(api → CH)가 분리된다. 인제스트 부하와 쿼리 부하가 같은 CH 클러스터를 공유하므로, 대시보드 쿼리 폭주가 인제스트를 밀어낼 수 있다는 점은 캐파 산정(/hyperdx/07-capacity-planning/)에서 다룬다.

4. 우리 케이스 K8s 배치 (mermaid)

표준 차트가 아니라 §1의 분기를 반영한 실제 청사진이다: ClickHouse/Keeper는 Altinity operator 영역(범용분석 겸용), HyperDX는 clickhouse.enabled:false로 HyperDX Only, MongoDB만 MCK(또는 Atlas 위임).

우리 케이스 K8s 배치 — 전체는 Kubernetes(EKS, multi-AZ) 클러스터 내부: Altinity operator 영역(범용분석 겸용 CH) / HyperDX-only(clickhouse.enabled=false) / 메타스토어(택1). S3만 클러스터 외부 cold tier

5. OTel Collector 배치·사이징

5.1 Agent vs Gateway — RUM-only는 게이트웨이만으로 충분

공식 문서는 2역할 패턴을 규정한다 . Agent(edge/sidecar/daemonset)는 노드·호스트에서 로그/메트릭을 긁고, Gateway(standalone deployment, 클러스터/리전당 1)는 단일 OTLP 엔드포인트로 수신해 변환·배치를 담당한다. ClickStack 배포판은 기본 게이트웨이 역할(mode: deployment) 이다.

RUM-only 워크로드는 브라우저 SDK가 게이트웨이 Service로 직접 OTLP를 쏘는 구조라, 노드 로그를 긁는 daemonset agent가 필수가 아니다 . 게이트웨이 deployment(2 replica + Service) 하나면 RUM 인제스트가 성립한다. 서버측 앱 트레이스/로그까지 내재화하는 시점에 daemonset을 추가하면 된다.

5.2 사이징 — 단위는 MB/s (events/s 환산은 추정)

사이징 기준 단위는 처리량(MB/s) 으로 잡는다. 공식 벤더 사이징은 events/s 단위로 “게이트웨이 ~60,000 events/s = 3 core / 12GB이지만, 이벤트당 평균 크기(특히 rrweb 리플레이는 이벤트가 크다)가 미지라 events/s ↔ MB/s ↔ 우리 볼륨 환산은 이상 못 된다.

우리 스케일 감(대략): 월 0.7TB를 인제스트 raw 바이트로 보면 평균 ≈ 0.27 MB/s, 압축 후 on-disk로 보면 raw는 ~수 배(예 6x면 1.6 MB/s)다 — 이 raw/on-disk 해석 자체가 미해결이라 정확한 값은 /hyperdx/07-capacity-planning/에서 두 해석 병기 + 실측으로 확정한다 . 어느 해석이든 **게이트웨이 1대(12 core)면 충분한 저볼륨 구간**이고, Collector는 이 스케일에서 병목이 아니다 . 병목/유실은 처리량이 아니라 아래 큐·백프레셔 설계 실수에서 온다.

5.3 큐·백프레셔·유실 지점 — “durable queue가 기본 존재하지 않는다”

processors:
  memory_limiter: { check_interval: 1s, limit_mib: 2048, spike_limit_mib: 256 }
  batch: { timeout: 1s, send_batch_size: 10000 }   # CH는 큰 배치 선호(≥1,000행)
exporters:
  clickhouse: {}   # 저볼륨이면 연결문자열에 async_insert=1 (+wait_for_async_insert=1)
  • Collector의 sending_queue기본 인메모리다. 파드가 죽으면 in-flight 배치는 소실된다. 디스크 큐잉을 하려면 file_storage extension을 붙여 퍼시스턴트 큐로 만들어야 한다 ✓/≈. ClickStack 배포판 베이스 config에 file_storage가 기본 탑재인지 커스텀 병합으로만 붙는지는 배포 시 실물 config로 확인한다 ?.
  • 이 유실 지점은 /hyperdx/05-keeper/의 “CH가 죽어도 Keeper가 큐잉하지 않는다"와 같은 층위다: 인제스트 파이프라인 어디에도 durable queue가 기본 존재하지 않는다. CH가 잠깐 죽으면 exporter retry → 큐 적체 → memory_limiter가 유입 refuse(백프레셔) → 브라우저 SDK 재시도/드롭 순으로 이어지고, 장시간 CH 다운은 RUM 이벤트 유실이다.
  • 멱등 재시도 안전장치 : 재시도 INSERT가 동일 데이터·동일 순서면 ClickHouse가 중복을 자동 무시한다 → at-least-once 재시도가 중복 폭증을 만들지 않는다.

설계 권고(원료): 게이트웨이 2 replica + memory_limiter + file_storage 퍼시스턴트 큐(gp3 소량) + async_insert. RUM 버스트(세션 리플레이는 이벤트가 크고 몰림)를 흡수하는 건 처리량 여유가 아니라 큐 퍼시스턴스 + replica HA다.

6. MongoDB 최소 규모 배포 (사용자 핵심 질문 — 정면 답)

MongoDB 부하는 데이터 적재량이 아니라 사용자·설정 수에 비례한다(모델 전수·부하 프로파일·무인증 실사고는 rum/07에 위임). RUM을 수년 적재해도 MongoDB는 안 커지고 데이터셋은 수백 MB~수 GB다 ✓/≈. 이 페이지는 그 위에서 “실제로 어느 최소 형상으로 배포하나” 에만 답한다.

6.1 얼마나 작게? — “0.2 CPU/200M"은 함정

MCK 공식 샘플(specify_pod_resources)은 mongod·agent 각각 cpu 0.2 / mem 200~250M를 쓰지만 이건 데모용 극소값이다 . WiredTiger 최소 캐시가 256MB라 200M limit는 실사용에서 OOM 위험이다. WiredTiger 기본 캐시 = max(0.5 × (RAM − 1GB), 256MB), 하한 256MB — 1GB RAM이면 산식상 256MB지만 OS·연결·집계 오버헤드로 위태롭다. mongo 5.0.x는 cgroup 메모리 리밋을 인식하나, 컨테이너에선 storage.wiredTiger.engineConfig.cacheSizeGB명시 고정하는 게 안전하다 (버전별 cgroup v2 인식 회귀 여부는 재확인 여지 ?).

항목데모 극소(비권장)실전 최소 권고
mongod requests0.2 CPU / 200Mi250m / 512Mi
mongod limits0.2 CPU / 250Mi1 CPU / 1Gi
wiredTigerCacheSizeGB(미설정)0.25~0.5 명시
mongodb-agent 사이드카0.2 / 200Mi100200m / 128256Mi
스토리지(PVC, gp3)10Gi(차트 기본; oplog 여유)

MCK 파드는 mongod + mongodb-agent 사이드카 + init 컨테이너 구조라 파드 총합이 mongod 단독보다 크다. 단일 멤버 파드 실효 바닥 ≈ ~0.4 vCPU / 0.751.25Gi / gp3 10Gi . 즉 “0.51 vCPU, 12GB면 되나"라는 감은 정확하다 — 단 200M 데모값은 쓰지 않는다.

6.2 members 1 vs 3 — 무엇이 달라지나

members: 1 (차트 기본)members: 3 (prod 권고)
복제없음(단일 mongod)Primary + Secondary×2, 자동 failover
장애파드 재시작=짧은 다운(EBS 재부착으로 데이터 생존), 노드/AZ 상실·PVC 손상=메타 유실1 파드/노드/AZ 상실 견딤(정족수 2/3)
HyperDX 영향api 메타 연결 상실 → UI 오류·알럿 평가 중단·대시보드 조회 불가(단 CH 인제스트는 계속)무중단(선출 수 초)
비용1× (~0.4 vCPU/1Gi/10Gi)3× (~1.2 vCPU/3Gi/30Gi) — 절대값 소액

메타 데이터셋이 워낙 작아 members:3의 절대 비용이 미미하다(≈1.2 vCPU/3Gi). “메타 유실 = 팀·대시보드·알럿 전면 재구성"이라는 손실이 크므로 3멤버는 값싼 보험이다. 단일 멤버는 staging이나 “백업으로만 지키는” 경우에 한정한다. 그리고 MongoDB 장애는 인제스트가 아니라 설정·알럿·UI를 멈춘다 — CH HA와 별개 축(“가용성·백업” 문제)으로 다뤄야 우선순위가 선다.

6.3 최소 배포 형상 — MongoDBCommunity CR

prod 기준 members:3 + SCRAM + WiredTiger 캐시 고정 + gp3 10Gi + AZ 분산 anti-affinity를 담은 실전 최소 매니페스트다(필드 기준) (operator/mongod 실이미지 태그는 배포 시 helm template로 확인 ?).

apiVersion: mongodbcommunity.mongodb.com/v1
kind: MongoDBCommunity
metadata:
  name: hyperdx-meta
  namespace: hyperdx
spec:
  members: 3
  type: ReplicaSet
  version: "5.0.32"               # ClickStack Helm 관찰값 (mongo 5.0.x)
  security:
    authentication:
      modes: ["SCRAM"]            # SCRAM 기본 활성 — 기본 비번은 반드시 교체
  users:
    - name: hyperdx
      db: hyperdx
      passwordSecretRef: { name: hyperdx-mongo-password }
      roles:
        - { name: dbOwner, db: hyperdx }
        - { name: clusterMonitor, db: admin }
      scramCredentialsSecretName: hyperdx-scram
  additionalMongodConfig:
    storage.wiredTiger.engineConfig.cacheSizeGB: 0.5   # ★ 컨테이너에선 명시 고정
  statefulSet:
    spec:
      template:
        spec:
          affinity:              # AZ 분산: 멤버가 한 AZ에 몰리면 members:3 무의미
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
                - labelSelector:
                    matchExpressions:
                      - { key: app, operator: In, values: [hyperdx-meta-svc] }
                  topologyKey: topology.kubernetes.io/zone
          containers:
            - name: mongod
              resources:
                requests: { cpu: "250m", memory: "512Mi" }
                limits:   { cpu: "1",    memory: "1Gi" }
            - name: mongodb-agent
              resources:
                requests: { cpu: "100m", memory: "128Mi" }
                limits:   { cpu: "250m", memory: "256Mi" }
      volumeClaimTemplates:
        - metadata: { name: data-volume }
          spec:
            accessModes: ["ReadWriteOnce"]
            storageClassName: gp3
            resources: { requests: { storage: 10Gi } }

6.4 인증·백업·버전

  • SCRAM 기본 활성 : hyperdx 앱 유저가 hyperdx DB에 dbOwner, admin DB에 clusterMonitor. 기본 비번(hyperdx)은 placeholder이므로 clickstack-secretMONGODB_PASSWORD로 반드시 교체한다.
  • 백업 = mongodump 자력 : MCK(Community Operator)에는 내장 백업이 없다. Ops Manager 연동 백업·PITR은 Enterprise 전용이다. 따라서 self-host면 mongodump CronJob → S3를 직접 짜는 게 표준이다(메타 소용량이라 덤프 수 초·수 MB). EBS snapshot도 대안이다.
  • 버전 mongo 5.0.32(Helm values 기준) : docker-compose(rum/07)도 mongo:5.0.32-focal로 동일. MCK operator는 구 mongodb-kubernetes-operator → 신 mongodb/mongodb-kubernetes(community+enterprise 통합)로 리네임됐다 — ClickStack이 어느 시점 operator/mongod 태그를 고정하는지는 배포 시 확인이 필요하다 ?.
외부 관리형(Atlas) 위임 — 백업 공백을 통째로 넘긴다

HyperDX는 MONGO_URI 하나만 있으면 되므로 Atlas(SRV 연결문자열)도 그대로 붙는다 .

방식장점트레이드오프
자체 MCK(in-cluster)클러스터 내부·egress 없음·비용 최소HA·백업 자력(mongodump CronJob), operator 운영 부담
Atlas M0(free, 512MB)무료·zero-ops, staging에 이상적shared 티어 제약, prod 부적합
Atlas M10(dedicated, ≈$57/mo , 10GB)자동 백업·PITR·멀티AZ turnkey — Community Operator 백업 공백 제거외부 의존, VPC peering/PrivateLink 필요, 월비용

메타데이터는 소용량 + 지연 무관(인제스트 hot path 아님) 이라 Atlas 위임의 마찰이 작다. “HA·백업을 직접 짜기 싫다"면 Atlas M10이 self-host의 백업 공백을 가장 깔끔히 메운다 (정가는 리전·시점 의존, ap-northeast-2 기준 재확인).

7. 컴포넌트별 가용성 — 역할·다운타임·HA·스케일·무손실 (종합)

§2~6은 각 컴포넌트의 역할·포트·복제·다운타임·MongoDB 최소 배포를 신호별로 흩어 다뤘다. 이 절은 그 세부를 가용성 한 장으로 종합한다 Σ — 컴포넌트마다 (a)무슨 역할인지, (b)죽으면 무엇이 멈추는지, (c)HA·스케일이 가능한지, (d)데이터를 어떻게 무손실로 지키는지를 한 줄씩 맞춰 본다. 개별 메커니즘의 근거·매니페스트·시나리오는 아래 relref로 위임하고, 여기서는 “어느 컴포넌트가 죽으면 관측이 어디까지 멈추나” 라는 운영 판단만 세운다.

한 가지 경계를 먼저 긋는다: 이 절은 가용성 전제만 종합하고, 각 컴포넌트를 실제로 어떤 옵션으로 프로비저닝하나(EBS hot/cold 스토리지·operator 노브·block-only 튜닝)는 뒤 페이지들이 상세히 잇는다. 즉 “무엇을 지켜야 하나"가 이 절, “어떻게 프로비저닝하나"가 다음 페이지들이다.

종합 매트릭스

컴포넌트역할(가용성 관점)상태HA 방식다운타임 시 거동(무엇이 멈추나)무손실 방어스케일 축상세
HyperDX app조회 UI·쿼리 API·OpAMP 서버무상태Service 뒤 replica 2+UI·쿼리만 잠깐 blip — 텔레메트리 적재·저장과 무관 상태 없음(메타=Mongo·텔레메트리=CH) → 자체 유실 개념 없음 수평 replica§2·§4
OTel CollectorRUM ingest 수집·배치·CH export준무상태(+디스크 큐)deployment ≥2 + file_storage persistent queue신규 ingest 정지 → 퍼시스턴트 큐로 완충, 큐 없으면 in-flight 유실 ✓/≈persistent queue(at-least-once) + 백프레셔(memory_limiter) + 클라 재시도 ✓/≈수평 replica§5·/hyperdx/05-keeper/
ClickHouse모든 텔레메트리 저장·쿼리 원천스테이트풀(EBS)RMT 멀티마스터 RF2/3, 2~3 AZ 분산replica 1대 죽어도 나머지가 read+write 계속(승격 없음), 전체 다운 시에만 조회+수집 정지 RF 복제 + insert_quorum + clickhouse-backup shard(용량, 0.7TB/월엔 불필요) / replica(가용성)/hyperdx/04-operator-topology-downtime/·/hyperdx/06-replication-failover/
ClickHouse Keeper복제 조정 메타(로그·part 참조·dedup·DDL 큐)스테이트풀(메타·소량)3노드 정족수, 3 AZ 분산정족수 상실 → CH 쓰기(INSERT/DDL/머지) 정지, 읽기 OK = 쓰기 SPOF 사용자 데이터 아님 · gp3 영속(Raft 메타 생존) · 3노드 정족수 3/5노드(내구성·정족수용, 처리량 아님)/hyperdx/05-keeper/·/hyperdx/06-replication-failover/
MongoDB앱 메타데이터(대시보드·알럿·유저·소스)스테이트풀(소량)ReplicaSet members:3 또는 Atlas설정·알럿 평가·UI만 정지 — 관측(ingest) 데이터와 무관 메타만 · ReplicaSet 복제 + mongodump 백업 불필요(부하∝설정 수, 적재량 무관) §6·/rum/07-hyperdx-mongodb/

“무엇이 죽으면 무엇이 멈추나” — blast radius

컴포넌트별 blast radius Σ

  • HyperDX app 다운 → UI·쿼리만. 브라우저 → Collector → CH 적재 경로는 그대로 흐른다(app은 조회 대면일 뿐 ingest 경로 밖).
  • OTel Collector 다운 → 신규 ingest 정지. file_storage 퍼시스턴트 큐가 있으면 in-flight를 디스크에 붙잡고 복귀 후 재개, 큐가 없으면 그 구간 이벤트 유실.
  • ClickHouse 전체 다운 → 조회 + 수집 둘 다 정지(저장·쿼리 원천이라 가장 광범위). replica 1대만 죽으면 나머지가 계속 서빙한다.
  • Keeper 정족수 상실 → 쓰기(INSERT/DDL/머지) 정지, 읽기는 계속. 데이터 노드가 멀쩡해도 조정 계층 과반 상실만으로 쓰기가 멈추는 유일한 지점.
  • MongoDB 다운 → 설정·알럿 평가·UI. 이미 적재 중인 관측 데이터는 무관.

핵심: 어느 하나의 다운도 “전체 관측 정지"를 뜻하지 않는다 Σ. 광범위한 정지는 CH 전체 다운(저장 원천)과 Keeper 정족수 상실(쓰기 경로)뿐이고, app·Mongo 다운은 조회·설정에 국한된다.

무손실은 두 트랙으로 갈린다

무손실 방어는 한 메커니즘이 아니라 성격이 다른 두 트랙으로 나뉜다. 이걸 뭉뚱그리면 “Keeper가 데이터를 지킨다” 같은 오해가 생긴다.

  • 트랙 1 — 텔레메트리(대량·스트리밍): 브라우저 SDK → OTel Collector file_storage persistent queue(at-least-once, block_on_overflow) → ClickHouse(RMT 복제 RF2/3 + insert_quorum + clickhouse-backup). in-flight 이벤트의 유실 방어는 Keeper가 아니라 앞단 큐 + 클라이언트 재시도가 만든다 — Keeper는 durable queue가 아니라 조정 메타 저장소일 뿐이다(/hyperdx/05-keeper/).
  • 트랙 2 — 메타데이터(소량·문서): MongoDB ReplicaSet(members:3) + mongodump 백업(S3). 적재량과 무관하게 사용자·대시보드·알럿 설정만 지키면 되므로, 복제 + 정기 덤프로 충분하다(/rum/07-hyperdx-mongodb/).

두 트랙의 내구성 메커니즘은 완전히 다르다 Σ: 트랙 1은 스트리밍 파이프라인의 큐 퍼시스턴스 + part 복제로, 트랙 2는 소량 문서 스토어의 ReplicaSet 복제 + 덤프로 지킨다. Keeper 정족수는 트랙 1의 쓰기 가용성을 좌우할 뿐, 그 자체가 이벤트 데이터를 보관하지는 않는다.

스케일 거동

스케일 축도 컴포넌트마다 성격이 다르다 Σ. app·Collector는 수평 replica로 처리량을 늘리고(무상태라 단순 복제), CH replica·Keeper·Mongo는 복제로 가용성을 얻는다(처리량이 아니라 고장 도메인 방어). 용량·쓰기 병렬을 늘리는 축은 CH shard 하나뿐인데, 0.7TB/월 규모에선 shard가 부채이므로 불필요하다(/hyperdx/04-operator-topology-downtime/). 즉 이 스케일에서 늘려야 할 것은 가용성용 replica이지 용량용 shard가 아니다.

이 가용성 전제 위에서 각 컴포넌트를 어떤 옵션으로 프로비저닝하나는 /hyperdx/02-hot-storage-ebs/·/hyperdx/03-s3-cold-tiering/·/hyperdx/04-operator-topology-downtime/·/hyperdx/08-block-only-tuning/가 잇는다. 시점 기준 2026-07.

우리 케이스에서는

배치: 표준 2-차트를 그대로 쓰지 않는다. clickhouse.enabled: false(+ 필요시 otel-collector.enabled: false)로 ClickHouse/Keeper를 차트 밖 Altinity CHI/CHK로 분리하고 HyperDX는 HyperDX Only로 붙인다. 표준 차트의 공식 CH operator를 끌어들이지 않아 범용분석 CH와 운영 체계를 하나로 일원화한다. CHI 매니페스트·다운타임은 /hyperdx/04-operator-topology-downtime/에서 이어받는다.

Collector: RUM-only라 daemonset은 불필요하고 게이트웨이 deployment 2 replica + file_storage 퍼시스턴트 큐(gp3 소량) + async_insert로 간다. 0.7TB/월은 1~2 core로 충분해 처리량은 병목이 아니다 — 유실 방어의 핵심은 큐 퍼시스턴스와 replica HA다.

MongoDB: 물리적으로는 단일 멤버 0.4 vCPU/0.751.25Gi/gp3 10Gi로 돌아간다. 그러나 prod는 members:3(≈1.2 vCPU/3Gi, 값싼 보험) + SCRAM + WiredTiger 캐시 0.25~0.5 고정 + mongodump CronJob(S3) + AZ anti-affinity, 또는 Atlas M10 위임으로 간다. staging은 members:1 또는 Atlas M0. MongoDB 장애는 관측(인제스트)을 멈추는 게 아니라 설정·알럿·UI를 멈춘다 — CH HA와 다른 축의 “가용성·백업” 문제로 우선순위를 잡는다. 시점 기준 2026-07.