서버나 애플리케이션이 잘 돌아가고 있는지 눈으로 확인하고 싶을 때, 가장 먼저 부딪히는 문제는 데이터를 어떻게 모으고, 어떻게 보여줄까이다. Prometheus와 Grafana는 이 두 문제를 각각 나눠서 해결하는 오픈소스 조합이다.
Prometheus
Grafana
정리하면 두 도구는 경쟁 관계가 아니라 역할 분담 관계
Prometheus가 모으고, Grafana가 보여줌
(대부분의 모니터링 스택에서 이 둘은 세트로 함께 쓰인다)
첫째, 완전한 오픈소스라 비용 부담이 없다.
Datadog이나 New Relic 같은 SaaS형 모니터링 툴은 사용량에 따라 과금되는데, 트래픽이 늘수록 비용이 엄청나게 늘어난다. Prometheus와 Grafana는 직접 서버에 설치해서 쓰는 자체 호스팅(self-hosted) 방식이라 라이선스 비용이 없다.
둘째, 쿠버네티스와 클라우드 네이티브 환경의 사실상 표준이다.
Kubernetes 생태계에서 Prometheus는 CNCF(Cloud Native Computing Foundation) 프로젝트로 채택되어 있고, 파드나 노드의 상태를 긁어오는 exporter가 이미 풍부하게 존재한다. 커뮤니티가 크기 때문에 문제가 생겼을 때 검색으로 답을 찾기 쉽다.
셋째, 유연한 커스터마이징이 가능하다.
코드가 공개되어 있으니 회사 내부 정책에 맞게 데이터 보관 정책, 알림 규칙, 대시보드 디자인을 원하는 대로 바꿀 수 있다. SaaS 툴은 이런 부분이 벤더 정책에 묶여있는 경우가 많다.
지표(metric) 중심의 모니터링이 필요할 때 적합하다.
CPU, 메모리, 요청 수, 에러율처럼 숫자로 떨어지는 데이터를 실시간에 가깝게 보고 싶은 경우다. 반대로 로그 원문을 뒤지거나 분산 트레이싱까지 필요하다면 Loki, Tempo 같은 도구를 추가로 붙여야 한다.
인프라를 직접 운영하는 팀에 적합하다.
서버든 컨테이너든 직접 관리하고 있고, 그 안에 모니터링 서버 하나 정도는 추가로 운영할 여력이 있는 경우다. 반대로 운영 인력이 아예 없거나 인프라를 신경 쓰고 싶지 않다면 Datadog 같은 매니지드 SaaS가 더 편할 수 있다.
데이터 보관 기간이 길지 않아도 되는 경우에 적합하다.
Prometheus는 기본적으로 로컬 디스크에 데이터를 저장하기 때문에, 1년 이상의 장기 이력을 저장하려면 Thanos나 VictoriaMetrics 같은 별도 컴포넌트를 추가해야 한다. 최근 몇 주 정도의 데이터만 보면 충분한 경우라면 기본 구성만으로 충분하다.
소규모 개인 프로젝트라면 오히려 과할 수 있다.
서비스가 5개 미만인 개인 프로젝트나 단순히 "서버가 죽었는지 살았는지"만 확인하고 싶다면, Uptime Kuma 같은 훨씬 가벼운 툴이 낫다. Prometheus + Grafana는 어느 정도 규모가 있는 서비스에서 적합하다
요약!!! 다음과 같은 상황에서 이 조합 선택하기
진짜 최소 필요사양
Docker가 없다면 아래 명령으로 설치 여부를 먼저 확인
docker --version
docker compose version
둘 다 버전이 출력되면 준비 완료
작업할 폴더를 하나 만들고 그 안에 다음과 같은 구조를 준비
monitoring/
├── docker-compose.yml
└── prometheus/
└── prometheus.yml
터미널에서 실행하면 한 번에 만들 수 있음
mkdir -p monitoring/prometheus
cd monitoring
monitoring/prometheus/prometheus.yml 파일을 아래 내용으로 만듦
(이 파일은 Prometheus가 "어디서, 얼마나 자주" 데이터를 긁어올지 정의)
global:
scrape_interval: 15s # 15초마다 지표 수집
evaluation_interval: 15s
scrape_configs:
# Prometheus 자기 자신을 모니터링
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 서버(호스트)의 CPU, 메모리, 디스크 지표 수집
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
# 컨테이너별 리소스 사용량 수집
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
monitoring/docker-compose.yml 파일을 아래처럼 만듦
version: '3.8'
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
ports:
- "9090:9090"
restart: unless-stopped
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
ports:
- "9100:9100"
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
ports:
- "8080:8080"
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
restart: unless-stopped
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
GF_SECURITY_ADMIN_PASSWORD는 반드시 실제 사용할 비밀번호로 바꾸는 걸 추천
볼륨(prometheus_data, grafana_data)을 지정해 뒀기 때문에 컨테이너를 재시작해도 데이터는 유지되긴함
monitoring 폴더에서 아래 명령을 실행
docker compose up -d
-d는 백그라운드 실행 옵션
실행 후 아래 명령으로 4개 컨테이너가 모두 정상 기동됐는지 확인
docker compose ps
-> prometheus, node-exporter, cadvisor, grafana 4개 컨테이너 상태가 모두 Up이면 성공
http://localhost:9090에 접속UP 상태로 보여야 정상DOWN이면 prometheus.yml의 target 주소나 컨테이너 이름을 다시 확인http://localhost:3000에 접속admin / admin이며, 최초 로그인 시 비밀번호 변경을 요구할 수 있음로그인 후 데이터소스를 연결
http://prometheus:9090 입력 (컨테이너 이름으로 접속하므로 localhost가 아님에 주의)직접 패널을 만들 수도 있지만, 커뮤니티에 이미 잘 만들어진 대시보드를 가져다 쓰는 게 훨씬 빠르긴함
1860893모니터링 스택을 끄고 싶을 때는 다음 명령을 사용
docker compose stop
컨테이너와 네트워크까지 완전히 제거하되 데이터는 보존하려면 다음을 사용
docker compose down
데이터까지 완전히 삭제하려면 -v 옵션을 추가
docker compose down -v
기본 설치가 끝난 뒤 실무에서 더 필요해지는 것
Alertmanager를 추가하면 특정 조건(예: CPU 90% 초과 5분 지속)에서 슬랙이나 이메일로 알림을 받을 수 있다. 데이터 보관 기간을 늘리고 싶다면 Thanos나 VictoriaMetrics를 검토한다. 애플리케이션 자체의 커스텀 지표(예: 주문 처리 건수)를 수집하려면 각 언어별 Prometheus 클라이언트 라이브러리(Python, Java, Node.js 등)로 /metrics 엔드포인트를 직접 노출시키면 된다.