Prometheus, Loki, InfluxDB 등 100개 이상의 데이터 소스를 연결하는 오픈소스 시각화 플랫폼
개요
Grafana는 메트릭, 로그, 트레이스를 시각화하고 분석하는 오픈소스 플랫폼입니다. Prometheus, InfluxDB, Elasticsearch, MySQL 등 100개 이상의 데이터 소스를 지원하며, 강력한 대시보드와 알림 기능을 제공합니다. 홈랩부터 엔터프라이즈까지 가장 널리 사용되는 모니터링 시각화 도구입니다.
| 항목 | 내용 |
|---|---|
| 공식 사이트 | https://grafana.com |
| GitHub | https://github.com/grafana/grafana |
| 라이선스 | AGPL-3.0 (OSS), Enterprise |
| GitHub Stars | 66k+ |
| Docker 이미지 | grafana/grafana:latest |
| 기본 포트 | 3000 |
| 최신 버전 | 12.x (2025) |
왜 Grafana인가?
1. 데이터 소스 통합의 왕
100개 이상의 데이터 소스를 지원합니다. Prometheus, InfluxDB, Elasticsearch, MySQL, PostgreSQL, CloudWatch, Azure Monitor 등 거의 모든 모니터링 백엔드와 연결됩니다.
2. 강력한 시각화
시계열 그래프, 게이지, 히트맵, 테이블, 지리 맵 등 다양한 패널 유형을 제공합니다. 드래그앤드롭으로 대시보드를 구성하고, PromQL, LogQL 등 쿼리 언어로 데이터를 자유롭게 조작할 수 있습니다.
3. 통합 알림 시스템
Grafana Alerting으로 메트릭과 로그 기반 알림을 설정합니다. Slack, Email, PagerDuty, Webhook 등 다양한 알림 채널을 지원합니다.
4. 커뮤니티 대시보드
grafana.com에 수천 개의 커뮤니티 대시보드가 공유되어 있습니다. ID만 입력하면 바로 가져와서 사용할 수 있습니다.
5. 멀티 테넌시
조직(Organization) 기능으로 팀별/프로젝트별로 대시보드와 데이터 소스를 분리할 수 있습니다.
Grafana 에코시스템
Grafana Labs는 Grafana를 중심으로 완전한 옵저버빌리티 스택을 제공합니다.
| 도구 | 역할 | 설명 |
|---|---|---|
| Grafana | 시각화 | 대시보드, 알림, 탐색 |
| Prometheus | 메트릭 | 시계열 메트릭 수집/저장 |
| Loki | 로그 | 로그 수집/저장 (Prometheus 스타일) |
| Tempo | 트레이스 | 분산 트레이싱 |
| Alloy | 에이전트 | 메트릭/로그 수집 에이전트 (Promtail 후속) |
| Mimir | 메트릭 스토리지 | 대규모 Prometheus 메트릭 저장 |
Grafana vs 다른 도구
| 항목 | Grafana | Kibana | Datadog |
|---|---|---|---|
| 라이선스 | AGPL-3.0 | Elastic License | SaaS |
| 가격 | 무료 (OSS) | 무료 (제한적) | $15+/호스트/월 |
| 데이터 소스 | 100개+ | Elasticsearch 중심 | 자체 에이전트 |
| 셀프호스팅 | ✅ | ✅ | ❌ |
| 알림 | ✅ 내장 | ⚠️ 별도 설정 | ✅ |
| 학습 곡선 | 중간 | 중간 | 낮음 |
| 추천 대상 | 홈랩, DevOps | ELK 스택 사용자 | 엔터프라이즈 |
Docker Compose로 설치하기
Grafana 단독 설치
services:
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=your-secure-password
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
grafana-data:
설치 및 실행
mkdir -p ~/grafana && cd ~/grafana
# docker-compose.yml 파일 생성 후
docker compose up -d
브라우저에서 http://<서버IP>:3000으로 접속합니다.
- 기본 계정: admin / admin (첫 로그인 시 변경 요구)
완전한 모니터링 스택 (PLG Stack)
Prometheus + Loki + Grafana 조합으로 메트릭과 로그를 함께 모니터링합니다.
전체 스택 docker-compose.yml
services:
# Grafana - 시각화
grafana:
image: grafana/grafana:latest
container_name: grafana
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
- ./provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
- GF_USERS_ALLOW_SIGN_UP=false
depends_on:
- prometheus
- loki
# Prometheus - 메트릭 수집/저장
prometheus:
image: prom/prometheus:latest
container_name: prometheus
restart: unless-stopped
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=15d'
# Loki - 로그 수집/저장
loki:
image: grafana/loki:latest
container_name: loki
restart: unless-stopped
ports:
- "3100:3100"
volumes:
- ./loki-config.yml:/etc/loki/local-config.yaml
- loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
# Promtail - 로그 수집 에이전트
promtail:
image: grafana/promtail:latest
container_name: promtail
restart: unless-stopped
volumes:
- ./promtail-config.yml:/etc/promtail/config.yml
- /var/log:/var/log:ro
- /var/run/docker.sock:/var/run/docker.sock
command: -config.file=/etc/promtail/config.yml
depends_on:
- loki
# Node Exporter - 시스템 메트릭
node-exporter:
image: prom/node-exporter:latest
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
# cAdvisor - 컨테이너 메트릭
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
volumes:
grafana-data:
prometheus-data:
loki-data:
prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node-exporter'
static_configs:
- targets: ['node-exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'loki'
static_configs:
- targets: ['loki:3100']
loki-config.yml
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
limits_config:
retention_period: 168h # 7일
promtail-config.yml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# 시스템 로그
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*.log
# Docker 컨테이너 로그
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'stream'
데이터 소스 자동 프로비저닝
provisioning/datasources/datasources.yml:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
isDefault: true
access: proxy
- name: Loki
type: loki
url: http://loki:3100
access: proxy
데이터 소스 설정
주요 데이터 소스
| 데이터 소스 | 용도 | URL 예시 |
|---|---|---|
| Prometheus | 시계열 메트릭 | http://prometheus:9090 |
| Loki | 로그 | http://loki:3100 |
| InfluxDB | 시계열 DB | http://influxdb:8086 |
| MySQL | 관계형 DB | mysql:3306 |
| PostgreSQL | 관계형 DB | postgres:5432 |
| Elasticsearch | 검색/로그 | http://elasticsearch:9200 |
데이터 소스 추가 방법
- 좌측 메뉴 → Connections → Data sources
- “Add data source” 클릭
- 데이터 소스 유형 선택 (예: Prometheus)
- URL 입력 및 인증 설정
- “Save & Test” 클릭
대시보드 생성
새 대시보드 만들기
- 좌측 메뉴 → Dashboards → New → New Dashboard
- “Add visualization” 클릭
- 데이터 소스 선택
- 쿼리 작성 (예: PromQL)
- 시각화 유형 선택
- 저장
커뮤니티 대시보드 가져오기
grafana.com에서 수천 개의 대시보드를 무료로 가져올 수 있습니다.
- Dashboards → New → Import
- Dashboard ID 입력 (예:
1860) - Load 클릭
- 데이터 소스 매핑
- Import
추천 커뮤니티 대시보드
| ID | 이름 | 용도 |
|---|---|---|
| 1860 | Node Exporter Full | 시스템 모니터링 |
| 893 | Docker and System | Docker + 시스템 |
| 179 | Docker Prometheus Monitoring | Docker 상세 |
| 13639 | NGINX Exporter | Nginx 모니터링 |
| 7362 | MySQL Overview | MySQL 모니터링 |
| 9628 | PostgreSQL Database | PostgreSQL 모니터링 |
주요 패널 유형
시계열 (Time Series)
기본 시계열 그래프. CPU, 메모리, 네트워크 트래픽 등.
# CPU 사용률
100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
게이지 (Gauge)
현재 값을 원형/반원형 게이지로 표시.
# 메모리 사용률
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
스탯 (Stat)
큰 숫자로 단일 값 표시.
# 업타임
(time() - node_boot_time_seconds) / 86400
테이블 (Table)
데이터를 테이블 형태로 표시.
히트맵 (Heatmap)
시간에 따른 분포를 히트맵으로 시각화.
로그 (Logs)
Loki 로그를 시각화.
{job="varlogs"} |= "error"
PromQL 기본
Prometheus 쿼리 언어로 메트릭을 조회합니다.
기본 쿼리
# 메트릭 조회
node_cpu_seconds_total
# 레이블 필터
node_cpu_seconds_total{mode="idle"}
# 시간 범위
node_cpu_seconds_total[5m]
집계 함수
# 평균
avg(node_cpu_seconds_total)
# 합계
sum(node_memory_MemTotal_bytes)
# 최대/최소
max(node_filesystem_avail_bytes)
min(node_filesystem_avail_bytes)
변화율
# 초당 변화율
rate(node_network_receive_bytes_total[5m])
# 순간 변화율
irate(node_cpu_seconds_total[5m])
실용 예시
# CPU 사용률 (%)
100 - (avg by(instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 메모리 사용률 (%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
# 디스크 사용률 (%)
100 - ((node_filesystem_avail_bytes / node_filesystem_size_bytes) * 100)
# 네트워크 수신 (MB/s)
rate(node_network_receive_bytes_total[5m]) / 1024 / 1024
# 컨테이너 메모리 사용량
container_memory_usage_bytes{name=~".+"}
LogQL 기본
Loki 로그 쿼리 언어입니다.
기본 쿼리
# 레이블로 필터
{job="varlogs"}
# 컨테이너 로그
{container="nginx"}
필터링
# 텍스트 포함
{job="varlogs"} |= "error"
# 텍스트 미포함
{job="varlogs"} != "debug"
# 정규식
{job="varlogs"} |~ "error|warning"
파싱
# JSON 파싱
{container="app"} | json
# logfmt 파싱
{job="varlogs"} | logfmt
# 특정 필드 추출
{container="nginx"} | pattern `<ip> - - [<_>] "<method> <path> <_>" <status>`
메트릭 추출
# 에러 로그 카운트 (1분간)
count_over_time({job="varlogs"} |= "error" [1m])
# 초당 로그 라인 수
rate({container="nginx"}[5m])
알림 설정
알림 규칙 생성
- Alerting → Alert rules → New alert rule
- 쿼리 작성 (예: CPU > 80%)
- 조건 설정 (임계값, 지속 시간)
- 알림 메시지 작성
- 저장
예시: CPU 알림
# Alert rule 설정
Query: 100 - (avg(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
Condition: WHEN last() OF A IS ABOVE 80
For: 5m
Contact Point 설정
알림을 받을 채널을 설정합니다.
- Alerting → Contact points → New contact point
- 유형 선택 (Slack, Email, Webhook 등)
- 설정 입력
- Test 후 저장
Slack 연동 예시
Type: Slack
Webhook URL: https://hooks.slack.com/services/xxx/xxx/xxx
Channel: #alerts
Title: {{ .CommonLabels.alertname }}
Text: {{ .CommonAnnotations.description }}
변수 (Variables)
대시보드에서 동적으로 값을 변경할 수 있습니다.
쿼리 변수
# 호스트 목록
label_values(node_uname_info, instance)
# 컨테이너 목록
label_values(container_memory_usage_bytes, name)
# Job 목록
label_values(up, job)
변수 사용
# 패널 쿼리에서 변수 사용
node_cpu_seconds_total{instance="$instance"}
# 여러 값 선택 가능
node_cpu_seconds_total{instance=~"$instance"}
환경 변수 설정
주요 환경 변수
environment:
# 관리자 계정
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=secure-password
# 사용자 가입 비활성화
- GF_USERS_ALLOW_SIGN_UP=false
# 익명 접근
- GF_AUTH_ANONYMOUS_ENABLED=false
# 서버 URL (리버스 프록시 사용 시)
- GF_SERVER_ROOT_URL=https://grafana.example.com
# 플러그인 설치
- GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-piechart-panel
# SMTP 설정
- GF_SMTP_ENABLED=true
- GF_SMTP_HOST=smtp.gmail.com:587
- GF_SMTP_USER=your-email@gmail.com
- GF_SMTP_PASSWORD=app-password
설정 파일 (grafana.ini)
[server]
root_url = https://grafana.example.com
[security]
admin_user = admin admin_password = secure-password
[users]
allow_sign_up = false
[auth.anonymous]
enabled = false
[smtp]
enabled = true host = smtp.gmail.com:587 user = your-email@gmail.com password = app-password
플러그인
인기 플러그인
| 플러그인 | 유형 | 용도 |
|---|---|---|
| grafana-clock-panel | Panel | 시계 위젯 |
| grafana-piechart-panel | Panel | 파이 차트 |
| grafana-worldmap-panel | Panel | 세계 지도 |
| alexanderzobnin-zabbix-app | App | Zabbix 연동 |
| redis-datasource | Data source | Redis |
플러그인 설치
# CLI로 설치
docker exec -it grafana grafana-cli plugins install grafana-clock-panel
docker restart grafana
# 또는 환경 변수로 설치
GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-piechart-panel
백업 및 복원
데이터 백업
# Grafana 데이터 백업
docker run --rm \
-v grafana-data:/data \
-v $(pwd):/backup \
alpine tar -czvf /backup/grafana-backup-$(date +%Y%m%d).tar.gz /data
# Prometheus 데이터 백업
docker run --rm \
-v prometheus-data:/data \
-v $(pwd):/backup \
alpine tar -czvf /backup/prometheus-backup-$(date +%Y%m%d).tar.gz /data
대시보드 내보내기
- 대시보드 열기
- Share → Export → Save to file
- JSON 파일 저장
대시보드 가져오기
- Dashboards → Import
- JSON 파일 업로드 또는 붙여넣기
- Import
트러블슈팅
데이터가 표시되지 않음
- 데이터 소스 연결 확인 (Save & Test)
- 시간 범위 확인 (우측 상단)
- 쿼리 올바른지 확인 (Explore에서 테스트)
- Prometheus에 타겟이 UP인지 확인
컨테이너 권한 문제
# Grafana 볼륨 권한 설정
sudo chown -R 472:472 ./grafana-data
메모리 부족
# docker-compose.yml에 리소스 제한 추가
deploy:
resources:
limits:
memory: 512M
Prometheus 스크래핑 실패
# Prometheus 타겟 상태 확인
http://<prometheus-ip>:9090/targets
마무리
Grafana는 메트릭 시각화의 사실상 표준입니다. Prometheus와 조합하면 강력한 메트릭 모니터링을, Loki와 조합하면 로그 분석을, 둘을 함께 사용하면 완전한 옵저버빌리티 스택을 구축할 수 있습니다.
커뮤니티 대시보드를 활용하면 몇 분 만에 전문적인 모니터링 환경을 만들 수 있고, PromQL과 LogQL을 익히면 어떤 데이터든 자유롭게 쿼리하고 시각화할 수 있습니다.
홈랩 모니터링부터 엔터프라이즈 옵저버빌리티까지, Grafana는 가장 신뢰할 수 있는 선택입니다.