Instalasi Monitoring (Prometheus + Grafana)

Status: SUDAH DIIMPLEMENTASIKAN (8 Juli 2026)

kube-prometheus-stack sudah berjalan di namespace monitoring-system, mengumpulkan metrik dari Longhorn, Traefik, PostgreSQL/Patroni, dan MariaDB Galera. Grafana sudah diekspos via HTTPS. Halaman ini didokumentasikan sebagai catatan implementasi — bukan lagi rencana.

1. Keputusan Teknis Awal

Item Keputusan
Instance Grafana Baru, khusus oneKE — bukan reuse grafana.sikomut.ums.id (isolasi data cluster ini)
Chart kube-prometheus-stack (prometheus-community) — bundel Prometheus + Grafana + Alertmanager + node-exporter + kube-state-metrics
Namespace monitoring-system
Retensi Prometheus 15 hari (titik awal — bisa dinaikkan setelah pola kapasitas storage jelas)
Akses Grafana https://oneke.ums.id/grafana/ (subpath, domain existing, TLS oneke-root-tls)

2. StorageClass longhorn-hdd — Ternyata Belum Pernah Dibuat

Temuan: StorageClass sudah didokumentasikan berbulan-bulan tapi tidak pernah benar-benar ada di cluster

Deployment Prometheus gagal di awal dengan error storage class "longhorn-hdd" does not exist — padahal StorageClass ini sudah disebut di dokumentasi rencana sejak awal (untuk data umum/backup, berbeda dari longhorn-db-single yang dipakai Galera/Postgres). Ternyata belum pernah benar-benar dieksekusi. Dibuat baru saat sesi ini.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: longhorn-hdd
provisioner: driver.longhorn.io
parameters:
  numberOfReplicas: "2"
  staleReplicaTimeout: "30"
allowVolumeExpansion: true

Kenapa replika 2×, bukan 3× (default Longhorn)?

Atas permintaan eksplisit Admin, replika diturunkan ke 2× untuk StorageClass ini — cukup untuk data yang sifatnya operasional/observability (bukan sekritikal data transaksional Galera/Postgres yang tetap tak tersentuh), sekaligus menghemat kapasitas storage node yang sudah cukup terpakai (lihat §3).

3. Kapasitas Longhorn — "no available disk for replica"

Setelah StorageClass dibuat, PVC Prometheus tetap gagal dijadwalkan dengan error scheduling Longhorn "no available disk for replica". Root cause: PVC Galera (3× 50Gi) + PVC Postgres (3× 50Gi) = 300Gi nominal reservation sudah melebihi ambang batas aman (storage-minimal-available-percentage: 25) di 3 storage node berkapasitas 128,8GB masing-masing — meskipun actual usage datanya masih sangat kecil (Longhorn menghitung dari nominal request, bukan usage riil).

Keputusan yang diambil (dua langkah, dipilih Admin lewat opsi cepat vs resize PVC existing):

  1. Turunkan storage-minimal-available-percentage dari 25% → 10% (Setting Longhorn, cluster-wide): bash kubectl -n longhorn-system patch settings.longhorn.io storage-minimal-available-percentage \ --type=merge -p '{"value":"10"}'
  2. Perkecil permintaan storage Prometheus dari rencana awal 15Gi → 5Gi (masih cukup untuk retensi 15 hari dengan volume data monitoring saat ini): bash kubectl patch prometheus monitoring-kube-prometheus-prometheus -n monitoring-system \ --type=merge -p '{"spec":{"storage":{"volumeClaimTemplate":{"spec":{"resources":{"requests":{"storage":"5Gi"}}}}}}}'

4. Install kube-prometheus-stack

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
  -n monitoring-system --create-namespace \
  --set prometheus.prometheusSpec.retention=15d \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=longhorn-hdd \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=15Gi

(Ukuran storage lalu dipatch turun ke 5Gi setelah masalah kapasitas di §3 ditemukan.)

5. Routing Grafana — Subpath Tanpa stripPrefix

Gotcha: pola subpath Grafana beda dari phpMyAdmin/Longhorn

Grafana tidak dipakai dengan stripPrefix (beda dari phpMyAdmin/Longhorn/docs). Grafana perlu tahu bahwa ia dilayani dari subpath — diatur lewat server.root_url + server.serve_from_sub_path: true di grafana.ini, mirip pola pgAdmin (lihat instalasi Postgres §9).

Gotcha kedua: Helm --set dengan nested dotted key gagal senyap

Percobaan awal --set grafana.grafana\.ini.server.root_url=... tidak ter-apply — ConfigMap grafana.ini yang dihasilkan cuma berisi domain = '', tanpa root_url/serve_from_sub_path sama sekali, tanpa error apapun dari Helm. Fix: pakai values file eksplisit (-f), bukan --set untuk config bertingkat seperti ini.

# grafana-values.yaml
grafana:
  adminPassword: "<auto-generated, lihat §8>"
  grafana.ini:
    server:
      domain: oneke.ums.id
      root_url: "https://oneke.ums.id/grafana/"
      serve_from_sub_path: true
helm upgrade monitoring prometheus-community/kube-prometheus-stack \
  -n monitoring-system -f grafana-values.yaml --reuse-values

IngressRoute Traefik (tanpa stripPrefix, hanya redirect trailing-slash + priority eksplisit mengikuti pola yang sudah ditemukan di migrasi Dashboard/Longhorn):

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: grafana-ingressroute
  namespace: monitoring-system
spec:
  entryPoints: [web, websecure]
  routes:
    - match: Host(`oneke.ums.id`) && PathPrefix(`/grafana`)
      kind: Rule
      priority: 100
      middlewares:
        - name: redirect-grafana-slash
      services:
        - name: monitoring-grafana
          port: 80
  tls:
    secretName: oneke-root-tls

6. ServiceMonitor / PodMonitor Tambahan

Tiga sumber metrik ditambahkan secara manual (belum ter-cover otomatis oleh chart bawaan):

Monitor Tipe Target Port Catatan
longhorn-manager ServiceMonitor Service longhorn-backend (namespace longhorn-system) manager (9500) Port sudah bernama, langsung jalan
traefik PodMonitor Pod app.kubernetes.io/name=traefik (namespace traefik-system) metrics (9100) Port sudah bernama di container
patroni PodMonitor Pod application=spilo (namespace postgres-system) 8008 Port container tidak bernama — lihat gotcha di bawah
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: patroni
  namespace: monitoring-system
  labels:
    release: monitoring       # wajib cocok dengan podMonitorSelector Prometheus CR
spec:
  selector:
    matchLabels: { application: spilo }
  namespaceSelector:
    matchNames: [postgres-system]
  podMetricsEndpoints:
    - path: /metrics
      targetPort: 8008         # numeric, karena container port Patroni tidak diberi nama
      interval: 30s

Semua ServiceMonitor/PodMonitor kustom diberi label release: monitoring

Prometheus CR dari chart ini membatasi serviceMonitorSelector/podMonitorSelector ke matchLabels: {release: monitoring} — tanpa label ini, monitor dibuat tapi tidak pernah dipakai Prometheus (silent, tidak ada error).

7. Metrik MariaDB Galera — Native, Bukan Exporter Manual

Lebih mudah dari dugaan awal

Berbeda dari rencana awal (deploy mysqld_exporter manual), mariadb-operator v26.6.0 ternyata sudah mendukung metrics secara native lewat field spec.metrics di CRD MariaDB — tinggal di-enable, operator otomatis membuat Deployment exporter (mysqld-exporter) dan ServiceMonitor sendiri.

kubectl patch mariadb galera-cluster -n galera-system --type=merge -p '
spec:
  metrics:
    enabled: true
    username: monitoring
    passwordSecretKeyRef:
      name: galera-monitoring-password
      key: password
      generate: true
    serviceMonitor:
      prometheusRelease: monitoring   # otomatis diterjemahkan jadi label release: monitoring
      interval: 30s
'

Operator membuat Deployment terpisah galera-cluster-metrics (bukan sidecar per-pod) yang melakukan multi-target probe ke ketiga node Galera sekaligus (/probe?target=<node>:3306, mirip pola blackbox-exporter) — satu exporter, tiga target, masing-masing diberi label role (primary/replica).

8. Bug: Cache Secret Kubelet Basi — Config Baru Tidak Otomatis Terbaca

Bug ditemukan: ServiceMonitor/PodMonitor baru tidak muncul di target Prometheus meski config sudah benar

Setelah longhorn-manager, traefik, dan patroni dibuat, Prometheus Operator terbukti sudah meregenerasi Secret config (prometheus-monitoring-kube-prometheus-prometheus) dengan benar — isi Secret di API server sudah memuat ketiga job baru. Tapi /api/v1/targets di Prometheus yang sedang berjalan tidak menunjukkan target baru sama sekali (bukan down/unknown, benar-benar tidak ada). Diperiksa lebih lanjut: file yang ter-mount di dalam Pod (/etc/prometheus/config/prometheus.yaml.gz) masih versi lama, meski Secret di API server sudah berubah puluhan menit sebelumnya — kubelet tidak me-refresh volume Secret yang sedang dipakai Pod tersebut.

Solusi: restart Pod Prometheus (kubectl delete pod prometheus-monitoring-kube-prometheus-prometheus-0) memaksa StatefulSet membuat Pod baru yang me-mount Secret versi terbaru. Config-reloader sendiri (yang memantau perubahan file via fsnotify) tidak bisa membantu di sini karena masalahnya ada satu langkah sebelum itu — di level kubelet, bukan di file yang sudah ter-mount.

Pola ini kemungkinan akan terulang setiap kali ServiceMonitor/PodMonitor baru ditambahkan — dicatat sebagai catatan operasional untuk penambahan monitor berikutnya.

9. Hasil Verifikasi Target

kubectl exec <pod-curl-sementara> -- curl -s \
  'http://monitoring-kube-prometheus-prometheus.monitoring-system.svc.cluster.local:9090/api/v1/targets?state=active'
Job Target Status
serviceMonitor/monitoring-system/longhorn-manager/0 7 endpoint (semua manager node Longhorn) up semua
podMonitor/monitoring-system/traefik/0 2 pod Traefik up semua
podMonitor/monitoring-system/patroni/0 3 pod Patroni up semua
serviceMonitor/galera-system/galera-cluster-metrics/0..2 3 node Galera (primary + 2 replica) up semua

10. Ringkasan Kredensial

Password admin Grafana auto-generated saat instalasi Helm, tersimpan di Secret monitoring-grafana (namespace monitoring-system, key admin-password) — tidak dituliskan plaintext di dokumen ini:

kubectl get secret monitoring-grafana -n monitoring-system \
  -o jsonpath='{.data.admin-password}' | base64 -d

Ringkasan Eksekusi

Langkah Status
StorageClass longhorn-hdd (baru, replika 2×)
Namespace monitoring-system
kube-prometheus-stack (Prometheus + Grafana + Alertmanager)
Retensi Prometheus 15 hari, storage 5Gi
Threshold storage-minimal-available-percentage 25%→10%
Grafana di /grafana/ (serve_from_sub_path)
ServiceMonitor Longhorn + PodMonitor Traefik/Patroni ✅ Semua target up
Metrik Galera (native mariadb-operator metrics) ✅ Semua target up
Link Grafana di homepage oneke.ums.id

Diimplementasikan 8–9 Juli 2026. Lihat Errata & Rekonsiliasi untuk temuan lain di sesi-sesi sebelumnya.