새벽 3시, "Disk Usage > 90%" 알림이 울립니다. 운영 중인 Kubernetes 클러스터의 메인 Prometheus 파드(Pod)가 또다시 스토리지 한계에 도달한 것입니다. 단순히 PVC(Persistent Volume Claim) 용량을 늘리는 것은 임시방편일 뿐입니다. 데이터 보존 기간(retention)을 15일로 줄여도, 메트릭 카디널리티(Cardinality)가 급증하는 상황에서는 턱없이 부족합니다. 더 심각한 문제는 Prometheus가 단일 인스턴스로 동작하고 있어, 재시작 시 수집 공백이 발생하는 SPOF(Single Point of Failure) 상태라는 점입니다. 본 글에서는 이러한 레거시 모니터링 시스템의 한계를 극복하고, Prometheus HA(고가용성)와 무제한에 가까운 장기 스토리지를 확보하기 위해 Thanos 사이드카 패턴을 도입한 과정을 공유합니다.
Prometheus의 태생적 한계와 Federation의 실패
우리가 운영하던 시스템은 초당 수십만 개의 시계열 데이터(Time Series)를 생성합니다. Prometheus는 로컬 디스크(TSDB)에 데이터를 저장하는 구조라, 디스크 I/O가 병목이 되거나 용량이 차면 과거 데이터를 삭제해야 합니다. 진정한 관측가능성(Observability)을 위해서는 1년 전 데이터와 현재를 비교할 수 있어야 하지만, 로컬 스토리지로는 불가능했습니다.
처음에는 Prometheus Federation을 시도했습니다. 계층적으로 Prometheus를 구성하여 데이터를 중앙으로 모으는 방식입니다.
결국 우리는 구조적인 변경이 필요하다는 결론을 내렸습니다. 데이터를 로컬에만 두지 않고 저렴한 객체 스토리지(S3, GCS 등)로 옮기면서도, Prometheus의 쿼리 인터페이스를 유지해야 했습니다. 이것이 바로 Thanos Architecture를 선택한 이유입니다.
해결책: Thanos Sidecar 패턴 구현
Thanos는 여러 컴포넌트로 구성되지만, 핵심은 Sidecar입니다. 기존 Prometheus 파드 내에 사이드카 컨테이너를 추가하여, Prometheus가 디스크에 쓰는 TSDB 블록을 실시간으로 감지하고 이를 S3와 같은 객체 스토리지로 업로드합니다.
1. 객체 스토리지 설정 (objstore.yml)
먼저 S3 버킷에 접근하기 위한 설정 파일을 생성합니다. 이 파일은 Kubernetes Secret으로 관리하는 것이 보안상 안전합니다.
# objstore.yml
type: S3
config:
bucket: "monitoring-thanos-store"
endpoint: "s3.ap-northeast-2.amazonaws.com"
region: "ap-northeast-2"
# AWS SDK가 파드의 IAM Role을 사용하도록 설정 (권장)
signature_version2: false
encrypt_sse: true
2. Prometheus StatefulSet 수정
가장 중요한 부분입니다. Prometheus 컨테이너와 Thanos Sidecar 컨테이너가 /prometheus 볼륨을 공유해야 합니다. 또한, Prometheus가 TSDB 블록을 생성하는 주기를 고정해야 사이드카가 안정적으로 업로드할 수 있습니다.
# prometheus-statefulset.yaml (발췌)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: prometheus-k8s
spec:
replicas: 2 # HA 구성을 위해 2개로 설정
template:
spec:
containers:
# [1] 기존 Prometheus 컨테이너
- name: prometheus
image: quay.io/prometheus/prometheus:v2.45.0
args:
- --config.file=/etc/prometheus/config_out/prometheus.env.yaml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention.time=6h # 로컬 보관은 짧게 (디스크 절약)
# 중요: 블록 생성 주기를 2시간으로 고정하여 업로드 충돌 방지
- --storage.tsdb.min-block-duration=2h
- --storage.tsdb.max-block-duration=2h
- --web.enable-lifecycle
volumeMounts:
- name: prometheus-storage
mountPath: /prometheus
# [2] Thanos Sidecar 컨테이너 추가
- name: thanos-sidecar
image: quay.io/thanos/thanos:v0.32.0
args:
- sidecar
- --tsdb.path=/prometheus
- --prometheus.url=http://127.0.0.1:9090
- --objstore.config-file=/etc/thanos/objstore.yml
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
volumeMounts:
- name: prometheus-storage
mountPath: /prometheus
- name: thanos-objstore-config
mountPath: /etc/thanos
위 설정에서 주목할 점은 --storage.tsdb.min-block-duration=2h 옵션입니다. Prometheus는 기본적으로 메모리에 있는 데이터를 일정 주기마다 디스크 블록으로 내리는데, 이 주기를 2시간으로 명시적으로 고정해야 Thanos Sidecar가 "아, 이 블록은 이제 완결되었으니 S3로 올려도 되겠구나"라고 판단할 수 있습니다. 로컬 Retention을 6시간으로 짧게 설정함으로써 로컬 디스크 비용을 획기적으로 줄일 수 있습니다.
Prometheus HA 및 Global View 구성
이제 데이터는 S3에 안전하게 저장됩니다. 하지만 replicas: 2로 설정했기 때문에 동일한 메트릭이 중복 수집되고 있습니다. 이를 하나의 뷰로 합쳐서 보여주는 것이 Thanos Query 컴포넌트의 역할입니다.
Thanos Query는 쿼리 시점에 중복 제거(Deduplication)를 수행합니다. 이를 위해서는 각 Prometheus 인스턴스가 서로 다른 external_labels를 가지면서도, HA 그룹임을 식별할 수 있는 공통 레이블을 가져야 합니다.
# prometheus-0 의 설정
global:
external_labels:
cluster: production
replica: 0
# prometheus-1 의 설정
global:
external_labels:
cluster: production
replica: 1
이후 Thanos Query에서 --query.replica-label=replica 옵션을 사용하면, cluster=production이 같은 데이터 중 replica 레이블만 다른 데이터를 자동으로 병합하여 보여줍니다. 이로써 완벽한 Prometheus HA 구성이 완료됩니다.
성능 검증 및 스토리지 효율성 분석
Thanos 도입 전후의 리소스 사용량을 비교해보았습니다. 테스트 환경은 AWS EKS, 노드 50대 규모의 클러스터입니다.
| 지표 (Metric) | 단일 Prometheus (Before) | Thanos Sidecar (After) |
|---|---|---|
| 로컬 디스크 사용량 | 500GB (15일 보관) | 20GB (6시간 보관) |
| 데이터 보존 기간 | 최대 15일 (용량 제한) | 무제한 (S3 비용만 발생) |
| 메트릭 조회 속도 (최근 6h) | 빠름 (로컬) | 빠름 (로컬 + Sidecar GRPC) |
| 장기 데이터 조회 (1년) | 불가능 | 가능 (Store Gateway 경유) |
가장 극적인 변화는 로컬 스토리지 의존성 탈피입니다. 로컬 디스크 사용량이 96% 감소했습니다. 이는 고가의 EBS 볼륨 비용을 절감하는 효과도 가져왔습니다. 또한, 파드가 재시작되더라도 S3에 데이터가 있으므로 데이터 유실 걱정이 사라졌습니다. 이것이 바로 우리가 원하던 안정적인 장기 스토리지 솔루션입니다.
Thanos Sidecar 공식 문서 확인주의사항 및 Edge Cases
Thanos가 만능은 아닙니다. 도입 시 다음과 같은 부작용이나 주의사항을 반드시 고려해야 합니다.
또한, Compactor 컴포넌트 운영 시 메모리 부족(OOM) 현상이 자주 발생할 수 있습니다. S3에 저장된 데이터를 다운샘플링(Downsampling)하는 과정에서 많은 메모리를 소모하기 때문입니다. 초기 설정 시 Compactor 파드에는 충분한 메모리 리밋을 부여하고, --compact.concurrency 옵션을 조절하여 병렬 처리 개수를 제한하는 것이 좋습니다.
결론
Thanos 사이드카 패턴은 Kubernetes 환경에서 Prometheus의 확장성 문제를 해결하는 표준에 가까운 아키텍처입니다. 우리는 이를 통해 모니터링 시스템의 안정성을 확보하고, 수년 치의 데이터를 저렴하게 보관하는 장기 스토리지 전략을 완성했습니다. 결과적으로 인프라 팀은 스토리지 알람의 공포에서 벗어나, 데이터 기반의 의사결정과 진정한 관측가능성 향상에 집중할 수 있게 되었습니다. 만약 Prometheus의 디스크 용량 경고를 보고 계신다면, 지금 바로 Thanos 도입을 검토해 보시기 바랍니다.
Post a Comment