Observability는 선택이 아니라 필수다. 하지만 SaaS 모니터링 비용이 인프라 비용보다 높아지는 순간이 온다. 그때가 자체 구축을 고민할 타이밍이다.
Datadog을 메인으로 사용하고 있었지만, 모든 환경에 적용하기엔 비용 부담이 있었다. Observability가 아예 없는 환경이 생기는 것보다는, 오픈소스로라도 갖추는 게 낫다고 판단했다. LGTM 스택(Loki, Grafana, Tempo, Mimir)을 EKS에 구축한 과정을 공유한다.
Datadog을 메인으로 사용하고 있지만, 모든 환경에 적용하기엔 비용 부담이 있었다. 특히 작은 규모의 계정들은 Observability가 아예 없는 상태로 운영되고 있었다.
메트릭 수집은 Observability의 절반에 불과하다. 나머지 절반은 시각화다. 데이터가 쌓여도 볼 수 없으면 의미가 없다.
LGTM 스택을 구축했지만 대시보드가 없었다. 커뮤니티 대시보드를 import 해봤지만 우리 환경과 맞지 않았다. 결국 운영 관점에서 필요한 대시보드를 직접 설계하고 구축했다. GitOps로 대시보드를 관리하는 방식도 함께 정리한다.
운영 관점에서 세 가지가 필요했다.
- 인프라 대시보드: 클러스터 전체 상태, 노드 헬스, 리소스 사용량
- APM 대시보드: 서비스별 요청량, 에러율, 레이턴시
- 파이프라인 대시보드: LGTM 스택 자체의 헬스 체크
Datadog을 쓸 때는 기본 제공되던 것들이다. LGTM 스택에서는 직접 구성해야 한다.
관측성(Observability)은 앱의 관심사가 아니다. 인프라가 책임져야 한다.
OpenTelemetry 커뮤니티와 Grafana Labs가 공통적으로 강조하는 원칙이다. 앱 개발자는 비즈니스 로직에 집중하고, 로그/트레이스/메트릭 수집은 플랫폼이 알아서 처리해야 한다. 하지만 현실은 그렇지 않은 경우가 많다. Dockerfile에 Agent를 넣고, Init Container를 설정하고, 환경변수를 10개 넘게 직접 입력하는 작업을 앱 개발자가 하고 있다면, 관심사 분리가 안 되고 있는 것이다.
이 글에서는 Init Container / 이미지 내장 방식에서 OTel Operator 방식으로 전환해야 하는 이유와 동작 원리를 정리한다.
Observability의 최종 목표는 MTTD(Mean Time To Detect)를 줄이는 것이다. 대시보드가 아무리 훌륭해도 24시간 지켜볼 수는 없다. Push 기반 알림이 있어야 문제를 빠르게 인지할 수 있다.
LGTM 스택에서 Mimir Ruler와 Alertmanager를 활용해 알림 시스템을 구축했다. 알림 룰을 GitOps로 관리하고, 알림 폭탄을 방지하기 위한 설계 포인트를 정리한다.
flowchart LR
subgraph GitOps[GitOps 관리]
Git[Git Repository]
CM[ConfigMap]
end
subgraph Mimir[Mimir]
Ruler[Ruler<br/>PromQL 평가]
Storage[(Metrics<br/>Storage)]
AM[Alertmanager<br/>라우팅/그룹핑]
end
subgraph Grafana[Grafana]
AlertUI[Alerting UI<br/>알림 현황 조회]
end
subgraph Slack[Slack]
Ch1[#alerts-service]
Ch2[#alerts-infra]
end
Git -->|Helm Deploy| CM
CM -->|Alert Rules| Ruler
Storage -->|메트릭 쿼리| Ruler
Ruler -->|알림 발생| AM
AM -->|namespace: app| Ch1
AM -->|namespace: observability| Ch2
AM -->|알림 상태| AlertUI
Ruler가 주기적으로 메트릭을 쿼리하고, 조건이 충족되면 Alertmanager로 알림을 보낸다. Alertmanager는 알림을 그룹핑하고, 라우팅 규칙에 따라 적절한 Slack 채널로 전송한다. Grafana에서는 현재 발생 중인 알림을 조회하고 히스토리를 확인할 수 있다.
데이터베이스의 신뢰성은 결국 “쓰기를 잃지 않는 것"에서 시작한다. PostgreSQL, MySQL, SQLite 모두 WAL(Write-Ahead Logging)이라는 동일한 원칙을 사용한다. 최종 저장소에 반영하기 전에 먼저 로그에 기록하라.
LGTM 스택도 같은 문제를 안고 있다. Ingester는 수신한 데이터를 메모리에 버퍼링했다가 주기적으로 오브젝트 스토리지(S3 등)에 flush한다. 이 사이에 프로세스가 죽으면? 메모리의 데이터는 사라진다. Mimir 기준으로 최대 2시간, Loki는 flush 주기만큼의 로그가 유실될 수 있다. WAL은 이 간극을 메운다.
WAL의 핵심은 단순하다. 데이터를 처리하기 전에 먼저 디스크에 기록한다.
비용 모니터링은 단순한 비용 관리 도구가 아니다. 때로는 성능 모니터링이나 에러 알림보다 먼저 문제를 잡아준다. 시스템은 정상인데 비용만 비정상인 상황, 그게 바로 서드파티 솔루션에서 발생한 문제였다.
주간 AWS 비용 리포트에서 S3 DataTransfer-Out이 $0에서 하루 $44로 뛰었다. 서비스에는 아무 이상이 없었고, 에러 로그도 없었다. 원인은 도입한 로그 수집 솔루션의 버그였다. 하루 7GB의 데이터를 349GB나 반복 전송하고 있었다.
자동화된 주간 비용 리포트에서 S3 DataTransfer-Out 항목이 눈에 띄었다. 기존에는 거의 $0이던 항목이 갑자기 하루 $40 이상 찍히고 있었다.