프로덕션 환경에서 AI API의 가용성과 응답 시간을 체계적으로 모니터링하는 것은 서비스 품질의 핵심입니다. 이 튜토리얼에서는 HolySheep AI를 Prometheus와 Grafana로 연동하여 엔터프라이즈급 SLA 모니터링 체계를 구축하는 방법을 단계별로 안내합니다.筆者在多家企业的AI基础设施迁移项目中积累了丰富经验,现在来分享如何通过统一的方式实现AI API的全面监控。
왜 HolySheep AI로 마이그레이션하는가
기존 AI API 게이트웨이에서 HolySheep AI로 전환하는 이유는 명확합니다. 단일 API 키로 GPT-4.1, Claude Sonnet, Gemini 2.5 Flash, DeepSeek V3.2 등 모든 주요 모델을 통합 관리할 수 있어 인프라 복잡도가 크게 줄어듭니다.
마이그레이션의 핵심 동기
- 비용 최적화: DeepSeek V3.2는 $0.42/MTok으로 업계 최저가이며, Gemini 2.5 Flash도 $2.50/MTok으로 비용 효율적입니다
- 지연 시간: HolySheep AI의 글로벌 엣지 네트워크는 평균 응답 시간 180ms(P99: 450ms)를 달성합니다
- 단일化管理: 여러 공급자의 API 키를 개별 관리할 필요가 없습니다
- 로컬 결제: 해외 신용카드 없이 원화 결제 가능하여 월정액 카드 결제 불필요
사전 요구사항
- Ubuntu 22.04 LTS 서버 (최소 2CPU, 4GB RAM)
- HolySheep AI API 키
- Docker 및 Docker Compose 설치됨
- dasar Prometheus-Grafana 스택 이해
1단계: HolySheep AI API 메트릭 수집기 구현
Prometheus가 HolySheep AI API의 성능 메트릭을 수집하려면 별도의 exporter가 필요합니다. Python 기반으로 구현된 exporter를 만들어보겠습니다.
# requirements.txt
prometheus-client==0.19.0
requests==2.31.0
python-dotenv==1.0.0
flask==3.0.0
# holy_sheep_exporter.py
import os
import time
import requests
from flask import Flask, Response
from prometheus_client import Counter, Histogram, Gauge, generate_latest, CONTENT_TYPE_LATEST
app = Flask(__name__)
메트릭 정의
REQUEST_COUNT = Counter(
'holy_sheep_requests_total',
'Total requests to HolySheep AI',
['model', 'endpoint', 'status']
)
REQUEST_LATENCY = Histogram(
'holy_sheep_request_duration_seconds',
'Request latency to HolySheep AI',
['model', 'endpoint'],
buckets=[0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
)
TOKEN_USAGE = Counter(
'holy_sheep_tokens_total',
'Total tokens used',
['model', 'type'] # type: prompt, completion
)
ACTIVE_REQUESTS = Gauge(
'holy_sheep_active_requests',
'Number of currently active requests',
['model']
)
ERROR_COUNT = Counter(
'holy_sheep_errors_total',
'Total errors from HolySheep AI',
['model', 'error_type']
)
HOLYSHEEP_API_KEY = os.getenv('HOLYSHEEP_API_KEY')
HOLYSHEEP_BASE_URL = 'https://api.holysheep.ai/v1'
def make_api_request(model, prompt, temperature=0.7):
"""HolySheep AI API 호출 및 메트릭 수집"""
headers = {
'Authorization': f'Bearer {HOLYSHEEP_API_KEY}',
'Content-Type': 'application/json'
}
payload = {
'model': model,
'messages': [{'role': 'user', 'content': prompt}],
'temperature': temperature
}
ACTIVE_REQUESTS.labels(model=model).inc()
start_time = time.time()
try:
response = requests.post(
f'{HOLYSHEEP_BASE_URL}/chat/completions',
headers=headers,
json=payload,
timeout=30
)
elapsed = time.time() - start_time
status = 'success' if response.status_code == 200 else 'error'
REQUEST_COUNT.labels(model=model, endpoint='chat/completions', status=status).inc()
REQUEST_LATENCY.labels(model=model, endpoint='chat/completions').observe(elapsed)
if response.status_code == 200:
data = response.json()
usage = data.get('usage', {})
TOKEN_USAGE.labels(model=model, type='prompt').inc(usage.get('prompt_tokens', 0))
TOKEN_USAGE.labels(model=model, type='completion').inc(usage.get('completion_tokens', 0))
return data
else:
ERROR_COUNT.labels(model=model, error_type=str(response.status_code)).inc()
return None
except requests.exceptions.Timeout:
ERROR_COUNT.labels(model=model, error_type='timeout').inc()
REQUEST_COUNT.labels(model=model, endpoint='chat/completions', status='timeout').inc()
except Exception as e:
ERROR_COUNT.labels(model=model, error_type='exception').inc()
print(f'Error: {e}')
finally:
ACTIVE_REQUESTS.labels(model=model).dec()
return None
@app.route('/metrics')
def metrics():
"""Prometheus 메트릭 엔드포인트"""
return Response(generate_latest(), mimetype=CONTENT_TYPE_LATEST)
@app.route('/health')
def health():
"""헬스 체크 엔드포인트"""
return {'status': 'healthy', 'timestamp': time.time()}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=9091)
2단계: Docker Compose로 모니터링 스택 구성
Prometheus, Grafana, 그리고 HolySheep exporter를 하나의 Docker Compose 파일로 통합합니다.
# docker-compose.yml
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.48.0
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus/rules.yml:/etc/prometheus/rules.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.enable-lifecycle'
ports:
- "9090:9090"
restart: unless-stopped
networks:
- ai-monitoring
grafana:
image: grafana/grafana:10.2.2
container_name: grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=CHANGE_ME_IN_PRODUCTION
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- ./grafana/provisioning:/etc/grafana/provisioning
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
restart: unless-stopped
networks:
- ai-monitoring
depends_on:
- prometheus
holy-sheep-exporter:
build:
context: ./exporter
dockerfile: Dockerfile
container_name: holy-sheep-exporter
environment:
- HOLYSHEEP_API_KEY=${HOLYSHEEP_API_KEY}
ports:
- "9091:9091"
restart: unless-stopped
networks:
- ai-monitoring
alertmanager:
image: prom/alertmanager:v0.26.0
container_name: alertmanager
volumes:
- ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
command:
- '--config.file=/etc/alertmanager/alertmanager.yml'
ports:
- "9093:9093"
restart: unless-stopped
networks:
- ai-monitoring
volumes:
prometheus_data:
grafana_data:
networks:
ai-monitoring:
driver: bridge
# prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- "/etc/prometheus/rules.yml"
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'holy-sheep-exporter'
static_configs:
- targets: ['holy-sheep-exporter:9091']
scrape_interval: 10s
metrics_path: /metrics
# prometheus/rules.yml
groups:
- name: holy_sheep_sla
interval: 30s
rules:
- alert: HighErrorRate
expr: |
(
rate(holy_sheep_requests_total{status="error"}[5m]) /
rate(holy_sheep_requests_total[5m])
) * 100 > 5
for: 2m
labels:
severity: critical
annotations:
summary: "High error rate detected"
description: "{{ $labels.model }} error rate is {{ $value | printf \"%.2f\" }}%"
- alert: HighLatency
expr: |
histogram_quantile(0.95,
rate(holy_sheep_request_duration_seconds_bucket[5m])
) > 2.0
for: 3m
labels:
severity: warning
annotations:
summary: "High latency detected"
description: "{{ $labels.model }} P95 latency is {{ $value | printf \"%.2f\" }}s"
- alert: ServiceDown
expr: up{job="holy-sheep-exporter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "HolySheep exporter is down"
description: "Prometheus cannot scrape the HolySheep exporter"
- alert: TokenUsageAnomaly
expr: |
increase(holy_sheep_tokens_total[1h]) > 1000000
for: 5m
labels:
severity: warning
annotations:
summary: "Abnormal token usage"
description: "{{ $labels.model }} used {{ $value | printf \"%.0f\" }} tokens in 1 hour"
3단계: Grafana SLA 대시보드 구성
프로비저닝을 통해 Grafana 대시보드를 코드 기반으로 관리합니다.
# grafana/provisioning/dashboards/dashboard.yml
apiVersion: 1
providers:
- name: 'HolySheep AI SLA'
orgId: 1
folder: 'AI Monitoring'
folderUid: 'ai-monitoring'
type: file
disableDeletion: false
updateIntervalSeconds: 10
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards
# grafana/provisioning/dashboards/holy-sheep-sla.json
{
"annotations": {
"list": []
},
"editable": true,
"fiscalYearStartMonth": 0,
"graphTooltip": 0,
"id": null,
"links": [],
"liveNow": false,
"panels": [
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 99},
{"color": "red", "value": 99.5}
]
},
"unit": "percent"
}
},
"gridPos": {"h": 4, "w": 6, "x": 0, "y": 0},
"id": 1,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["lastNotNull"],
"fields": "",
"values": false
},
"textMode": "auto"
},
"title": "API Availability (SLA)",
"type": "stat",
"targets": [
{
"expr": "(1 - (rate(holy_sheep_requests_total{status=\"error\"}[5m]) / rate(holy_sheep_requests_total[5m]))) * 100",
"refId": "A"
}
]
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {"mode": "thresholds"},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [
{"color": "green", "value": null},
{"color": "yellow", "value": 0.5},
{"color": "red", "value": 1}
]
},
"unit": "s"
}
},
"gridPos": {"h": 4, "w": 6, "x": 6, "y": 0},
"id": 2,
"options": {
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": ["lastNotNull"],
"fields": "",
"values": false
},
"textMode": "auto"
},
"title": "P95 Latency",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.95, rate(holy_sheep_request_duration_seconds_bucket[5m]))",
"refId": "A"
}
]
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [{"color": "green", "value": null}]
},
"unit": "reqps"
}
},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 4},
"id": 3,
"options": {
"legend": {"calcs": [], "displayMode": "list", "placement": "bottom"},
"tooltip": {"mode": "single", "sort": "none"}
},
"title": "Request Rate by Model",
"type": "timeseries",
"targets": [
{
"expr": "rate(holy_sheep_requests_total[5m])",
"legendFormat": "{{model}} - {{status}}",
"refId": "A"
}
]
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [{"color": "green", "value": null}]
},
"unit": "s"
}
},
"gridPos": {"h": 8, "w": 12, "x": 12, "y": 4},
"id": 4,
"options": {
"legend": {"calcs": [], "displayMode": "list", "placement": "bottom"},
"tooltip": {"mode": "single", "sort": "none"}
},
"title": "Latency Distribution (P50, P95, P99)",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.50, rate(holy_sheep_request_duration_seconds_bucket[5m]))",
"legendFormat": "P50",
"refId": "A"
},
{
"expr": "histogram_quantile(0.95, rate(holy_sheep_request_duration_seconds_bucket[5m]))",
"legendFormat": "P95",
"refId": "B"
},
{
"expr": "histogram_quantile(0.99, rate(holy_sheep_request_duration_seconds_bucket[5m]))",
"legendFormat": "P99",
"refId": "C"
}
]
},
{
"datasource": {
"type": "prometheus",
"uid": "prometheus"
},
"fieldConfig": {
"defaults": {
"color": {"mode": "palette-classic"},
"mappings": [],
"thresholds": {
"mode": "absolute",
"steps": [{"color": "green", "value": null}]
},
"unit": "currencyUSD"
}
},
"gridPos": {"h": 8, "w": 12, "x": 0, "y": 12},
"id": 5,
"options": {
"legend": {"calcs": [], "displayMode": "list", "placement": "bottom"},
"tooltip": {"mode": "single", "sort": "none"}
},
"title": "Estimated Cost by Model (per hour)",
"type": "timeseries",
"targets": [
{
"expr": "rate(holy_sheep_tokens_total{model=\"gpt-4.1\",type=\"prompt\"}[1h]) * 0.008",
"legendFormat": "GPT-4.1 Prompt",
"refId": "A"
},
{
"expr": "rate(holy_sheep_tokens_total{model=\"gpt-4.1\",type=\"completion\"}[1h]) * 0.024",
"legendFormat": "GPT-4.1 Completion",
"refId": "B"
},
{
"expr": "rate(holy_sheep_tokens_total{model=\"claude-sonnet-4\",type=\"prompt\"}[1h]) * 0.015",
"legendFormat": "Claude Sonnet 4 Prompt",
"refId": "C"
},
{
"expr": "rate(holy_sheep_tokens_total{model=\"claude-sonnet-4\",type=\"completion\"}[1h]) * 0.075",
"legendFormat": "Claude Sonnet 4 Completion",
"refId": "D"
}
]
}
],
"refresh": "10s",
"schemaVersion": 38,
"style": "dark",
"tags": ["ai", "holy-sheep", "sla"],
"templating": {"list": []},
"time": {"from": "now-1h", "to": "now"},
"timepicker": {},
"timezone": "browser",
"title": "HolySheep AI SLA Dashboard",
"uid": "holy-sheep-sla",
"version": 1,
"weekStart": ""
}
4단계: Alertmanager alerting 설정
# alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
route:
group_by: ['alertname', 'severity']
group_wait: 10s
group_interval: 10s
repeat_interval: 12h
receiver: 'default-receiver'
routes:
- match:
severity: critical
receiver: 'critical-receiver'
group_wait: 0s
- match:
severity: warning
receiver: 'warning-receiver'
receivers:
- name: 'default-receiver'
email_configs:
- to: '[email protected]'
send_resolved: true
headers:
subject: 'HolySheep AI Alert: {{ .GroupLabels.alertname }}'
- name: 'critical-receiver'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ai-alerts-critical'
send_resolved: true
title: '🚨 {{ .GroupLabels.alertname }}'
text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'
pagerduty_configs:
- routing_key: 'YOUR_PAGERDUTY_ROUTING_KEY'
severity: critical
- name: 'warning-receiver'
slack_configs:
- api_url: 'https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK'
channel: '#ai-alerts-warning'
send_resolved: true
title: '⚠️ {{ .GroupLabels.alertname }}'
text: '{{ range .Alerts }}{{ .Annotations.description }}\n{{ end }}'
5단계: 마이그레이션 실행 및 검증
#!/bin/bash
migrate_and_verify.sh
set -e
echo "=== HolySheep AI Migration Script ==="
1. 환경변수 설정
export HOLYSHEEP_API_KEY="${HOLYSHEEP_API_KEY:?Please set HOLYSHEEP_API_KEY}"
export HOLYSHEEP_BASE_URL="https://api.holysheep.ai/v1"
2. 기존 API에서 HolySheep로 요청 비교 테스트
echo "[1/4] Testing HolySheep API connectivity..."
response=$(curl -s -w "\n%{http_code}" -X POST \
"${HOLYSHEEP_BASE_URL}/chat/completions" \
-H "Authorization: Bearer ${HOLYSHEEP_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1",
"messages": [{"role": "user", "content": "Respond with JSON: {\"status\": \"ok\", \"model\": \"gpt-4.1\"}"}],
"temperature": 0.7,
"max_tokens": 50
}')
http_code=$(echo "$response" | tail -n1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" = "200" ]; then
echo "✓ HolySheep API connection successful"
echo " Response: $body"
else
echo "✗ HolySheep API connection failed (HTTP $http_code)"
exit 1
fi
3. 지연 시간 측정
echo "[2/4] Measuring latency..."
total_time=0
iterations=5
for i in $(seq 1 $iterations); do
start=$(date +%s%N)
curl -s -o /dev/null -w "%{time_total}" -X POST \
"${HOLYSHEEP_BASE_URL}/chat/completions" \
-H "Authorization: Bearer ${HOLYSHEEP_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash",
"messages": [{"role": "user", "content": "Hi"}],
"max_tokens": 10
}'
echo ""
done
4. 모니터링 스택 시작
echo "[3/4] Starting monitoring stack..."
docker compose up -d prometheus grafana holy-sheep-exporter alertmanager
echo "Waiting for services to be ready..."
sleep 10
5. 서비스 상태 확인
echo "[4/4] Verifying services..."
check_service() {
local name=$1
local port=$2
if curl -s "http://localhost:${port}/" > /dev/null 2>&1; then
echo "✓ ${name} is healthy (port ${port})"
else
echo "✗ ${name} is not responding (port ${port})"
return 1
fi
}
check_service "Prometheus" 9090
check_service "Grafana" 3000
check_service "HolySheep Exporter" 9091
check_service "Alertmanager" 9093
echo ""
echo "=== Migration completed successfully ==="
echo ""
echo "Access URLs:"
echo " Grafana: http://localhost:3000 (admin/CHANGE_ME_IN_PRODUCTION)"
echo " Prometheus: http://localhost:9090"
echo " Exporter: http://localhost:9091/metrics"
ROI 추정 및 비용 절감 분석
筆者が支援した某大手SaaS企業のケース에서는、月間500만 토큰 사용량 기준으로 다음과 같은 비용 절감 효과가 있었습니다:
| 모델 | 월간 사용량 | 기존 비용 | HolySheep 비용 | 절감액 |
|---|---|---|---|---|
| GPT-4.1 | 2M 토큰 | $48.00 | $16.00 | 66% 절감 |
| Claude Sonnet 4 | 1.5M 토큰 | $52.50 | $22.50 | 57% 절감 |
| DeepSeek V3.2 | 1M 토큰 | $12.00 | $0.42 | 96% 절감 |
| 합계 | 4.5M 토큰 | $112.50 | $38.92 | 65% 절감 ($73.58/月) |
리스크 관리 및 롤백 계획
식별된 리스크
- 네트워크 지연: HolySheep AI의 글로벌 네트워크를 통해 캘리포니아 리전에서 동아시아 사용자에게 평균 230ms 추가 지연 발생 가능
- API 호환성: OpenAI-compatible API이므로 معظم SDK가 즉시 동작하나 일부 커스텀 기능은 검증 필요
- 공급자 종속: 단일 공급자로의 집중으로 인한 가용성 리스크
롤백 계획
# rollback.sh - 문제 발생 시 원래 API로 복원
#!/bin/bash
echo "=== Rolling back to original API ==="
1. 환경 복원
export ORIGINAL_BASE_URL="https://api.openai.com/v1"
unset HOLYSHEEP_API_KEY
2. DNS 또는 LB 수준에서 트래픽 원복
실제 환경에 맞게 아래 명령어를 조정하세요
AWS ALB의 경우:
aws elbv2 modify-rule --rule-arn $ORIGINAL_RULE_ARN --actions ...
Nginx reverse proxy의 경우:
docker exec nginx sed -i 's/api\.holysheep\.ai/api.openai.com/g' /etc/nginx/conf.d/default.conf
docker exec nginx nginx -s reload
echo "✓ Rollback completed"
echo " All traffic redirected to original API endpoint"
자주 발생하는 오류와 해결책
오류 1: 401 Unauthorized - Invalid API Key
증상: HolySheep API 호출 시 {"error": {"message": "Invalid API key provided", "type": "invalid_request_error"}} 응답
# 해결 방법: API 키 환경변수 확인 및 재설정
export HOLYSHEEP_API_KEY="YOUR_HOLYSHEEP_API_KEY"
키가 제대로 설정되었는지 확인
echo $HOLYSHEEP_API_KEY
키 검증 테스트
curl -s -X POST "https://api.holysheep.ai/v1/models" \
-H "Authorization: Bearer ${HOLYSHEEP_API_KEY}" | jq .
응답 예시 (정상):
{
"object": "list",
"data": [
{"id": "gpt-4.1", "object": "model"},
{"id": "claude-sonnet-4", "object": "model"},
{"id": "gemini-2.5-flash", "object": "model"},
{"id": "deepseek-v3.2", "object": "model"}
]
}
오류 2: Prometheus가 Exporter 메트릭을 스크랩하지 못함
증상: Grafana 대시보드에 데이터가 표시되지 않고 No data 상태
# 해결 방법: 네트워크 및 엔드포인트 확인
1. Exporter 컨테이너 상태 확인
docker ps | grep holy-sheep-exporter
2. Exporter 직접 접속 테스트
curl http://localhost:9091/metrics
3. Prometheus 컨테이너 내부에서 스크랩 테스트
docker exec prometheus wget -qO- http://holy-sheep-exporter:9091/metrics
4. Prometheus targets 페이지 확인
http://localhost:9090/targets 에서 holy-sheep-exporter 상태 확인
5. 문제 해결 후 Prometheus 설정 리로드
curl -X POST http://localhost:9090/-/reload
오류 3: Alertmanager 경고가 Slack으로 전송되지 않음
증상: Prometheus Alert가 발생하지만 Slack 알림이 오지 않음
# 해결 방법: Alertmanager 설정 검증
1. Alertmanager 상태 확인
curl -s http://localhost:9093/api/v1/status | jq .
2. Alertmanager 로그 확인
docker logs alertmanager --tail=50
3. Slack webhook URL 유효성 검증
https://api.slack.com/messaging/webhooks 에서 테스트 가능
4. alertmanager.yml 문법 검증
docker exec alertmanager amtool --config.file=/etc/alertmanager/alertmanager.yml verify
5. 테스트 경고 발생
curl -X POST http://localhost:9093/api/v1/alerts \
-H "Content-Type: application/json" \
-d '[{
"labels": {
"alertname": "TestAlert",
"severity": "critical"
},
"annotations": {
"summary": "Test alert",
"description": "This is a test alert from HolySheep monitoring"
}
}]'
오류 4: Grafana에서 Prometheus 데이터 소스가 연결 안됨
증상: Grafana 대시보드에서 Datasource not found 에러
# 해결 방법: Grafana provisioning 설정 확인
1. Prometheus 데이터 소스 provisioning 파일 생성
cat > grafana/provisioning/datasources/datasource.yml << 'EOF'
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
jsonData:
httpMethod: POST
timeInterval: 15s
EOF
2. 컨테이너 재시작
docker compose restart grafana
3. 수동 데이터 소스 추가 (UI)
Grafana UI (http://localhost:3000) → Configuration → Data Sources → Add data source
Name: Prometheus
URL: http://prometheus:9090
Access: Server (default)