↓ Lewati ke konten utama
  1. Posts/

Cara Setup Monitoring Prometheus dan Grafana dengan Docker

Noor Khafidzin
Penulis
Noor Khafidzin
Seorang homelab enthusiast yang terobsesi pada efisiensi sistem dan seni pemecahan masalah (troubleshooting).
Daftar isi

Selama ini pemantauan homelab saya cuma berdua: SSH dan menebak. Setiap ada VM yang terasa lambat, saya masuk ke mesin yang salah lebih dulu, buka htop, keluar, lalu coba mesin berikutnya. Begitu komposisinya bertambah jadi satu Docker host, dua node Proxmox, dan beberapa VM lain, cara seperti ini tidak bisa dipertahankan lagi.

Solusinya adalah monitoring stack. Prometheus bertugas mengumpulkan metrik dari semua mesin, Grafana menampilkan metrik tersebut sebagai grafik dan dashboard, dan Alertmanager memberi tahu saya kalau ada nilai yang melewati ambang batas, misalnya disk hampir penuh. Semua komponennya berjalan sebagai container Docker di satu mesin, sedangkan mesin yang dipantau cukup menjalankan satu exporter ringan.

Artikel ini memandu proses setup dari nol sampai jadi, termasuk bagian yang sering dilewati tutorial lain: menarik metrik Proxmox VE langsung dari API-nya menggunakan PVE Exporter. Semua konfigurasi di sini ditulis dan diuji memakai Prometheus 3.15.1 dan Grafana OSS 13.3.0, dua versi stabil per November 2026. Untuk Anda yang baru pertama kali menyentuh Prometheus atau Grafana, cukup ikuti langkahnya secara berurutan karena setiap langkah menyiapkan file yang dibutuhkan langkah berikutnya.

Apa yang Akan Kita Bangun
#

Ada enam container yang berjalan di satu jaringan Docker:

Container Tugas Port
prometheus Menarik dan menyimpan metrik 9090
grafana Dashboard dan visualisasi 3000
node-exporter Metrik hardware dan OS 9100
cadvisor Metrik per-container Docker 8080
alertmanager Pengirim notifikasi alert 9093
pve-exporter Metrik Proxmox VE via API 9221

Prometheus bekerja dengan model pull. Setiap 15 detik dia mengunjungi URL /metrics di setiap target, lalu menyimpan angka yang ditemukan. Exporter adalah program kecil yang tugasnya menyediakan angka itu: node-exporter melaporkan CPU, memori, dan disk sebuah mesin; cadvisor melaporkan statistik per-container; dan pve-exporter bertanya ke API Proxmox lalu menerjemahkan jawabannya ke format Prometheus. Grafana sendiri tidak menyimpan apa pun, dia hanya menampilkan hasil query ke Prometheus.

flowchart LR
    subgraph SOURCES["Mesin & Layanan (Target Pantau)"]
        direction TB
        NE["Node Exporter
(Host, VM, PVE Nodes)
:9100"] CAD["cAdvisor
(Container Docker)
:8080"] PVE["Proxmox VE Cluster
(API Status)"] end PVEEXP["pve-exporter
:9221"] PVE -->|API Token| PVEEXP subgraph CORE["Monitoring Stack (Docker)"] direction TB PROM["Prometheus
:9090
(Scrape & TSDB)"] end NE -->|Pull /metrics| PROM CAD -->|Pull /metrics| PROM PVEEXP -->|Pull /pve| PROM subgraph OUTPUT["Visualisasi & Notifikasi"] direction TB GRAF["Grafana
:3000
(Dashboard)"] AM["Alertmanager
:9093"] NOTIF["Notifikasi
(Telegram / Discord / Webhook)"] end PROM -->|PromQL Query| GRAF PROM -->|Kirim Alert| AM AM --> NOTIF style PROM fill:#e6522c,stroke:#333,stroke-width:1px,color:#fff style GRAF fill:#f46800,stroke:#333,stroke-width:1px,color:#fff

Persiapan dan Prasyarat
#

  • Satu mesin Linux dengan Docker dan Docker Compose terpasang. Minimal 2 core CPU dan 4 GB RAM supaya nyaman.
  • Akses SSH ke mesin tersebut, serta ke mesin lain yang mau dipantau.
  • Minimal satu node Proxmox VE jika ingin mengikuti bagian PVE. Cukup akses web UI, tidak perlu menyentuh CLI Proxmox.
  • Waktu sekitar satu jam, sebagian besar untuk mengetik file konfigurasi dan menunggu image terunduh.

Langkah 1. Membuat Struktur Folder Proyek
#

mkdir -p monitoring-stack/prometheus monitoring-stack/alertmanager monitoring-stack/grafana/provisioning/datasources
cd monitoring-stack

Setiap folder punya satu tugas:

  • prometheus/ menyimpan prometheus.yml dan alert_rules.yml
  • alertmanager/ menyimpan alertmanager.yml
  • grafana/provisioning/datasources/ bisa diisi file yang mendaftarkan data source Prometheus secara otomatis

Penalaran Teknis: File konfigurasi sengaja diletakkan di luar container. Dengan begitu kita bisa mengeditnya dengan editor biasa lalu me-reload Prometheus tanpa build ulang apa pun.

Langkah 2. Konfigurasi Prometheus
#

Buat file prometheus/prometheus.yml dengan isi berikut, dan ganti alamat IP-nya dengan milik Anda:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets: ["alertmanager:9093"]

rule_files:
  - "alert_rules.yml"

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "node-exporter"
    static_configs:
      - targets: ["node-exporter:9100", "10.1.1.20:9100", "10.1.1.10:9100", "10.1.1.200:9100", "100.114.62.179:9100"]

  - job_name: "cadvisor"
    static_configs:
      - targets: ["cadvisor:8080"]

  - job_name: "pve"
    static_configs:
      - targets:
        - 10.1.1.20  # Proxmox VE node 1
        - 10.1.1.10  # Proxmox VE node 2
    metrics_path: /pve
    params:
      module: [default]
      cluster: ['1']
      node: ['1']
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: pve-exporter:9221  # PVE exporter

Satu file kecil lagi supaya Prometheus bisa langsung start. Isinya baru kita lengkapi di Langkah 10:

echo "groups: []" > prometheus/alert_rules.yml

Penalaran Teknis: Ada tiga hal penting di file di atas:

  • Di dalam jaringan Docker, container saling menghubungi lewat nama service. Target node-exporter:9100 adalah container dari compose kita sendiri, jadi dia otomatis memantau Docker host-nya.
  • Target berupa IP adalah mesin lain yang menjalankan node exporter secara native, bukan lewat Docker. Contoh di atas memantau dua node Proxmox di 10.1.1.20 dan 10.1.1.10, satu VM di 10.1.1.200, dan satu mesin kecil yang saya akses lewat VPN (makanya IP-nya diawali 100.). Sesuaikan semuanya dengan alamat Anda.
  • Job pve memang terlihat aneh, tapi logikanya sederhana. Prometheus tidak pernah menghubungi kedua IP node itu secara langsung. Tiga baris relabel_configs menulis ulang alamat scrape sehingga request yang sebenarnya dikirim ke pve-exporter:9221, dengan alamat node dibawa sebagai parameter. Satu container pve-exporter jadi melayani semua node Proxmox, dan tiap node tetap punya label instance sendiri.

Blok alerting dan rule_files merujuk ke Alertmanager serta file aturan alert yang akan kita buat di langkah-langkah berikutnya.

Langkah 3. Persiapan Node Proxmox
#

Di sini ada dua pekerjaan, dan keduanya dilakukan di sisi Proxmox, bukan di Docker. Pertama, tiap node Proxmox memasang node exporter dari repositori Debian. Kedua, kita membuat API token supaya pve-exporter boleh membaca data cluster.

Memasang Node Exporter di Tiap Node
#

SSH ke setiap node Proxmox lalu jalankan:

apt update
apt install prometheus-node-exporter

Paket ini otomatis berjalan sebagai service systemd dan menyajikan metrik di port 9100. Verifikasi singkat:

systemctl status prometheus-node-exporter
curl -s localhost:9100/metrics | head

Itulah alasan job node-exporter di prometheus.yml mendaftarkan IP node dengan port 9100. Tidak perlu Docker di sisi Proxmox, paket apt saja sudah cukup.

Membuat User dan API Token
#

PVE Exporter mengambil data lewat API Proxmox, jadi dia butuh token dengan izin baca. Berikut langkahnya di web UI:

  1. Buka Datacenter > Permissions > Users, klik Add. Beri nama grafana dengan realm Linux PAM, sehingga identitasnya menjadi grafana@pam.
Membuat user grafana di web UI Proxmox
  1. Lanjut ke Datacenter > Permissions > API Tokens, klik Add. Pilih user grafana@pam, isi Token ID dengan grafana, dan biarkan opsi Privilege separation tidak dicentang supaya token mewarisi izin user-nya.
Membuat API token untuk user grafana@pam
  1. Setelah dialog tertutup, rahasia token berupa deretan UUID ditampilkan sekali saja. Salin dan simpan dulu karena tidak bisa dilihat lagi nanti.

  2. Terakhir, beri izin baca. Buka Datacenter > Permissions > Add > User Permission, isi Path dengan /, pilih user grafana@pam, dan role PVEAuditor.

Memberi role PVEAuditor di level Datacenter

Penalaran Teknis: Izin yang dipasang di level Datacenter (path /) berlaku untuk semua node dalam cluster. Dua node saya ada dalam satu cluster, jadi satu token grafana@pam sudah mencakup 10.1.1.20 dan 10.1.1.10 sekaligus. Kalau node Anda berdiri sendiri-sendiri (tidak di-cluster), ulangi langkah user, token, dan permission ini di masing-masing node.

File Kredensial pve.yml
#

Buat file pve.yml di root proyek:

default:
  username: grafana@pam
  token_name: grafana
  token_value: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  verify_ssl: false

Ganti token_value dengan rahasia yang tadi disalin. Nilai verify_ssl: false biasanya diperlukan di homelab karena sertifikat Proxmox umumnya self-signed.

Langkah 4. Menulis File Docker Compose
#

Buat compose.yml di root proyek. Versi image sudah disesuaikan dengan rilis stabil terbaru, Prometheus v3.15.1 dan Grafana 13.3.0:

services:
  prometheus:
    image: prom/prometheus:v3.15.1
    container_name: prometheus
    volumes:
      - ./prometheus:/etc/prometheus
      - prometheus-data:/prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.retention.time=15d"
    ports:
      - "9090:9090"
    restart: unless-stopped
    networks:
      - frontend

  grafana:
    image: grafana/grafana-oss:13.3.0
    container_name: grafana
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=changeme_now
    restart: unless-stopped
    networks:
      - frontend

  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    pid: host
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - "--path.procfs=/host/proc"
      - "--path.sysfs=/host/sys"
      - "--path.rootfs=/rootfs"
    ports:
      - "9100:9100"
    restart: unless-stopped
    networks:
      - frontend

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - "8080:8080"
    restart: unless-stopped
    networks:
      - frontend

  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    volumes:
      - ./alertmanager:/etc/alertmanager
    ports:
      - "9093:9093"
    restart: unless-stopped
    networks:
      - frontend

  pve-exporter:
    image: prompve/prometheus-pve-exporter
    container_name: pve-exporter
    volumes:
      - ./pve.yml:/etc/prometheus/pve.yml
    ports:
      - "9221:9221"
    environment:
      - PROXMOX_VE_USERNAME=grafana@pam
      - PROXMOX_VE_TOKEN_NAME=grafana
      - PROXMOX_VE_TOKEN_VALUE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    restart: unless-stopped
    networks:
      - frontend

volumes:
  prometheus-data:
  grafana-data:

networks:
  frontend:
    external: true

Beberapa hal yang perlu dicatat dari file di atas:

  • Ganti GF_SECURITY_ADMIN_PASSWORD sebelum stack pertama kali dijalankan.
  • Dua named volume (prometheus-data dan grafana-data) menjaga data tetap hidup antar restart. Tanpa itu, semua data hilang setiap docker compose down.
  • Environment di service pve-exporter berisi kredensial yang sama dengan pve.yml. Kalau keduanya berbeda, environment variable yang menang, jadi pilih salah satu sebagai sumber utama dan jaga tetap sinkron.
  • Node exporter berjalan dengan pid: host dan beberapa mount read-only supaya bisa melihat proses dan filesystem asli host, bukan isi container-nya. Cadvisor butuh mount serupa untuk memeriksa container lain.
  • --storage.tsdb.retention.time=15d berarti Prometheus menyimpan data 15 hari. Kalau disk terbatas, kecilkan nilainya atau tambahkan --storage.tsdb.retention.size.

Tentang jaringan frontend: saya memakai jaringan Docker eksternal yang sudah ada sebelumnya di homelab saya, jaringan yang sama dengan yang dibuat di artikel Traefik saya. Kalau Anda belum punya, buat dulu dengan docker network create frontend, atau hapus saja semua blok networks: di atas dan biarkan Compose membuat jaringan bawaan untuk proyek ini.

Jangan jalankan stack dengan password default Grafana. Password bawaan adalah hal pertama yang dicoba bot setiap menemukan halaman login Grafana yang terbuka ke internet.

Langkah 5. Konfigurasi Alertmanager
#

Buat alertmanager/alertmanager.yml:

route:
  group_by: ["alertname"]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: default-webhook

receivers:
  - name: default-webhook
    webhook_configs:
      - url: http://contoh-webhook-anda/
        send_resolved: true

Bagian route menentukan bagaimana alert dikelompokkan dan dikirim. Alert dengan nama sama digabung jadi satu notifikasi lewat group_by, ada tunggu 30 detik sebelum pengiriman pertama (group_wait), dan alert yang masih aktif dikirim ulang tiap 4 jam (repeat_interval). Receiver di contoh ini berupa webhook. Nanti bisa diganti dengan Telegram, Discord, atau email, format konfigurasinya ada di dokumentasi resmi Alertmanager.

Selama belum ada alert yang aktif, Alertmanager tidak mengirim apa pun, jadi URL webhook placeholder seperti di atas tidak masalah untuk saat ini.

Langkah 6. Menjalankan Stack
#

docker compose up -d
docker compose ps

Harusnya muncul enam container dengan status Up. Container yang stuck di Restarting hampir selalu berarti ada volume yang mengarah ke file yang tidak ada. Periksa kembali jalurnya, pelakunya paling sering adalah pve.yml yang lupa dibuat.

Enam container monitoring berjalan

Langkah 7. Memeriksa Target di Prometheus
#

Buka http://localhost:9090/targets (ganti localhost dengan IP mesin kalau Anda browsing dari laptop). Harusnya ada sembilan target hijau: Prometheus sendiri, lima instance node-exporter, cadvisor, dan dua entri pve, satu per node Proxmox. Entri pve menampilkan IP node, bukan IP exporter, sebagai efek dari relabel di Langkah 2.

Semua target Prometheus berstatus UP

Target yang DOWN biasanya berarti IP salah, exporter-nya tidak jalan di mesin tersebut, atau ada firewall di antaranya. Klik targetnya untuk melihat pesan error-nya.

Langkah 8. Menghubungkan Grafana ke Prometheus
#

Masuk ke http://localhost:3000 dengan user admin dan password yang tadi diset di compose. Buka Connections > Data sources > Add data source, pilih Prometheus, isi URL dengan http://prometheus:9090, lalu klik Save & Test.

URL data source harus http://prometheus:9090, bukan localhost. Grafana berjalan di container-nya sendiri, dan localhost di dalam container itu menunjuk ke Grafana-nya sendiri, bukan ke Prometheus. Ini kesalahan paling umum pemula.
Data source Prometheus berhasil terhubung ke Grafana

Kalau ingin data source terdaftar otomatis tanpa klik, buat grafana/provisioning/datasources/prometheus.yml:

apiVersion: 1
datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: true

Dengan file ini sudah ada sebelum stack pertama kali dijalankan, data source langsung tersedia begitu Grafana start.

Langkah 9. Membangun Dashboard Grafana
#

Panel pertama sebaiknya dicoba manual supaya konsep dasarnya paham. Buat dashboard baru lewat Dashboards > New > Add visualization, pilih data source Prometheus, lalu isi query:

rate(node_cpu_seconds_total{mode="idle"}[5m])

Query ini menghitung seberapa cepat waktu CPU idle berlalu dalam lima menit terakhir per core. Semakin sibuk mesin, semakin kecil nilainya.

Setelah itu, dashboard komunitas jauh lebih praktis. Buka Dashboards > Import dan masukkan ID berikut:

  • 1860, Node Exporter Full (halaman dashboard): tampilan lengkap satu mesin, dari CPU, memori, disk, sampai jaringan. Setelah import, pilih mesinnya dari dropdown Host. Semua mesin di job node-exporter muncul di sana, baik yang terpasang via apt maupun yang berjalan sebagai container.
  • 893, Docker and System Monitoring (halaman dashboard): tampilan per-container dari data cadvisor.
  • 10347, Proxmox via Prometheus (halaman dashboard): tampilan cluster dan node Proxmox dari data pve-exporter.
Dashboard Node Exporter Full di Grafana
Dashboard Proxmox dengan data PVE Exporter

Langkah 10. Aturan Alert
#

Sekarang lengkapi prometheus/alert_rules.yml yang tadi masih berupa placeholder:

groups:
  - name: host-alerts
    rules:
      - alert: HighCPUUsage
        expr: 100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High CPU usage on {{ $labels.instance }}"
          description: "CPU usage has been above 85% for 5 minutes on {{ $labels.instance }}."

      - alert: LowDiskSpace
        expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100 < 10
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "Low disk space on {{ $labels.instance }}"
          description: "Root filesystem free space is below 10% on {{ $labels.instance }}."

Aturan pertama membalik angka idle tadi menjadi persentase pemakaian CPU per mesin (avg by (instance)), lalu memicu alert kalau nilainya di atas 85%. Kalimat for: 5m artinya kondisi harus bertahan lima menit sebelum alert dianggap sah. Inilah yang mencegah kita diganggu karena lonjakan CPU sesaat. Aturan kedua memantau sisa ruang filesystem root dan masuk kriteria kritis kalau di bawah 10% selama sepuluh menit.

Terapkan tanpa restart:

curl -X POST http://localhost:9090/-/reload

Cek http://localhost:9090/alerts, keduanya harus muncul dengan status Inactive. Siklus hidupnya: Inactive (aman), Pending (kondisi terpenuhi tapi durasi for belum genap), lalu Firing (alert dikirim ke Alertmanager).

Dua alert rule berstatus Inactive

Kesalahan yang Sering Terjadi
#

  • Pakai localhost di target atau data source. Di dalam jaringan container, localhost menunjuk ke container itu sendiri. Pakai nama service atau IP mesin.
  • Melewatkan named volume. Tanpa volume, semua data metrik dan dashboard hilang setiap docker compose down.
  • Password default Grafana dibiarkan. Terutama kalau port 3000 bisa dijangkau dari luar.
  • Tidak memantau pertumbuhan disk. Prometheus terus menulis data selama 15 hari. Perhatikan ukuran volume prometheus-data, atau kecilkan retention.
  • Edit rule tapi tidak reload. Perubahan alert_rules.yml baru berlaku setelah endpoint /-/reload dipanggil atau container di-restart.
  • Mencampur angka node exporter dan cadvisor. Yang satu angka host, yang satu angka container. Memori terpakai 90% di cadvisor adalah pemakaian container, bukan mesinnya.
  • Alert tanpa for. Tanpa durasi, lonjakan sesaat langsung jadi notifikasi.

Troubleshooting Cepat
#

Gejala Kemungkinan penyebab Cek pertama
Target DOWN di /targets Exporter tidak jalan atau IP/port salah docker compose ps, lalu curl ke /metrics dari sisi Prometheus
Panel Grafana No data URL data source pakai localhost Ganti ke http://prometheus:9090
cAdvisor langsung exit Ada mount yang tidak lengkap Bandingkan blok volumes dengan contoh di atas
pve-exporter restart terus pve.yml tidak ada atau token salah docker logs pve-exporter
Alertmanager tidak mau start YAML tidak valid docker logs alertmanager, atau validasi dengan amtool check-config
Error YAML di Prometheus Typo di prometheus.yml docker logs prometheus, pesannya menyebut baris persisnya

Pertanyaan yang Sering Diajukan
#

Apakah Prometheus dan Grafana gratis? Ya, keduanya open source dan bisa dijalankan di server sendiri tanpa biaya lisensi. Yang Anda bayar hanyalah hardware yang menjalankannya.

Berapa RAM yang dibutuhkan? Untuk skala di artikel ini, 4 GB RAM dan 2 core sudah nyaman. Pemakaian bertambah seiring jumlah target yang dipantau dan panjang retention.

Apakah Grafana bisa jalan tanpa Prometheus? Bisa. Grafana mendukung banyak data source lain seperti Loki, InfluxDB, sampai database SQL. Prometheus hanya salah satu pilihan yang paling umum untuk metrik.

Bagaimana kalau mesin utamanya Windows? Docker Desktop dengan backend WSL 2 bisa menjalankan stack ini. Catatannya, node exporter tidak bisa melaporkan metrik host Windows dengan benar, jadi angka CPU dan memori Windows host-nya tidak akurat.

Berapa lama data disimpan? Di konfigurasi artikel ini 15 hari, sesuai flag --storage.tsdb.retention.time=15d. Naikkan atau turunkan sesuai kapasitas disk. Data lama tidak hilang saat upgrade selama named volume-nya tidak dihapus.

Penutup
#

Sekarang semua mesin di homelab, container Docker, sampai cluster Proxmox bisa dipantau dari satu halaman Grafana, dan ada dua alert yang berjaga kalau CPU atau disk bermasalah. Langkah berikutnya yang wajar: ganti receiver webhook Alertmanager dengan notifikasi yang benar-benar Anda baca, tambahkan exporter untuk aplikasi tertentu, dan sesuaikan retention dengan kapasitas disk.

Kalau ada langkah yang macet atau hasilnya berbeda dari yang ditulis, ceritakan di komentar, saya bantu cek.

Terkait


Muat Komentar