Datadog 걷어내고 LGTM 스택 구축하기 - OTel Sidecar + Grafana/Loki/Tempo/Mimir
Datadog 비용 압박으로 오픈소스 LGTM 스택(Grafana, Loki, Tempo, Mimir)으로 전환한 경험을 공유합니다. OTel Collector 사이드카 설계부터 노이즈 필터링, MDC 기반 요청 추적, IRSA 기반 S3 저장소 구성까지 실전 구축기입니다.
배경
이전 글에서 ECS → EKS 마이그레이션을 다뤘다. 그 과정에서 모니터링도 함께 전환했는데, 기존에는 Datadog을 쓰고 있었다.
Datadog의 문제
Datadog 자체는 좋은 도구다. APM, 로그, 메트릭, 대시보드까지 올인원으로 제공하고, 에이전트 하나만 붙이면 바로 동작한다. 하지만 우리 상황에서는 비용이 문제였다. 호스트 기반 과금 - 서비스가 늘어날수록 비용이 선형으로 증가한다. dev, stage, prod 환경을 전부 모니터링하면 호스트 수가 금방 늘어난다 로그 과금이 특히 부담 - 로그 수집량 기반으로 과금되는데, Spring Boot 앱의 로그량이 만만치 않다. 로그 레벨을 내리면 장애 시 원인 추적이 어려워진다 기능 대비 사용률이 낮았다 - Datadog이 제공하는 풍부한 기능 중 실제로 쓰는 건 APM 트레이싱, 로그 검색, 기본 메트릭 정도였다. 비용 대비 활용도가 낮았다
EKS로 마이그레이션하면서 인프라를 새로 구성하는 김에, 모니터링도 오픈소스 기반으로 전환하기로 했다.
왜 LGTM 스택인가
Grafana Labs에서 밀고 있는 LGTM 스택은 이름 그대로 네 가지 컴포넌트로 구성된다:
| 컴포넌트 | 역할 | Datadog 대응 | |||| | Loki | 로그 수집/조회 | Log Management | | Grafana | 시각화/대시보드 | Dashboards | | Tempo | 분산 트레이싱 | APM | | Mimir | 메트릭 장기 저장 | Metrics |
선택 이유는 단순하다: 비용 - 오픈소스 셀프 호스팅이라 인프라 비용만 든다. Helm 차트로 EKS에 배포하면 끝 통합 - Grafana에서 로그 → 트레이스 → 메트릭을 하나의 UI에서 오갈 수 있다. Trace ID 하나로 전부 연결된다 표준 - OpenTelemetry(OTel) 네이티브 지원. 벤더 종속 없이 표준 프로토콜로 데이터를 수집한다 확장성 - 각 컴포넌트가 독립적이라 필요한 것만 스케일할 수 있다. 로그가 많으면 Loki만 늘리면 된다
전체 아키텍처
데이터 흐름
모니터링 데이터의 흐름을 한 문장으로 요약하면 이렇다: Spring Boot → OTel Java Agent가 자동 계측 → OTel Collector 사이드카가 수신 → 로그/트레이스/메트릭을 Loki/Tempo/Mimir로 전송 → S3에 장기 저장 → Grafana에서 조회
핵심은 OTel Collector를 사이드카로 배치한 것이다. DaemonSet이 아닌 사이드카를 선택한 이유: 격리 - 서비스별 OTel 설정을 독립적으로 관리할 수 있다. 노이즈 필터링 같은 설정이 서비스마다 다르다 리소스 제어 - 서비스별로 Collector의 CPU/메모리를 독립적으로 조절할 수 있다 장애 격리 - Collector가 죽어도 해당 Pod에만 영향을 준다. DaemonSet이면 노드 전체가 영향받는다
인프라 구성
LGTM 스택 전체를 assist-tools namespace에 배포했다. 전용 Karpenter NodePool로 격리하고, Taint/Toleration으로 다른 워크로드가 섞이지 않게 했다.
| 컴포넌트 | 배포 모드 | Replicas | 스토리지 | ||||| | Grafana | Single | 1 | PVC 10Gi | | Loki | SimpleScalable | backend/read/write 각 1 | S3 (my-lgtm) | | Tempo | Distributed | distributor 2, ingester 2, querier 2 | S3 (my-cluster-lgtm) | | Mimir | Classic | 각 컴포넌트 1 | S3 (my-lgtm) |
OTel Java Agent - 애플리케이션 계측
자동 계측
Spring Boot 앱에 OTel Java Agent를 붙이면 코드 수정 없이 자동으로 트레이스, 메트릭, 로그를 수집한다. HTTP 요청, DB 쿼리, Redis 명령어, 외부 API 호출 등이 전부 자동으로 span으로 기록된다.
Dockerfile에서 에이전트를 -javaagent로 로드한다:
CI에서 빌드할 때 최신 OTel Java Agent를 다운로드하고 이미지에 포함시킨다:
환경 변수로 연결
Kustomize base Deployment에서 OTel Agent가 사이드카 Collector로 데이터를 보내도록 환경 변수를 설정한다:
localhost:4317이 핵심이다. 사이드카는 같은 Pod 안에 있으니 네트워크 오버헤드가 없다. 서비스 디스커버리나 DNS 조회도 필요 없다.
샘플링 설정
Spring Boot의 Micrometer 설정으로 트레이스 샘플링 비율을 제어한다:
prod에서 100% 샘플링은 Tempo 저장 비용과 성능 양쪽에서 부담이다. 40%면 장애 추적에 충분하면서도 저장 비용을 합리적으로 유지할 수 있다.
OTel Collector 사이드카 - 수집/가공/전송
OTel Collector는 모든 Pod에 사이드카로 배포된다. base Deployment에 기본 컨테이너로 포함되어 있고, 환경별 설정은 overlay에서 ConfigMap 패치로 관리한다.
Receiver - 데이터 수신