본문으로 건너뛰기

Grafana 대시보드 구성

Grafana는 Prometheus, Loki, InfluxDB 등 다양한 데이터소스의 메트릭과 로그를 시각화하는 오픈소스 분석 플랫폼입니다. 이 챕터에서는 Grafana 설치부터 Nginx와 Tomcat 전용 대시보드 구성, 알림 설정, JSON 프로비저닝, Loki 로그 패널 연동까지 운영 환경에서 즉시 활용할 수 있는 수준으로 다룹니다.


Grafana 설치

Docker로 설치 (권장)

docker run -d \
--name grafana \
-p 3000:3000 \
-e GF_SECURITY_ADMIN_USER=admin \
-e GF_SECURITY_ADMIN_PASSWORD=admin123 \
-v grafana-data:/var/lib/grafana \
grafana/grafana:10.4.2

# 브라우저에서 접근: http://localhost:3000
# 초기 계정: admin / admin123

apt로 설치 (Debian/Ubuntu)

# GPG 키 및 저장소 추가
sudo apt-get install -y apt-transport-https software-properties-common wget
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | \
sudo tee /etc/apt/sources.list.d/grafana.list

sudo apt-get update
sudo apt-get install -y grafana

# 서비스 시작
sudo systemctl enable --now grafana-server

# 상태 확인
sudo systemctl status grafana-server
# 웹 UI: http://localhost:3000

기본 설정 확인

# /etc/grafana/grafana.ini (주요 항목만)
[server]
http_port = 3000
domain = your-domain.com
root_url = https://%(domain)s/

[security]
admin_user = admin
admin_password = your-secure-password

[users]
allow_sign_up = false
default_theme = dark

[auth.anonymous]
enabled = false
sudo systemctl restart grafana-server

Prometheus 데이터소스 연결

웹 UI에서 수동 연결

  1. 좌측 메뉴 → Connections→ ** Data sources**→ ** Add data source**
  2. Prometheus 선택
  3. 설정:
    • Name: Prometheus
    • URL: http://prometheus:9090 (Docker Compose) 또는 http://localhost:9090
    • Scrape interval: 15s
  4. Save & test 클릭 → "Successfully queried the Prometheus API." 확인

API로 데이터소스 등록 (자동화)

curl -X POST http://admin:admin123@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Prometheus",
"type": "prometheus",
"url": "http://prometheus:9090",
"access": "proxy",
"isDefault": true,
"jsonData": {
"httpMethod": "POST",
"scrapeInterval": "15s"
}
}'

Nginx 대시보드 구성

공개 대시보드 임포트 (ID: 12559)

Grafana Labs에서 제공하는 공개 Nginx 대시보드를 임포트하는 가장 빠른 방법입니다:

  1. 좌측 메뉴 → Dashboards→ ** Import**
  2. Dashboard ID: 12559 입력 후 ** Load**클릭
  3. 데이터소스로 Prometheus 선택 후 Import

직접 패널 구성

Nginx 대시보드에서 핵심적으로 필요한 패널을 직접 만드는 방법입니다.

패널 1: 초당 요청 수 (RPS)

패널 유형: Time series
쿼리:
rate(nginx_http_requests_total[5m])
패널 제목: Nginx RPS
단위: reqps (requests/sec)

패널 2: 응답 시간 (p95)

패널 유형: Time series
쿼리:
histogram_quantile(0.95, rate(nginx_request_duration_seconds_bucket[5m]))
패널 제목: Response Time (p95)
단위: seconds
임계선: 1.0s (warning), 2.0s (critical)

패널 3: HTTP 상태 코드별 비율

패널 유형: Pie chart
쿼리:
sum by (status) (rate(nginx_http_requests_total[5m]))
패널 제목: HTTP Status Distribution

패널 4: 에러율 (5xx)

패널 유형: Stat
쿼리:
sum(rate(nginx_http_requests_total{status=~"5.."}[5m]))
/
sum(rate(nginx_http_requests_total[5m])) * 100
패널 제목: 5xx Error Rate (%)
임계값: 1% = yellow, 5% = red

패널 5: 활성 연결 수

패널 유형: Gauge
쿼리:
nginx_connections_active
패널 제목: Active Connections
최대값: 1000
임계값: 500 = yellow, 800 = red

패널 6: 연결 상태 분포 (Reading/Writing/Waiting)

패널 유형: Bar chart
쿼리들:
nginx_connections_reading (Alias: Reading)
nginx_connections_writing (Alias: Writing)
nginx_connections_waiting (Alias: Waiting)
패널 제목: Connection State

Tomcat 대시보드 구성

공개 대시보드 임포트 (ID: 4701)

JVM 모니터링을 위한 공개 대시보드:

  1. 좌측 메뉴 → Dashboards→ ** Import**
  2. Dashboard ID: 4701 입력 후 ** Load**
  3. 데이터소스로 Prometheus 선택 후 Import

Tomcat 전용 패널 구성

패널 1: JVM 힙 메모리 사용량

패널 유형: Time series
쿼리:
jvm_memory_heap_used_bytes (Alias: Used)
jvm_memory_heap_max_bytes (Alias: Max)
패널 제목: JVM Heap Memory
단위: bytes (auto)

패널 2: JVM 힙 사용률 (%)

패널 유형: Gauge
쿼리:
jvm_memory_heap_used_bytes / jvm_memory_heap_max_bytes * 100
패널 제목: JVM Heap Usage (%)
최대값: 100
임계값: 70 = yellow, 90 = red

패널 3: Tomcat 스레드 풀 현황

패널 유형: Time series
쿼리:
tomcat_threadpool_currentthreadcount{connector="http-nio-8080"} (Alias: Current)
tomcat_threadpool_currentthreadsbusy{connector="http-nio-8080"} (Alias: Busy)
tomcat_threadpool_maxthreads{connector="http-nio-8080"} (Alias: Max)
패널 제목: Thread Pool (http-nio-8080)

패널 4: 요청 처리량 (RPS)

패널 유형: Time series
쿼리:
rate(tomcat_requestcount_total{connector="http-nio-8080"}[5m])
패널 제목: Request Rate (RPS)
단위: reqps

패널 5: GC 실행 빈도

패널 유형: Time series
쿼리:
rate(jvm_gc_CollectionCount_total[5m])
패널 제목: GC Collection Rate

패널 6: GC 소요 시간

패널 유형: Time series
쿼리:
rate(jvm_gc_CollectionTime_total[5m])
패널 제목: GC Collection Time (ms/s)

알림(Alerting) 설정

Contact Point 설정 — Slack

  1. 좌측 메뉴 → Alerting→ ** Contact points**→ ** Add contact point**
  2. 이름: Slack-Ops
  3. Slack 선택
  4. Webhook URL: Slack 인입 웹훅 URL 입력
  5. Optional Slack settings:
    • Channel: #alerts
    • Username: Grafana Alert
    • Icon emoji: :bell:
  6. Test 버튼으로 메시지 확인 후 Save contact point

Contact Point 설정 — 이메일

# /etc/grafana/grafana.ini 에 SMTP 설정 추가
[smtp]
enabled = true
host = smtp.gmail.com:587
user = your-email@gmail.com
password = your-app-password
skip_verify = false
from_address = grafana@example.com
from_name = Grafana
sudo systemctl restart grafana-server

이메일 Contact Point 생성:

  1. Alerting→ ** Contact points**→ ** Add contact point**
  2. Email 선택
  3. Addresses: ops-team@example.com
  4. Save contact point

알림 룰 생성

  1. Alerting→ ** Alert rules**→ ** New alert rule**
  2. 쿼리 작성:
    # Nginx 5xx 에러율 5% 초과 알림
    sum(rate(nginx_http_requests_total{status=~"5.."}[5m]))
    /
    sum(rate(nginx_http_requests_total[5m])) * 100
  3. Conditions 설정:
    • Condition: IS ABOVE 5 (5% 초과 시 알림)
    • For: 2m (2분 지속 시 발화)
  4. Labels: severity=critical
  5. Notification policy 탭에서 Contact Point 연결
  6. Save rule

Notification Policy 설정

  1. Alerting→ ** Notification policies**
  2. 기본 정책 수정 또는 새 정책 추가
  3. Matchers: severity=critical → Contact Point: Slack-Ops
  4. Repeat interval: 12h

대시보드 JSON 프로비저닝 (자동 로드)

Grafana 시작 시 대시보드를 자동으로 로드하는 프로비저닝 기능입니다. CI/CD 파이프라인에서 대시보드를 코드로 관리할 때 유용합니다.

프로비저닝 설정

# /etc/grafana/provisioning/dashboards/default.yml
# 또는 grafana/provisioning/dashboards/default.yml (Docker)
apiVersion: 1

providers:
- name: 'default'
orgId: 1
type: file
disableDeletion: false
updateIntervalSeconds: 30 # 30초마다 변경 감지
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true

데이터소스 프로비저닝

# /etc/grafana/provisioning/datasources/prometheus.yml
apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
jsonData:
httpMethod: POST
scrapeInterval: "15s"
version: 1
editable: true

대시보드 JSON 내보내기 및 저장

UI에서 만든 대시보드를 JSON으로 내보내는 방법:

  1. 대시보드 우측 상단 Share 아이콘 → Export
  2. Export for sharing externally 토글 켜기
  3. Save to file 클릭 → nginx-dashboard.json 파일 다운로드
  4. 파일을 /var/lib/grafana/dashboards/ 또는 Docker 볼륨 마운트 경로에 복사

Docker Compose에서 자동 적용:

# docker-compose.yml
grafana:
image: grafana/grafana:10.4.2
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning:ro
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro

Grafana + Loki 연동 (로그 패널)

Loki는 Prometheus와 동일한 레이블 모델을 사용하는 로그 집계 시스템입니다. Grafana와 통합하면 메트릭과 로그를 같은 대시보드에서 분석할 수 있습니다.

Loki + Promtail Docker Compose 추가

# docker-compose.yml에 추가
loki:
image: grafana/loki:3.0.0
container_name: loki
ports:
- "3100:3100"
volumes:
- ./loki/loki-config.yml:/etc/loki/loki-config.yml:ro
- loki-data:/loki
command: -config.file=/etc/loki/loki-config.yml
networks:
- monitoring

promtail:
image: grafana/promtail:3.0.0
container_name: promtail
volumes:
- /var/log/nginx:/var/log/nginx:ro
- ./promtail/promtail-config.yml:/etc/promtail/config.yml:ro
command: -config.file=/etc/promtail/config.yml
depends_on:
- loki
networks:
- monitoring
# loki/loki-config.yml
auth_enabled: false

server:
http_listen_port: 3100

ingester:
lifecycler:
ring:
kvstore:
store: inmemory
replication_factor: 1
chunk_idle_period: 5m
chunk_retain_period: 30s

schema_config:
configs:
- from: 2024-01-01
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h

storage_config:
boltdb_shipper:
active_index_directory: /loki/index
cache_location: /loki/cache
filesystem:
directory: /loki/chunks

limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h
# promtail/promtail-config.yml
server:
http_listen_port: 9080

positions:
filename: /tmp/positions.yaml

clients:
- url: http://loki:3100/loki/api/v1/push

scrape_configs:
- job_name: nginx
static_configs:
- targets:
- localhost
labels:
job: nginx
__path__: /var/log/nginx/access.log
pipeline_stages:
- regex:
expression: '^(?P<remote_addr>\S+) - (?P<remote_user>\S+) \[(?P<time_local>[^\]]+)\] "(?P<request>[^"]+)" (?P<status>\d+) (?P<body_bytes_sent>\d+)'
- labels:
status:
remote_addr:

Loki 데이터소스 등록

curl -X POST http://admin:admin123@localhost:3000/api/datasources \
-H "Content-Type: application/json" \
-d '{
"name": "Loki",
"type": "loki",
"url": "http://loki:3100",
"access": "proxy"
}'

Grafana 로그 패널 구성

대시보드에 Logs 패널 추가:

  1. 대시보드 편집 → Add panel→ 패널 유형: ** Logs**
  2. 데이터소스: Loki
  3. 쿼리:
    # Nginx 5xx 에러 로그
    {job="nginx"} |= "\" 5" | regexp `(?P<status>\d{3})` | status =~ "5.."

    # 특정 IP 요청 로그
    {job="nginx"} |= "203.0.113.5"

    # 느린 요청 (응답 시간 포함 JSON 포맷)
    {job="nginx"} | json | request_time > 1.0
  4. 패널 저장

고수 팁

대시보드 폴더 구조: 프로비저닝 경로에서 foldersFromFilesStructure: true를 설정하면 디렉토리 구조가 Grafana의 폴더 구조로 자동 매핑됩니다.

grafana/dashboards/
├── nginx/
│ ├── nginx-overview.json
│ └── nginx-errors.json
└── tomcat/
├── jvm-metrics.json
└── tomcat-requests.json

변수를 활용한 동적 대시보드: 여러 서버를 하나의 대시보드에서 관리할 때는 템플릿 변수를 활용합니다.

  1. 대시보드 설정 → Variables→ ** Add variable**
  2. Type: Query
  3. 쿼리: label_values(nginx_connections_active, instance)
  4. 패널 쿼리에 $instance 변수 적용:
    nginx_connections_active{instance="$instance"}

Explore 기능: 좌측 메뉴의 ** Explore**에서 Prometheus와 Loki 쿼리를 즉석에서 실행하고 메트릭-로그를 함께 확인할 수 있어 장애 분석 시 매우 유용합니다.