본문 바로가기

Notice
Recent Posts
Link
Calendar
«   2026/05   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
Total
Today
관리 메뉴

Loki write / read / backend 역할 정리 본문

Kubernetes

Loki write / read / backend 역할 정리

BinaryNumber 2026. 5. 16. 16:10
반응형

Helm으로 Loki를 설치하면 loki-write, loki-backend StatefulSet과 loki-read Deployment가 생깁니다. 처음 보면 "왜 파드가 이렇게 많지?" 싶은데, 이건 Loki의 Simple Scalable 배포 모드 때문입니다.

이 글에서는 세 가지 배포 모드가 무엇인지, 그리고 각 StatefulSet이 내부적으로 어떤 컴포넌트를 묶어놓은 건지 정리합니다.

테스트 환경: Loki v3.x, loki-stack Helm chart

Loki의 3가지 배포 모드

Loki는 하나의 바이너리로 배포 모드를 target 파라미터로 제어합니다.

1. Monolithic (단일 모드)

모든 컴포넌트가 하나의 파드에서 실행됩니다. 개발 환경이나 소규모 로그 수집에 적합하지만 수평 확장이 안 됩니다.

deploymentMode: SingleBinary

loki:
  commonConfig:
    replication_factor: 1
  storage:
    type: filesystem

2. Simple Scalable (권장 모드) — Helm 기본값

역할을 write, read, backend 세 그룹으로 나눠서 배포합니다. 각 그룹을 독립적으로 스케일링할 수 있어서 운영 환경에 적합합니다.

deploymentMode: SimpleScalable

3. Microservices (완전 분산 모드)

모든 컴포넌트를 개별 Deployment로 분리합니다. 세밀한 리소스 제어가 가능하지만 관리 복잡도가 높아서 대규모 환경에서만 사용합니다.

deploymentMode: Distributed

Simple Scalable의 세 컴포넌트 그룹

Helm 설치 후 확인하면 이렇게 나타납니다. read는 Stateless라서 Deployment, writebackend는 디스크 상태(WAL, 인덱스)가 필요해서 StatefulSet입니다.

$ kubectl get statefulset -n monitoring

NAME             READY   AGE
loki-backend     1/1     5m
loki-write       3/3     5m

$ kubectl get deployment -n monitoring

NAME             READY   AGE
loki-read        2/2     5m

write

로그 수집 입구. 받아서 버퍼링하고 저장.

Distributor Ingester

read

Grafana 쿼리 처리. 분할하고 병렬 조회.

Query Frontend Querier

backend

백그라운드 작업. 압축, 알림, 인덱스 캐시.

Compactor Ruler Index Gateway

write — 로그를 받아서 저장

[Promtail / Alloy][write: Distributor][write: Ingester][Object Storage]

Distributor

Promtail이 로그를 보내면 가장 먼저 만나는 컴포넌트입니다.

  • 들어오는 로그의 라벨 유효성 검사
  • 스트림 해시 기반으로 어느 Ingester로 보낼지 결정 (일관된 해시링)
  • ingestion_rate_limit 초과 시 429 응답 반환
  • 자체 상태 없음 — stateless하게 동작

Ingester

Distributor에게 받은 로그를 메모리에 청크로 버퍼링했다가 Object Storage로 플러시합니다.

  • 로그 스트림을 메모리 청크에 압축 저장
  • 일정 조건(시간 또는 크기)이 되면 S3 등으로 플러시
  • WAL(Write-Ahead Log)을 디스크에 기록해서 파드 재시작 시 복구 가능
  • Stateful하기 때문에 StatefulSet으로 배포됨
# Helm values.yaml — write 스케일링
write:
  replicas: 3
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "1000m"
      memory: "1Gi"
언제 늘리나: 로그 수집 지연이 발생하거나 Distributor에서 rate limit 에러가 많이 나면 write 레플리카를 늘립니다.

read — 쿼리를 받아서 조회

[Grafana][read: Query Frontend][read: Querier][Ingester] + [Object Storage]

Query Frontend

Grafana가 LogQL 쿼리를 보내면 가장 먼저 받는 컴포넌트입니다.

  • 쿼리를 시간 단위로 잘게 분할해서 여러 Querier에게 병렬 처리 위임
  • 결과를 캐시해서 동일 쿼리 반복 시 빠르게 반환 (memcached 연동 가능)
  • 쿼리 우선순위 큐 관리

Querier

실제로 데이터를 가져오는 컴포넌트입니다.

  • Ingester와 Object Storage 양쪽에서 동시에 조회
    • Ingester: 아직 플러시되지 않은 최신 로그 (수 분 이내)
    • Object Storage: 플러시된 과거 로그
  • 두 결과를 합쳐서 중복 제거 후 반환
# Helm values.yaml — read 스케일링
read:
  replicas: 2
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "2000m"
      memory: "2Gi"
언제 늘리나: Grafana에서 로그 조회가 느리거나 타임아웃이 발생하면 read 레플리카를 늘립니다.

backend — 백그라운드 작업

[backend: Compactor] → 인덱스 압축 + 오래된 로그 삭제 [backend: Ruler] → LogQL 알림 규칙 평가 → AlertManager [backend: Index Gateway] → Querier 인덱스 캐시 중계

Compactor

  • 작은 인덱스 파일들을 하나로 압축해서 조회 성능 향상
  • retention_period 설정에 따라 오래된 로그 삭제
  • 한 번에 하나만 실행 — 레플리카는 1개가 원칙

Ruler

  • LogQL 표현식으로 정의한 알림 규칙을 주기적으로 평가
  • 조건 충족 시 AlertManager로 알림 전송
  • Prometheus Ruler와 동일한 개념

Index Gateway

  • Querier가 매번 Object Storage에서 인덱스를 읽는 대신 캐시된 인덱스 제공
  • 대규모 환경에서 Object Storage 요청 수 감소 → 비용 절감
# Helm values.yaml — backend 설정
backend:
  replicas: 1  # 대부분 1개로 충분
  resources:
    requests:
      cpu: "100m"
      memory: "256Mi"
    limits:
      cpu: "500m"
      memory: "512Mi"

한눈에 정리

StatefulSet내부 컴포넌트역할스케일링 기준
write (StatefulSet)Distributor, Ingester로그 수집 + 버퍼링 + 저장수집 지연 / rate limit 에러
read (Deployment)Query Frontend, Querier쿼리 처리 + 데이터 조회조회 느림 / 타임아웃
backend (StatefulSet)Compactor, Ruler, Index Gateway압축 / 알림 / 인덱스 캐시거의 건드릴 일 없음

자주 하는 실수

replication_factor를 1로 설정하고 write를 3개 띄우는 경우

replication_factor: 1이면 하나의 Ingester에만 저장되므로, 그 파드가 재시작될 때 미플러시 로그가 유실될 수 있습니다. write 레플리카 수와 replication_factor를 맞춰야 합니다.
loki:
  commonConfig:
    replication_factor: 3  # write replicas와 동일하게
write:
  replicas: 3
Object Storage 없이 SimpleScalable 모드를 쓰는 경우

Simple Scalable 모드는 반드시 외부 Object Storage가 필요합니다. filesystem 스토리지는 Monolithic 모드에서만 동작합니다. 로컬 환경에서 테스트하려면 MinIO를 함께 띄우세요.

실무 설정 예시

# custom-values.yaml

deploymentMode: SimpleScalable

loki:
  storage:
    type: s3
    s3:
      region: ap-northeast-2
      bucketnames: my-loki-chunks
  commonConfig:
    replication_factor: 3

write:
  replicas: 3
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "1"
      memory: "1Gi"

read:
  replicas: 2
  resources:
    requests:
      cpu: "500m"
      memory: "512Mi"
    limits:
      cpu: "2"
      memory: "2Gi"

backend:
  replicas: 1
  resources:
    requests:
      cpu: "100m"
      memory: "256Mi"
    limits:
      cpu: "500m"
      memory: "512Mi"

마치며

Loki의 Simple Scalable 모드는 쓰기/읽기 부하를 독립적으로 조절할 수 있어서 운영 환경에서 효율적입니다. 실제로 로그 수집량이 많아지면 write만 늘리고, Grafana 조회가 느려지면 read만 늘리면 되기 때문에 리소스 낭비가 없습니다.

'Kubernetes' 카테고리의 다른 글

ArgoCD Notifications Slack 연동  (0) 2026.05.16
ArgoCD ApplicationSet  (0) 2026.05.16
ArgoCD Application, AppProject  (0) 2026.05.16
ArgoCD Helm 설치 시 생성되는 컴포넌트 역할 정리  (0) 2026.05.16
Comments