ClickStack: Clickhouse ๊ธฐ๋ฐ˜ APM

[์›๋ณธ ๋งํฌ]

Clickhouse๋Š” ๊ทผ๋ž˜ ๊ฐ€์žฅ ํ•ซํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ ์ค‘ ํ•˜๋‚˜๋‹ค.
์š”์ฆ˜ APM ํ™˜๊ฒฝ์œผ๋กœ๋„ ๊ฐ๊ด‘๋ฐ›๊ณ  ์žˆ๋Š”๋ฐ, ํŠนํžˆ ๋Œ€๊ธฐ์—…์—์„œ ๋งŽ์ด ์“ฐ๋”๋ผ.

Clickhouse๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠน์žฅ์ ์ด ์žˆ๋‹ค.

  1. ๋งค์šฐ ๋†’์€ ์Šคํ† ๋ฆฌ์ง€ ์ €์žฅ ํšจ์œจ: ์••์ถ•์„ ๋นก์„ธ๊ฒŒ ํ•˜๊ธฐ ๋•Œ๋ฌธ

  1. ๋งค์šฐ ๋†’์€ ์„ฑ๋Šฅ์˜ ์ฟผ๋ฆฌ ์„ฑ๋Šฅ: ๋Œ€์‹  ๋™์‹œ ์ฟผ๋ฆฌ ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ ์ง€๋งŒ, APM ์ž์ฒด์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์— ์ƒ์‡„๋จ

  1. ๋‚˜์˜์ง€ ์•Š์€ ์„ฑ๋Šฅ์˜ INSERT ์ฒ˜๋ฆฌ๋Ÿ‰: ์นด์‚ฐ๋“œ๋ผ ๊ฐ™์€ ๊ณ ์„ฑ๋Šฅ KV์— ๋น„ํ•  ๋ฐ”๋Š” ์•„๋‹ˆ์ง€๋งŒ, async insert ๋“ฑ ๋ฒ„ํผ๋ง ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฝค ์ฒ˜๋ฆฌ๋Ÿ‰์ด ์ข‹์Œ

  1. ์ปฌ๋Ÿผํ˜• ์ €์žฅ๊ตฌ์กฐ

  1. ์‹œ๊ณ„์—ด ๋ฐ์ดํ„ฐ์— ์œ ๋ฆฌํ•จ: ํŒŒํ‹ฐ์…˜ํ‚ค๋ฅผ ํƒ€์ž„์Šคํƒฌํ”„ ๊ธฐ๋ฐ˜์œผ๋กœ ์„ค๊ณ„ํ•˜๋ฉด ํšจ์œจ์ ์ธ ํ˜•ํƒœ๋กœ ์ ์žฌ/์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅ

  1. ๋‹จ์ผ ์†Œ์Šค๋กœ ๊ด€๋ฆฌํฌ์ธํŠธ ํ†ต์ผ ๊ฐ€๋Šฅ (Loki, Prometheus, Tempo 3๊ฐœ๋ฅผ ๋™์‹œ์— ๋„์›Œ์„œ ๊ด€๋ฆฌํ•ด์•ผํ•˜๋Š” ๊ด‘๊ธฐ์—์„œ ๋ฒ—์–ด๋‚  ์ˆ˜ ์žˆ์Œ)






์•„ํ‚คํ…์ณ

๊ธฐ๋ณธ ๊ตฌ์„ฑ์š”์†Œ๋Š” ์‹ฌํ”Œํ•œ ํŽธ์ด๋‹ค.
Clickhouse๋ฅผ ๋‹จ์ผ ์Šคํ† ๋ฆฌ์ง€๋กœ ์‚ฌ์šฉํ•˜๊ณ , Otel ์—์ด์ „ํŠธ๋กœ ๋กœ๊ทธ๋ฅผ ์˜๊ณ , HyperDX๋ผ๋Š” ๋Œ€์‹œ๋ณด๋“œ๋กœ ๋กœ๊ทธ๋ฅผ ๋ณด๋Š” ์‹์ด๋‹ค.

๋งค์šฐ ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰์„ ๊ฐ๋‹นํ•˜๊ธฐ ์œ„ํ•ด์„œ ์•ž๋‹จ์— ์นดํ”„์นด ๊ฐ™์€๊ฑธ ๋ถ™์ด๊ธฐ๋„ ํ•˜๊ณ , ์Šคํ† ๋ฆฌ์ง€ ๊ธฐ๋ฐ˜์˜ ๊ณ„์ธตํ™” ๊ตฌ์„ฑ์„ ํ•˜๊ธฐ๋„ ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋‹จ ๊ฐ€๋ณ๊ฒŒ ์‹œ์ž‘ํ•˜๊ธฐ์—๋Š” ์ด ์ •๋„๋กœ๋„ ์ถฉ๋ถ„ํ•˜๋‹ค.

๋Œ€์‹œ๋ณด๋“œ์˜ ์˜คํ”ผ์…œ ์„ ํƒ์ง€๋Š” HyperDX์ธ๋ฐ, HyperDX ์™ธ์—๋„ Grafana, Signoz๋ฅผ ๋Œ€์•ˆ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ทจํ–ฅ์— ๋งž์ถฐ์„œ ๊ณ ๋ฅด๋ฉด ๋œ๋‹ค.
HyperDX๋Š” clickhouse์—์„œ ์ธ์ˆ˜ํ•ด์„œ ๊ด€๋ฆฌํ•˜๋Š” ์ค‘์ด๊ณ , Signoz๋Š” ํ‰์ด ๊ทธ๋ ‡๊ฒŒ ์ข‹์ง„ ๋ชปํ•œ ๊ฒƒ ๊ฐ™๋”๋ผ. Grafana๋Š” Clickhouse์šฉ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์„ค์น˜ํ•˜๋ฉด ๋ถ™์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ์•„์ฃผ ํŠนํ™”๋˜์–ด์žˆ์ง„ ์•Š๋‹ค.
๊ทธ๋ž˜์„œ Grafana + HyperDx๋ฅผ ๋ณ‘ํ–‰์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋ก€๊ฐ€ ๋งŽ์€ ๊ฒƒ ๊ฐ™๋‹ค.

์ฐธ๊ณ ๋กœ HyperDX๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ/์„ค์ • ๊ด€๋ฆฌ์— MongoDB๋ฅผ ์“ฐ๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ๊ฐ’์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋งค์šฐ ๋†’์€ ์ฒ˜๋ฆฌ๋Ÿ‰๊ณผ ๋น„์šฉ ํšจ์œจ์„ฑ์„ ์›ํ•œ๋‹ค๋ฉด, ์ด๋Ÿฐ ์‹์œผ๋กœ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ์“ฐ๊ธฐ ์ฒ˜๋ฆฌ๋Ÿ‰ ๊ฐ€๋“œ ๊ณ„์ธต: ์นดํ”„์นด ๊ฐ™์€ ๊ณ ์„ฑ๋Šฅ ์Šคํ† ๋ฆฌ์ง€๋ฅผ ์ค‘๊ฐ„์— ๋‘ฌ์„œ ์ผ๋‹จ clickhouse์— ๊ฐ€ํ•ด์ง€๋Š” ์ˆœ๊ฐ„ ๋ถ€ํ•˜๋ฅผ ์™„ํ™”ํ•˜๊ณ , batch insert๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

  1. ์Šคํ† ๋ฆฌ์ง€ ํšจ์œจ์„ฑ ๊ณ„์ธต: ์˜ค๋ž˜๋œ ๋กœ๊ทธ๋ฅผ S3 ๊ฐ™์€ ์ €๋ ดํ•œ ์Šคํ† ๋ฆฌ์ง€๋กœ exportํ•˜๋˜, ์ด ๋˜ํ•œ clickhouse๋ฅผ ํ†ตํ•ด์„œ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. ์ฝ์„ ๋•Œ๋งŒ S3 ๋น„์šฉ์ด ๋‚˜์˜ค๊ณ , ์ €์žฅ๋น„์šฉ์€ ๋””์Šคํฌ์— ๋น„ํ•ด ์ƒ๋Œ€์ ์œผ๋กœ ์ €๋ ดํ•˜๋‹ค.






Docker๋กœ ์‹œ์ž‘ํ•ด๋ณด๊ธฐ (๋‹จ์ผ ์ด๋ฏธ์ง€)

๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ Clickhouse ์กฐ์ง์—์„œ ๋งŒ๋“ค์–ด๋†“์€ ๋‹จ์ผ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
ํ•˜๋‚˜์˜ ์ด๋ฏธ์ง€์— clickhouse, otel collector, hyperdx, mongodb๋ฅผ ๋‹ค ๋ง์•„๋†“์€ ๊ตฌ์„ฑ์ด๋‹ค.

๊ทธ๋ƒฅ ๋น ๋ฅด๊ฒŒ ์‹œ์ž‘ํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด docker cli๋กœ ๋ฐ”๋กœ ์‹œ์ž‘ํ•˜๋ฉด ๋˜๊ณ 

docker run --name clickstack -p 8123:8123 -p 8080:8080 -p 4317:4317 -p 4318:4318 clickhouse/clickstack-all-in-one:latest clickstack

์กฐ๊ธˆ ๋” ์˜์†์ ์œผ๋กœ, ์ปค์Šคํ…€ํ•˜๋ฉฐ ๊ด€๋ฆฌํ•˜๊ธธ ์›ํ•œ๋‹ค๋ฉด compose๋ฅผ ์“ฐ๋ฉด ๋œ๋‹ค.

services:
  clickstack:
    image: ${CLICKSTACK_IMAGE}
    container_name: clickstack
    restart: unless-stopped
    mem_limit: 12g # total memory ceiling for the all-in-one container
    environment:
      # Absolute base for post-login redirects. MUST match the external origin
      # users reach the UI on (scheme://host:port), e.g. behind a tunnel/proxy.
      # If unset it defaults to http://localhost:8080, which breaks login for
      # anyone not browsing from the host itself.
      - FRONTEND_URL=${FRONTEND_URL}
      - CLICKHOUSE_DEFAULT_PASSWORD=${CLICKHOUSE_DEFAULT_PASSWORD}
      - CLICKHOUSE_API_PASSWORD=${CLICKHOUSE_API_PASSWORD}
      - CLICKHOUSE_WORKER_PASSWORD=${CLICKHOUSE_WORKER_PASSWORD}
    ports:
      - "${HYPERDX_PORT}:8080" # HyperDX UI
      - "${OTLP_GRPC_PORT}:4317" # OTLP gRPC
      - "${OTLP_HTTP_PORT}:4318" # OTLP HTTP
      - "8123:8123" # ClickHouse HTTP
    volumes:
      - ch_data:/var/lib/clickhouse
      - ch_logs:/var/log/clickhouse-server
      - mongo_data:/data/db
      - ./clickhouse/config.d:/etc/clickhouse-server/config.d:ro
      - ./clickhouse/users.xml:/etc/clickhouse-server/users.xml:ro
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080"]
      interval: 30s
      timeout: 5s
      retries: 5
      start_period: 60s

volumes:
  ch_data:
  ch_logs:
  mongo_data:

์—๋Ÿฌ ์—†์ด ์‹คํ–‰๋˜๋ฉด ์ž˜ ๋œ ๊ฒƒ์ด๋‹ค.




Kubernetes๋กœ ์‹œ์ž‘ํ•˜๊ธฐ (v2)

์ฟ ๋ฒ„๋ฅผ ์“ด๋‹ค๋ฉด ์ข€ ๋” ์ œ๋Œ€๋กœ ๋œ ๊ตฌ์„ฑ์„ ๋น„๊ต์  ๊ฐ„ํŽธํ•˜๊ฒŒ ์„ธํŒ…ํ•  ์ˆ˜ ์žˆ๋‹ค.
์–˜๋“ค helm chart ๋ฒ„์ „ ๊ด€๋ฆฌ๋‚˜ ๊ณต์‹ ๋ฌธ์„œ ๊ด€๋ฆฌ๊ฐ€ ๊ฐœํŒ์ด๋ผ ๊ทธ๋ƒฅ ๋”ฐ๋ผ์„œ latest๋กœ ๋ฐ›์œผ๋ฉด ํ„ฐ์ง€๋Š” ์ƒํ™ฉ์ด๋‹ค. ํ•ญ์ƒ ๋ฒ„์ „์„ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

# cert manager๊ฐ€ ์—†๋‹ค๋ฉด ์„ค์น˜
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.3/cert-manager.yaml

# helm ์ดˆ๊ธฐํ™”
helm repo add clickstack https://clickhouse.github.io/ClickStack-helm-charts
helm repo add mongodb https://mongodb.github.io/helm-charts
helm repo update

# mongodb ์„ค์น˜ (hyperDX ์ƒํƒœ ๊ด€๋ฆฌ)
helm install mongodb-kubernetes-operator mongodb/mongodb-kubernetes \
    --set operator.watchNamespace=clickstack

# operator ์„ค์น˜
helm install clickhouse-operator oci://ghcr.io/clickhouse/clickhouse-operator-helm \
   --create-namespace \
   -n clickhouse-operator-system \
    --version v0.0.6

operator๊ฐ€ ์ž˜ ์‹คํ–‰๋œ๋‹ค๋ฉด, clickstack์„ ๋ณธ๊ฒฉ์ ์œผ๋กœ ๊น”๋ฉด ๋œ๋‹ค.

helm install my-clickstack clickstack/clickstack --version 2.1.1 -n clickstack --create-namespace

๋ฐฐํฌํ•˜๊ณ  ๋‚˜์„œ ์กฐ๊ธˆ๋งŒ ๊ธฐ๋‹ค๋ฆฌ๋ฉด

์ด๋ ‡๊ฒŒ ๋‹ค ๋œฐ ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ๊ฐœ๋ณ„ service๋ฅผ ์—ด๊ฑฐ๋‚˜ ํฌํŠธํฌ์›Œ๋”ฉํ•ด์„œ ๋ถ™์—ฌ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๋Œ€์‹œ๋ณด๋“œ๊ฐ€ app์ด๋ผ๋Š” service์ด๊ณ , ๋กœ๊ทธ ์ˆ˜์ง‘ ์—”๋“œํฌ์ธํŠธ๋Š” otel-collector๋ผ๋Š” service๋ฅผ ์“ฐ๋ฉด ๋œ๋‹ค.

kubectl port-forward -n clickstack svc/my-clickstack-app 3000:3000

์ƒ์„ธํ•œ ๊ฒƒ๋“ค์€ ์Šคํ‚ตํ•œ๋‹ค.




์‚ฌ์šฉํ•ด๋ณด๊ธฐ

๋งŒ์•ฝ Clickstack ํ”„๋ฆฌ์…‹์„ ํ†ตํ•ด ๊ตฌ์„ฑํ–ˆ๋‹ค๋ฉด, clickhouse์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธ ํ…Œ์ด๋ธ”์ด ๊ตฌ์„ฑ๋  ๊ฒƒ์ด๋‹ค.

๋ญ๊ฐ€ ๋งŽ๋‹ค.

๊ทธ๋ฆฌ๊ณ  HyperDX์— ์ ‘์†ํ•˜๋ฉด, ์ตœ์ดˆ ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด์ด ๋œฌ๋‹ค.

์—ฌ๊ธฐ์„œ ๋ฃจํŠธ๊ณ„์ • ๋งŒ๋“ค๋ฉด ๋œ๋‹ค.

๋งŒ๋“ค๊ณ  ๋กœ๊ทธ์ธํ•ด์„œ ๋“ค์–ด๊ฐ€๋ฉด ๋ฐ”๋กœ ๊ทธ๋Ÿด๋“ฏํ•˜๊ฒŒ ๊พธ๋ฉฐ์ง„ ํ™”๋ฉด์ด ๋œฐ ๊ฒƒ์ด๋‹ค.

์ˆ˜์ง‘์šฉ API Key๋„ ์—ฌ๊ธฐ์„œ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฑธ ๋“ค๊ณ  Otel Collector์— ์˜๋ฉด ๋œ๋‹ค.


๊ทธ๋ฆฌ๊ณ  ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฉ”ํŠธ๋ฆญ๊ณผ Trace๋“ค์ด ๊ฐ€์‹œํ™”๋œ๋‹ค.
Grafana๋ณด๋‹จ Elastic APM(Kibana)์— ๊ฐ€๊นŒ์šด ์Šคํƒ€์ผ์ด๋‹ค. ์‚ฌ์ „ ๊ตฌ์„ฑ์ด ๊ทธ๋Ÿด๋“ฏํ•˜๊ฒŒ ๋˜์–ด์žˆ๊ณ , Grafana์ฒ˜๋Ÿผ ์ •์‹ ์—†์ด ์กฐํ•ฉํ•˜๋Š” ์Šคํƒ€์ผ์€ ์•„๋‹ˆ๋‹ค.

์—์ด์ „ํŠธ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ ์ž์ฒด๋Š” ํ‘œ์ค€ Otel ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด๋ฉด ๋œ๋‹ค. ๊ฒฐ๊ตญ ์ˆ˜์ง‘ ๊ณ„์ธต์ด Otel๋กœ ์ถ”์ƒํ™”๋˜์–ด์žˆ๊ธฐ ๋•Œ๋ฌธ์—, Grafana ์Šคํƒ์„ ์“ฐ๋Š” ๊ฒƒ๊ณผ ํฐ ์ฐจ์ด๋Š” ์—†๋‹ค.
์ฐจ์ด๊ฐ€ ๋ฒŒ์–ด์ง€๋Š” ๋ถ€๋ถ„์€ clickhouse์— ๋Œ€ํ•œ ์šด์˜ ์Šคํ‚ฌ์ผ ๊ฒƒ์ด๋‹ค.




๋กœ๊ทธ & ํŠธ๋ ˆ์ด์Šค ์ˆ˜์ง‘

๊ฐ„๋‹จํ•˜๊ฒŒ ์ˆ˜์ง‘์„ ํ•ด๋ณด๋ ค๋ฉด INGESTION Key๋ฅผ ๋“ค๊ณ  Otel Collector์— ์ฐ”๋Ÿฌ๋ณด๋Š” ๊ฒƒ์ด ๋น ๋ฅด๋‹ค.
์ด๊ฑด Trace๋ฅผ ํ•˜๋‚˜. ์Œ“๋Š”๋‹ค.

KEY=ํ‚ค๊ฐ’

curl -s -w '\nHTTP=%{http_code}\n' -X POST http://localhost:4318/v1/traces \
  -H "authorization: $KEY" -H 'content-type: application/json' \
  -d "{\"resourceSpans\":[{\"resource\":{\"attributes\":[{\"key\":\"service.name\",\"value\":{\"stringValue\":\"probe-real\"}}]},\"scopeSpans\":[{\"spans\":[{\"traceId\":\
"5b8efff798038103d269b633813fc60c\",\"spanId\":\"eee19b7ec3c1b174\",\"name\":\"probe\",\"kind\":1,\"startTimeUnixNano\":\"${NOW}\",\"endTimeUnixNano\":\"${END}\"}]}]}]}"

๊ทธ๋Ÿผ ์ด๋Ÿฐ ์‹์œผ๋กœ ์Œ“์ด๊ณ  ๊ฐ€์‹œํ™”๊ฐ€ ๋œ๋‹ค.

์ดํ›„์—๋Š” Otel ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•ด์„œ ์–ธ์–ด์— ๋งž๊ฒŒ ์—์ด์ „ํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค.

๋กœ๊ทธ๋„ ์ˆ˜์ง‘ํ•˜๋ฉด ์ด๋Ÿฐ ์‹์œผ๋กœ ์Œ“์ธ๋‹ค.




๋Œ€์‹œ๋ณด๋“œ ๊นŽ๊ธฐ

์›ํ•œ๋‹ค๋ฉด Grafana์ฒ˜๋Ÿผ Tile์„ ํ•˜๋‚˜ํ•˜๋‚˜ ๋ถ™์—ฌ์„œ ์ปค์Šคํ…€ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
์‚ฌ์šฉ๋ฒ•์€ ๋Œ€์ถฉ ๋น„์Šทํ•˜๋‹ค.

๋Œ€์‹œ๋ณด๋“œ์— Tile๋“ค์„ ์ •์˜ํ•ด์„œ ๋„ฃ๊ณ , ๋ ˆ์ด์•„์›ƒ์„ ์›ํ•˜๋Š”๋Œ€๋กœ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋กœ๊ทธ๋Š” ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค. Search Tile์ด ๊ฐ€์žฅ ์ ์ ˆํ•œ ๊ฒƒ ๊ฐ™๋‹ค. ์‹œ๊ณ„์—ด๋กœ ๋ณด์—ฌ์ค€๋‹ค.

๋กœ๊ทธ ๋ฒ ์ด์Šค๋กœ ๋กœ๊ทธ ๋ ˆ๋ฒจ๋ณ„ ์นด์šดํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด, ์ด๋Ÿฐ ์‹์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
group by ์ ˆ๋งŒ ๋Œ€์‘๋˜๋Š” ๊ฒƒ์œผ๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค.

๋ฉ”ํŠธ๋ฆญ์€ ์ ์žฌ๋˜์–ด์žˆ๋Š” ์ง€ํ‘œ ์ค‘์— ์ ์ ˆํžˆ ๊ณจ๋ผ์„œ ์ฐจํŠธ๋กœ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค. ๋Œ€์ฒด๋กœ Average๊ฐ€ ๋ถ€ํ•ฉํ•œ๋‹ค.

์ปค์Šคํ…€ ํ•„ํ„ฐ๋„ ์ ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋งŒ์•ฝ 'environment'๋ผ๋Š” ์ปค์Šคํ…€ ์†์„ฑ์„ ์ถ”๊ฐ€ํ–ˆ๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ํ•„ํ„ฐ ๋ฒ„ํŠผ์ด ํ•„์š”ํ•˜๋‹ค๋ฉด ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

๊ทธ๋Ÿผ ์ด๋ ‡๊ฒŒ ์ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค.




๊พธ๋ฏธ๊ธฐ

Tile์˜ Display ์„ธํŒ…์„ ๊ฑด๋“œ๋ฆฌ๋ฉด ์ด๋Ÿฐ์ €๋Ÿฐ ์กฐ์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
๋Œ€ํ‘œ์ ์ธ ๊ฒƒ์€ ์ˆซ์ž ๋‹จ์œ„ ํ‘œ๊ธฐ๋‹ค.

์ˆซ์ž๋ฅผ ํ‘œ์‹œํ•  ๋•Œ ์–ด๋–ค ๋‹จ์œ„๋กœ ํ‘œ์‹œํ• ์ง€๋ฅผ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Data๋กœ ํ•˜๋ฉด

๋ฐ”์ดํŠธ ๋‹จ์œ„๊ณ„๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค. ์•„๋งˆ ์ด๊ฑธ ์ œ์ผ ์ž์ฃผ ์“ฐ์ง€ ์•Š์„๊นŒ ์‹ถ๋‹ค.


๊ทธ๋ฆฌ๊ณ  ๊ทธ๋ฃน์„ ์‚ฌ์šฉํ•˜๋ฉด Tile๋“ค์„ ๋ฌถ์–ด์„œ ๊น”๋”ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.





TTL ๊ธฐ๋ฐ˜์˜ ๋กœ๊ทธ ๋งŒ๋ฃŒ ์„ค์ •

์›ํ•œ๋‹ค๋ฉด ์ด๊ฒƒ๋„ TTL ๊ธฐ๋ฐ˜์œผ๋กœ ๋กœ๊ทธ๋ฅผ ์ œ๊ฑฐํ•˜๊ฑฐ๋‚˜, ์Šคํ† ๋ฆฌ์ง€ ๊ณ„์ธต์œผ๋กœ ์˜ฎ๊ธธ ์ˆ˜ ์žˆ๋‹ค.
๋กœ๊ทธ๋ฅผ ์˜ค๋ž˜ ๋ณด๊ด€ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค๋ฉด TTL ์ œ๊ฑฐ๋งŒ์œผ๋กœ๋„ ์ถฉ๋ถ„ํ•  ๊ฒƒ์ด๋‹ค.

-- 30-day retention for ClickStack telemetry.
-- ttl_only_drop_parts drops whole expired parts (lower merge overhead).
ALTER TABLE default.otel_logs   MODIFY SETTING ttl_only_drop_parts = 1;
ALTER TABLE default.otel_logs   MODIFY TTL Timestamp + toIntervalDay(30);

ALTER TABLE default.otel_traces MODIFY SETTING ttl_only_drop_parts = 1;
ALTER TABLE default.otel_traces MODIFY TTL Timestamp + toIntervalDay(30);

ALTER TABLE default.otel_metrics_gauge                 MODIFY TTL TimeUnix + toIntervalDay(30);
ALTER TABLE default.otel_metrics_sum                   MODIFY TTL TimeUnix + toIntervalDay(30);
ALTER TABLE default.otel_metrics_histogram             MODIFY TTL TimeUnix + toIntervalDay(30);
ALTER TABLE default.otel_metrics_exponential_histogram MODIFY TTL TimeUnix + toIntervalDay(30);
ALTER TABLE default.otel_metrics_summary               MODIFY TTL TimeUnix + toIntervalDay(30);

๊ทธ๋Ÿด๋•Œ๋Š” ์ด๋Ÿฐ ์ฟผ๋ฆฌ๋งŒ ๋‚ ๋ ค์ค˜๋„ ์ถฉ๋ถ„ํ•˜๋‹ค. clickhouse ๋‚ด์—์„œ 30์ผ๊นŒ์ง€๋งŒ ๋ณด๊ด€ํ•˜๊ณ  ์ง€์šด๋‹ค.

๋‹ค๋งŒ, ๋””์Šคํฌ ํฌ๊ธฐ ๊ธฐ์ค€์œผ๋กœ rotation์„ ๋Œ๋ฆฌ๋Š” ๊ฒƒ์€ ์ง์ ‘์ ์œผ๋กœ ์ง€์›๋˜์ง€๋Š” ์•Š๋Š”๋‹ค.
๊ทธ๊ฑด ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ๋Œ๋ ค์•ผ ํ•œ๋‹ค.




์•„์‰ฌ์šด ์ ๋“ค

๋‹น์—ฐํ•˜์ง€๋งŒ ๋ชจ๋“  ๊ธฐ์ˆ ์—๋Š” ๋งน์ ์ด ์žˆ๊ณ , ์ด ์Šคํƒ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค.

(์˜คํ”ˆ์†Œ์Šค๋ฅผ ์“ด๋‹ค๋ฉด) helm์„ ๋น„๋กฏํ•œ ํŒจํ‚ค์ง• ์ˆ˜์ค€์ด ๊ทธ๋ ‡๊ฒŒ ์ข‹์ง„ ๋ชปํ•˜๋‹ค. ์—ด์‹ฌํžˆ ๋งŒ๋“ค๊ณ  ์žˆ๋Š” ๊ฒƒ ๊ฐ™๊ธด ํ•œ๋ฐ, ๋ญ”๊ฐ€ ์ข€ ๊ผฌ๋ฆ„ํ•˜๋‹ค. ์ œ๋Œ€๋กœ ์„œ๋น„์Šค ํ™˜๊ฒฝ์—์„œ ์“ฐ๋ ค๋ฉด ๊ฒฐ๊ตญ ์ง์ ‘ ๊นŽ์•„์•ผํ•˜๋Š” ๋ถ€๋ถ„์ด ์ƒ๊ธธ๋“ฏ

๋Œ€์‹œ๋ณด๋“œ ์ปค์Šคํ…€์ด ๊ฝค ์ž˜ ๋˜์ง€๋งŒ, Grafana์ฒ˜๋Ÿผ ๋Œ€์‹œ๋ณด๋“œ๋ฅผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ฒ˜๋Ÿผ ๊ณต์œ ํ•˜๊ณ  ๋‹ค์šด๋ฐ›๋Š” ํ™˜๊ฒฝ์ด ์กด์žฌํ•˜์ง„ ์•Š๋Š”๋‹ค. ๋Œ€์‹  ๊ธฐ๋ณธ์ ์ธ ์‚ฌ์šฉ ํ๋ฆ„์€ Kibana(Elastic APM)์ฒ˜๋Ÿผ ์–ด๋А ์ •๋„ ์ •์˜ํ•ด์„œ ์ œ๊ณตํ•œ๋‹ค.

Continuos Profiling์— ๋Œ€ํ•œ ๊ณ ๋ ค๊ฐ€ ์—†๋‹ค. ํ•„์š”ํ•˜๋‹ค๋ฉด pyroscope ๊ฐ™์€ ๋ฐ๋‹ค ๋”ฐ๋กœ ์ €์žฅํ•˜๊ณ  ๊ทธ๊ฑธ Grafana๋‚˜ pyroscope ์ž์ฒด ๋Œ€์‹œ๋ณด๋“œ๋กœ ์‹œ๊ฐํ™”ํ•ด์•ผ ํ•œ๋‹ค.



์ฐธ์กฐ
https://clickhouse.com/docs/use-cases/observability/clickstack/getting-started/oss?loc=clickstack-oss
https://github.com/ClickHouse/ClickStack-helm-charts
https://clickhouse.com/docs/use-cases/observability/clickstack/deployment/helm-v1
https://tech.kakaopay.com/post/pallas-v2-log-platform/
https://github.com/ClickHouse/clickhouse-operator