Metrics dan Prometheus #
Log memberi tahu apa yang terjadi pada request individual. Metrics memberi gambaran sistemik: berapa request per detik, berapa error rate, berapa latensi rata-rata dan p99, berapa persen resource yang terpakai. Prometheus adalah de facto standar untuk metrics di ekosistem Kubernetes — ia dirancang khusus untuk lingkungan cloud-native yang dinamis di mana Pod bisa muncul dan menghilang kapan saja.
Arsitektur Prometheus di Kubernetes #
Komponen utama:
Prometheus Server
→ Scrape metrics dari endpoint /metrics di setiap target
→ Simpan sebagai time-series data
→ Evaluasi alerting rules
→ Expose query API untuk Grafana
ServiceMonitor / PodMonitor (via Prometheus Operator)
→ Definisikan target mana yang di-scrape
→ Kubernetes-native cara konfigurasi scraping
Alertmanager
→ Terima alert dari Prometheus
→ Route ke Slack, PagerDuty, email, dll
→ Deduplication dan grouping
kube-state-metrics
→ Expose state Kubernetes object sebagai metrics
→ Deployment replicas, Pod status, PVC status, dll
node-exporter
→ Expose metrics hardware dan OS dari setiap node
→ CPU, memory, disk, network di level node
Tipe Metrics Prometheus #
Counter:
→ Nilai yang hanya bisa naik (atau reset ke 0 saat restart)
→ Contoh: jumlah total request, jumlah error, jumlah bytes dikirim
→ Selalu akhiri dengan _total
→ Query: rate(http_requests_total[5m]) → request per detik
Gauge:
→ Nilai yang bisa naik dan turun
→ Contoh: jumlah Pod aktif, penggunaan memory saat ini, antrian tasks
→ Query: langsung tanpa fungsi rate
Histogram:
→ Distribusi nilai dalam bucket
→ Contoh: latensi request (bucket: <10ms, <50ms, <100ms, <500ms, ...)
→ Menghasilkan tiga metrics: _bucket, _sum, _count
→ Query: histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))
Summary:
→ Mirip Histogram tapi pre-calculated quantile di sisi client
→ Kurang fleksibel dari Histogram untuk aggregation lintas instance
→ Lebih jarang digunakan di Kubernetes
Instrumentasi Aplikasi #
# Python: menggunakan prometheus_client
from prometheus_client import Counter, Histogram, Gauge, start_http_server
REQUEST_COUNT = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status_code']
)
REQUEST_DURATION = Histogram(
'http_request_duration_seconds',
'HTTP request duration in seconds',
['method', 'endpoint'],
buckets=[.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5]
)
ACTIVE_CONNECTIONS = Gauge(
'active_connections',
'Number of active connections'
)
# Gunakan di handler
def handle_request(method, endpoint):
with REQUEST_DURATION.labels(method=method, endpoint=endpoint).time():
ACTIVE_CONNECTIONS.inc()
try:
response = process_request()
REQUEST_COUNT.labels(
method=method,
endpoint=endpoint,
status_code=response.status
).inc()
return response
finally:
ACTIVE_CONNECTIONS.dec()
# Expose /metrics endpoint
start_http_server(9090)
// Go: menggunakan prometheus/client_golang
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
requestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "http_requests_total",
Help: "Total HTTP requests",
}, []string{"method", "endpoint", "status_code"})
requestDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "HTTP request duration",
Buckets: prometheus.DefBuckets,
}, []string{"method", "endpoint"})
)
Prometheus Operator dan ServiceMonitor #
Prometheus Operator memudahkan konfigurasi scraping dengan Kubernetes-native resources:
# ServiceMonitor — definisikan endpoint mana yang di-scrape
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: api-monitor
namespace: monitoring # namespace Prometheus Operator
labels:
release: prometheus # label yang digunakan Prometheus untuk discover monitor
spec:
namespaceSelector:
matchNames:
- production
selector:
matchLabels:
app: api # pilih Service berlabel app=api
endpoints:
- port: metrics # nama port di Service
interval: 15s # scrape setiap 15 detik
path: /metrics
scheme: http
# Service harus expose port metrics dengan nama yang tepat
apiVersion: v1
kind: Service
metadata:
name: api-service
labels:
app: api
spec:
selector:
app: api
ports:
- name: http
port: 80
targetPort: 8080
- name: metrics # ← nama port yang direferensikan ServiceMonitor
port: 9090
targetPort: 9090
kube-state-metrics: Metrics Kubernetes Object #
kube-state-metrics mengekspos state Kubernetes sebagai metrics yang bisa di-query:
# Jumlah Pod yang tidak running
count(kube_pod_status_phase{namespace="production", phase!="Running"})
# Deployment yang tidak mencapai desired replicas
kube_deployment_status_replicas_available{namespace="production"}
!=
kube_deployment_spec_replicas{namespace="production"}
# PVC yang tidak bound
kube_persistentvolumeclaim_status_phase{phase!="Bound"}
# Node yang tidak ready
kube_node_status_condition{condition="Ready", status!="true"}
# Jumlah restart container (indikasi crash loop)
increase(kube_pod_container_status_restarts_total[1h]) > 5
PromQL: Query Language Prometheus #
# Request per detik selama 5 menit terakhir
rate(http_requests_total[5m])
# Error rate (persentase 5xx)
sum(rate(http_requests_total{status_code=~"5.."}[5m]))
/
sum(rate(http_requests_total[5m]))
* 100
# Latensi p99 per endpoint
histogram_quantile(0.99,
sum by (le, endpoint) (
rate(http_request_duration_seconds_bucket[5m])
)
)
# CPU usage per Pod
sum by (pod) (
rate(container_cpu_usage_seconds_total{
namespace="production",
container!=""
}[5m])
)
# Memory usage sebagai persentase dari limit
container_memory_usage_bytes{namespace="production"}
/
container_spec_memory_limit_bytes{namespace="production"}
* 100
Recording Rules untuk Performa #
Query yang kompleks di-evaluate setiap kali dashboard dimuat bisa lambat. Recording rules pre-compute hasil query secara berkala:
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: api-recording-rules
namespace: monitoring
spec:
groups:
- name: api.rules
interval: 30s
rules:
# Pre-compute error rate
- record: job:http_error_rate:ratio5m
expr: |
sum by (job) (rate(http_requests_total{status_code=~"5.."}[5m]))
/
sum by (job) (rate(http_requests_total[5m]))
# Pre-compute p99 latency per service
- record: job:http_request_duration_p99:5m
expr: |
histogram_quantile(0.99,
sum by (job, le) (
rate(http_request_duration_seconds_bucket[5m])
)
)
Four Golden Signals #
Empat metrik yang paling penting untuk setiap service:
1. Latency (Latensi)
Berapa lama request diselesaikan?
Pantau p50, p95, p99 — bukan average
→ histogram_quantile(0.99, ...)
2. Traffic (Throughput)
Berapa banyak request per detik?
→ rate(http_requests_total[5m])
3. Errors (Error Rate)
Berapa persen request yang gagal?
→ sum(rate(5xx[5m])) / sum(rate(all[5m]))
4. Saturation (Kejenuhan)
Seberapa penuh resource yang digunakan?
CPU usage % dari limit, memory % dari limit
→ container_cpu_usage / container_cpu_limit * 100
Ringkasan #
- Prometheus pull-based, bukan push — Prometheus scrape endpoint
/metricsdari target; tidak perlu konfigurasi di setiap service untuk tahu ke mana harus kirim; ServiceMonitor mendefinisikan target.- Histogram untuk latensi, Counter untuk volume — gunakan Histogram untuk data yang butuh percentile (latensi, ukuran payload); Counter untuk data kumulatif (jumlah request, errors).
- Four Golden Signals sebagai dashboard minimum — latensi p99, throughput (req/s), error rate, dan saturation (CPU/memory %) adalah metrik dasar untuk setiap service.
- kube-state-metrics untuk state Kubernetes — Deployment replicas, Pod status, PVC binding, node health — semua tersedia tanpa instrumentasi manual.
- Recording rules untuk dashboard yang responsif — query kompleks yang di-run setiap 15 detik sangat membebani Prometheus; pre-compute dengan recording rules.
- Histogram quantile butuh label
ledalam sum —histogram_quantile(0.99, sum by (le, endpoint) (...))— tanpaledalam sum, query salah secara matematis.