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 /metrics dari 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 le dalam sumhistogram_quantile(0.99, sum by (le, endpoint) (...)) — tanpa le dalam sum, query salah secara matematis.

← Sebelumnya: Logging   Berikutnya: Alerting →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact