跳轉至

Monitoring(Grafana + Prometheus + Loki 監控系統)

Overview

Monitoring 係 benhoweb.com 嘅自托管(self-hosted)基礎監控服務,部署喺 Oracle Cloud Infrastructure(OCI)嘅 ARM64 實例上。佢嘅作用係統一收集、儲存、可視化同警示成個平台所有服務嘅運行狀態,令管理員可以喺單一 Dashboard 入面掌握一切。

成個 Stack 由七個核心組件組成:GrafanaPrometheusLokicAdvisorPromtailAlertmanagerNode Exporter,構成一套完整嘅「指標(Metrics)+ 日誌(Logs)」雙軌監控方案。指標方面,Prometheus 負責拉取同儲存各服務嘅 /metrics 數據;日誌方面,Promtail 收集 Docker Log 並推送至 Loki;最後全部集中喺 Grafana 做可視化查詢同 Alertmanager 做警示通知。

Monitoring 服務奉行「一件新服務一個 Container」嘅原則,所有組件都以 Docker Compose 管理,並透過 Cloudflare Tunnel 安全接入,唔會喺 Host 上面開放任何 Port。呢個設計令監控系統本身亦成為妥善管理嘅一部分,符合整體基建嘅零信任網絡策略。另外,Grafana 嘅後端資料庫直接共用 pg-main,體現「新服務一律共用 pg-main」嘅平台政策。

Architecture

Monitoring Stack 喺單一 Oracle Cloud ARM64 實例上運行,所有服務透過 Docker Compose 綑綁喺同一個名為 cf_network 嘅外部 Docker 網絡。架構可以分為以下幾個層次:

核心組件

  • Grafana(13.1.1):監控 Dashboard 前端,提供統一嘅可視化介面。佢嘅設定資料庫唔係本地 SQLite,而係 PostgreSQL——使用 pg-main 提供嘅 grafana database。
  • Prometheus:指標收集同儲存引擎,定期拉取各 exporter 嘅 /metrics 端點,並根據 rule 產生警示。
  • Loki:日誌聚合系統,以標籤方式索引日誌,配合 Grafana Explore 做日誌查詢。
  • cAdvisor:收集容器層面嘅資源使用數據(CPU、記憶體、網絡、磁碟 IO),俾 Prometheus scrape。
  • Promtail:日誌收集 agent,會自動發現 Docker Container 嘅 stdout/stderr 日誌並推送至 Loki。
  • Alertmanager:處理 Prometheus 產生嘅警示,經過去重、分組、抑制後,轉發至郵件、Telegram 等通知渠道。
  • Node Exporter:收集 Host(即 Oracle Cloud VM)層級嘅系統指標,例如 CPU load、記憶體使用量、磁碟空間、網絡流量。

網絡設計

所有 Web 服務(包括 Grafana)一律經由 Cloudflare Tunnel 對外提供,唔會直接暴露 Host Port。用戶透過 https://grafana.benhoweb.com 存取 Grafana,流量由 Cloudflare 邊緣進入 Tunnel,再轉發至 Stack 內部嘅 Grafana container。呢個設計有兩個好處:

  1. 完全隱藏實際 VM IP,大幅減少被掃描同攻擊嘅機會;
  2. TLS 終止由 Cloudflare 處理,內部唔使再管理證書。

數據流向

Node Exporter ──► Prometheus ──► Grafana
cAdvisor ──────► Prometheus ──► Alertmanager ──► 通知渠道
Promtail ──────► Loki ────────► Grafana

Deployment

前置要求

  • Oracle Cloud(OCI)ARM64 VM,建議至少 4 OCPU / 24 GB RAM,行 Ubuntu 或 Oracle Linux。
  • 已初始化 cf_network Docker external network:
docker network create cf_network
  • 已有運行中嘅 pg-main PostgreSQL 服務,並建立好 grafana 用戶同 database。
  • 準備 .env 檔案,包含 GF_SECURITY_ADMIN_PASSWORDGF_DATABASE_PASSWORD

部署步驟

  1. 建立目錄並放入 docker-compose.yml
mkdir -p ~/monitoring && cd ~/monitoring
  1. 確保 .env 檔案內容正確:
GF_SECURITY_ADMIN_PASSWORD=your_strong_password
GF_DATABASE_PASSWORD=your_grafana_db_password
  1. 啟動整個 Stack:
docker compose up -d
  1. 喺 Cloudflare Zero Trust Dashboard 建立 Tunnel,加入 Public Hostname:

  2. Subdomaingrafana

  3. Domainbenhoweb.com
  4. Servicehttp://grafana:3000

Cloudflare Tunnel 用戶端可以以 sidecar container 形式部署喺同一 cf_network 網絡,或者直接裝喺 Host 度。

Configuration

Grafana

Grafana 嘅關鍵設定全部透過環境變數注入:

  • 管理員帳號GF_SECURITY_ADMIN_USER=admin,密碼由 .env 提供,避免使用預設值。
  • PostgreSQL Backend
GF_DATABASE_TYPE: postgres
GF_DATABASE_HOST: pg-main:5432
GF_DATABASE_NAME: grafana
GF_DATABASE_USER: grafana
GF_DATABASE_PASSWORD: ${GF_DATABASE_PASSWORD}
GF_DATABASE_SSL_MODE: disable
  • Root URLGF_SERVER_ROOT_URL=https://grafana.benhoweb.com,確保經 Cloudflare Tunnel 存取時,Grafana 可以正確產生 URL。
  • 關閉更新檢查GF_ANALYTICS_REPORTING_ENABLED=falseGF_ANALYTICS_CHECK_FOR_UPDATES=falseGF_NEWS_NEWS_FEED_ENABLED=false,減少無謂嘅對外連線。

Prometheus

需要準備 prometheus.yml 定義 scrape targets:

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['node-exporter:9100']
  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

另外,Prometheus 需要掛載 alert rule 檔案,並將 alertmanager:9093 設為 Alertmanager 地址。

時間時區

所有容器統一設定 TZ: Asia/Hong_Kong,令 Log 時間戳同 Dashboard 時間顯示都符合香港用家習慣。

Operations

日常管理

  • 查閱日誌:Promtail 會自動收集所有 Container 嘅 stdout 日誌並送入 Loki,操作員可以喺 Grafana Explore 入面用 LogQL 查詢,完全唔使 SSH 入 VM。
  • 重啟服務:修改設定之後:
docker compose restart grafana prometheus
  • 更新映像:由於版本已經係固定(例如 grafana/grafana:13.1.1),升級時只需改 tag 再執行 docker compose up -d

備份策略

  • Grafana 嘅 database 由 pg-main 統一備份,啱啱符合平台嘅「共用 PostgreSQL」政策。
  • Prometheus 數據屬短期熱數據,預設 retention 為 15 日;如需更長保留期,可以加 --storage.tsdb.retention.time=30d,並考慮用額外 Block Volume 儲存。
  • Loki 嘅日誌數據同樣係短期,建議設定 retention 為 7 至 30 日。

監控自身

為咗避免「監控系統死咗但冇人知」,Stack 本身會被 Node Exporter 同 cAdvisor 監控;亦可以設定 Cron Job 定期檢查 https://grafana.benhoweb.com 嘅 HTTP 狀態,或用外部 Uptime Kuma 做健康檢查。

FAQ

點解 Grafana 要共用 pg-main?

根據 benhoweb.com 嘅平台政策,「新服務一律共用 pg-main」。好處係只需備份一個 PostgreSQL 實例、唔使每個服務各自起 Database Container、並可以透過 PostgreSQL role 統一管理權限。代價係 pg-main 成為單點,所以 pg-main 本身需要做定期 PITR 備份或 HA。

點解唔開 Host Port?

所有 Web 服務都用 Cloudflare Tunnel,原因係:

  1. 安全:VM 冇任何對外 Port,攻擊者根本無從入手;
  2. 穩定:Tunnel 出站連線唔需要 Dynamic DNS,亦唔怕 ISP 轉 IP;
  3. 一致:所有服務統一接入 cf_network,網絡設定簡單清晰。

Prometheus 會唔會好食空間?

Prometheus 嘅 TSDB 會按 retention policy 自動清理,預設 15 日。喺 ARM64 VM 上建議將 /prometheus 放喺 SSD Block Volume,同時可以調低 scrape interval 或者只收集必要嘅指標,控制儲存用量。

點解 Stack 入面冇 Grafana Agent / Alloy?

呢個 Stack 已經有 Promtail 做日誌收集,指標收集亦由 Prometheus 直接 pull 各 exporter 完成,所以唔需要額外嘅 Agent。若日後要收集 Kubernetes 或遠端機嘅數據,就可以考慮引入 Alloy。

點解要指定 Grafana 版本?

用固定版本(例如 13.1.1)可以確保部署可重現,避免「尋日仲得、今日爆咗」嘅情況。升級時經過測試先至改 tag,符合 Dockhand GitHub Stack 嘅管理哲學。


本頁面由 benhoweb.com 基建團隊維護,最後更新於 2026 年。

Source

Coverage auto (container scan)