Prometheus
Kubernetesとクラウドネイティブ環境の事実上の標準監視システム。多次元データモデルとPromQLクエリ言語を提供し、HTTPプルモデルでメトリクスを収集。
監視サーバー
Prometheus
概要
Prometheusは、Kubernetesとクラウドネイティブ環境の事実上の標準監視システムです。多次元データモデルとPromQLクエリ言語を提供し、HTTPプルモデルでメトリクスを収集する時系列データベースです。SoundCloudで開発され、現在はCloud Native Computing Foundation(CNCF)の卒業プロジェクトとして、コンテナ化された環境でのアプリケーション監視に最適化されています。
詳細
Prometheusは2012年にSoundCloudで開発が開始され、2016年にCNCFの2番目の卒業プロジェクトとなりました。現在では採用率79%でKubernetes監視の事実上の標準となっており、2024年には7年ぶりのメジャーリリースであるPrometheus 3.0がリリースされ、OpenTelemetry統合が強化されました。
主要な技術的特徴
- 多次元データモデル: ラベルによる柔軟なメトリクス分類
- PromQLクエリ言語: 強力な時系列データクエリ機能
- HTTPプルモデル: スケーラブルなメトリクス収集方式
- Service Discovery: 動的な監視対象の自動発見
- Alertmanager連携: 柔軟なアラート管理機能
用途
- Kubernetesクラスター監視
- マイクロサービス監視
- アプリケーション性能監視(APM)
- インフラストラクチャ監視
- SLI/SLO管理
メリット・デメリット
メリット
- Kubernetes標準: K8s環境での事実上の標準監視システム
- 柔軟なクエリ: PromQLによる強力な分析機能
- スケーラビリティ: 大規模環境での高いパフォーマンス
- 豊富なエコシステム: 多数のExporterとサードパーティツール
- オープンソース: 無料で高機能な監視システム
- Cloud Native対応: コンテナ環境に最適化された設計
デメリット
- 学習コスト: PromQLの習得が必要
- 長期保存の制限: デフォルトでは長期データ保存に制限
- 高可用性設定の複雑さ: HA構成の設定が複雑
- リソース消費: 大量メトリクス収集時の高いリソース消費
- ダッシュボード機能: 可視化にはGrafana等の別ツールが必要
参考ページ
書き方の例
基本的なPrometheus設定
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
external_labels:
monitor: 'prometheus-monitor'
rule_files:
- "alert_rules.yml"
- "recording_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
scrape_configs:
# Prometheus自身の監視
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# Node Exporter
- job_name: 'node'
static_configs:
- targets:
- 'node1:9100'
- 'node2:9100'
- 'node3:9100'
# Kubernetes API Server
- job_name: 'kubernetes-apiservers'
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
# Application monitoring
- job_name: 'spring-boot-app'
metrics_path: '/actuator/prometheus'
static_configs:
- targets:
- 'app1:8080'
- 'app2:8080'
PromQLクエリ例
# 基本的なメトリクス取得
up
# 特定のジョブの稼働状況
up{job="node"}
# レート計算(5分間の平均レート)
rate(http_requests_total[5m])
# 集計関数の使用
sum(rate(http_requests_total[5m])) by (job)
# パーセンタイル計算
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
# CPU使用率計算
100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# メモリ使用率
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
# ディスク使用率
100 - ((node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes)
# レスポンスタイム集計
avg(rate(http_request_duration_seconds_sum[5m]) / rate(http_request_duration_seconds_count[5m]))
# エラー率
rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100
アラートルール設定
# alert_rules.yml
groups:
- name: basic.rules
rules:
# インスタンスダウン
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Instance {{ $labels.instance }} down"
description: "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 1 minute."
# 高CPU使用率
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "High CPU usage on {{ $labels.instance }}"
description: "CPU usage is above 80% for more than 5 minutes on {{ $labels.instance }}"
# 高メモリ使用率
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 5m
labels:
severity: critical
annotations:
summary: "High memory usage on {{ $labels.instance }}"
description: "Memory usage is above 90% on {{ $labels.instance }}"
# ディスク容量不足
- alert: DiskSpaceLow
expr: 100 - ((node_filesystem_avail_bytes * 100) / node_filesystem_size_bytes) > 85
for: 5m
labels:
severity: warning
annotations:
summary: "Disk space low on {{ $labels.instance }}"
description: "Disk usage is above 85% on {{ $labels.instance }}"
# HTTPエラー率
- alert: HighErrorRate
expr: rate(http_requests_total{status=~"5.."}[5m]) / rate(http_requests_total[5m]) * 100 > 5
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate on {{ $labels.instance }}"
description: "Error rate is above 5% for more than 5 minutes"
Recording Rules設定
# recording_rules.yml
groups:
- name: cpu_memory_rules
interval: 30s
rules:
# CPU使用率の記録ルール
- record: instance:cpu_usage:rate5m
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# メモリ使用率の記録ルール
- record: instance:memory_usage:ratio
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
- name: http_rules
interval: 30s
rules:
# HTTPリクエストレートの記録ルール
- record: job:http_requests:rate5m
expr: sum(rate(http_requests_total[5m])) by (job)
# HTTPエラー率の記録ルール
- record: job:http_errors:rate5m
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) by (job) / sum(rate(http_requests_total[5m])) by (job)
Kubernetes環境でのDeployment
# prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
namespace: monitoring
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
serviceAccountName: prometheus
containers:
- name: prometheus
image: prom/prometheus:v2.45.0
args:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus/'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
- '--web.enable-admin-api'
ports:
- containerPort: 9090
resources:
limits:
memory: "2Gi"
cpu: "1000m"
requests:
memory: "1Gi"
cpu: "500m"
volumeMounts:
- name: prometheus-config
mountPath: /etc/prometheus/
- name: prometheus-storage
mountPath: /prometheus/
volumes:
- name: prometheus-config
configMap:
name: prometheus-config
- name: prometheus-storage
persistentVolumeClaim:
claimName: prometheus-pvc
---
apiVersion: v1
kind: Service
metadata:
name: prometheus
namespace: monitoring
spec:
selector:
app: prometheus
ports:
- port: 9090
targetPort: 9090
type: ClusterIP
カスタムメトリクス(Go言語例)
package main
import (
"net/http"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
// Counter メトリクス
httpRequestsTotal = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total number of HTTP requests",
},
[]string{"method", "endpoint", "status"},
)
// Histogram メトリクス
httpDuration = promauto.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Duration of HTTP requests",
Buckets: prometheus.DefBuckets,
},
[]string{"method", "endpoint"},
)
// Gauge メトリクス
activeConnections = promauto.NewGauge(
prometheus.GaugeOpts{
Name: "active_connections",
Help: "Number of active connections",
},
)
)
func recordMetrics() {
go func() {
for {
activeConnections.Set(float64(time.Now().Unix() % 100))
time.Sleep(2 * time.Second)
}
}()
}
func main() {
recordMetrics()
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/api/users", func(w http.ResponseWriter, r *http.Request) {
timer := prometheus.NewTimer(httpDuration.WithLabelValues(r.Method, "/api/users"))
defer timer.ObserveDuration()
// ビジネスロジック処理
time.Sleep(100 * time.Millisecond)
httpRequestsTotal.WithLabelValues(r.Method, "/api/users", "200").Inc()
w.WriteHeader(http.StatusOK)
w.Write([]byte("OK"))
})
http.ListenAndServe(":8080", nil)
}