Loki write / read / backend 역할 정리 본문
Helm으로 Loki를 설치하면 loki-write, loki-backend StatefulSet과 loki-read Deployment가 생깁니다. 처음 보면 "왜 파드가 이렇게 많지?" 싶은데, 이건 Loki의 Simple Scalable 배포 모드 때문입니다.
이 글에서는 세 가지 배포 모드가 무엇인지, 그리고 각 StatefulSet이 내부적으로 어떤 컴포넌트를 묶어놓은 건지 정리합니다.
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, write와 backend는 디스크 상태(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 Ingesterread
Grafana 쿼리 처리. 분할하고 병렬 조회.
Query Frontend Querierbackend
백그라운드 작업. 압축, 알림, 인덱스 캐시.
Compactor Ruler Index Gatewaywrite — 로그를 받아서 저장
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"
write 레플리카를 늘립니다.
read — 쿼리를 받아서 조회
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"
read 레플리카를 늘립니다.
backend — 백그라운드 작업
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이면 하나의 Ingester에만 저장되므로, 그 파드가 재시작될 때 미플러시 로그가 유실될 수 있습니다. write 레플리카 수와 replication_factor를 맞춰야 합니다.
loki:
commonConfig:
replication_factor: 3 # write replicas와 동일하게
write:
replicas: 3
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 |
