iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0

今天我們要深入介紹 Grafana 和 Loki 這兩個強大的開源監控工具,並學習如何使用 docker-compose 部署這個監控平台。這個平台將成為我們監控網站 API 效能和日誌的重要基礎設施,為後續的 API 監控和效能分析做好準備。

什麼是 Grafana?

Grafana 是一個開源的數據可視化和監控平台,廣泛用於展示時間序列數據,如系統指標、業務指標和日誌數據。它提供了豐富的圖表類型和靈活的儀表板配置,讓使用者能夠創建美觀且資訊豐富的監控介面。

Grafana 的核心特性

  1. 多元化數據源支援

    • Prometheus, InfluxDB, Elasticsearch
    • MySQL, PostgreSQL, CloudWatch
    • Loki(日誌數據)
    • 和許多其他數據源
  2. 豐富的視覺化元件

    • 時間序列圖表
    • 儀表板和單一數值顯示
    • 表格、熱力圖、地理圖
    • 警報和通知系統
  3. 強大的查詢能力

    • 支持各種查詢語言(PromQL, LogQL 等)
    • 數據轉換和計算功能
    • 變數和模板功能
  4. 企業級功能

    • 使用者權限管理
    • 組織和團隊管理
    • 儀表板共享和匯出

什麼是 Loki?

Loki 是 Grafana 開發的輕量級日誌聚合系統,設計理念是"像 Prometheus 一樣,但針對日誌"。與傳統的日誌系統(如 ELK Stack)不同,Loki 不對日誌內容進行全文索引,而是只索引標籤(labels),這使得它更加輕量和成本效益。

Loki 的核心概念

  1. 標籤優先的架構

    • 只索引標籤,不索引日誌內容
    • 大幅降低存儲和運算成本
    • 快速的標籤查詢能力
  2. LogQL 查詢語言

    • 類似 PromQL 的語法
    • 支持日誌流過濾和聚合
    • 正則表達式和字串匹配
  3. 水平擴展性

    • 微服務架構設計
    • 支持多租戶
    • 雲原生和 Kubernetes 友好
  4. 與 Grafana 完美整合

    • 原生支持 Grafana 視覺化
    • 統一的查詢和警報介面
    • 日誌和指標的關聯分析

Loki 與傳統日誌系統的比較

特性 Loki ELK Stack 傳統日誌
索引策略 僅索引標籤 全文索引 檔案存儲
存儲成本 中等
查詢速度 快(標籤查詢) 快(全文搜索)
資源需求 輕量 重量 輕量
學習曲線 中等 陡峭 簡單
擴展性 優秀 良好 有限

Docker Compose 部署架構

我們將部署一個監控平台,包含以下核心組件:

┌─────────────┐    ┌─────────────┐
│   Grafana   │    │    Loki     │
│   (3000)    │────│   (3100)    │
│  視覺化介面  │    │  日誌儲存    │
└─────────────┘    └─────────────┘
       │                   │
       └──── 查詢與視覺化 ────┘
                  ▲
                  │
            ┌─────────────┐
            │  API 應用   │
            │ (直接推送)   │
            └─────────────┘

架構說明

  1. Grafana (port 3000) - 提供美觀的監控儀表板和查詢介面
  2. Loki (port 3100) - 輕量級日誌聚合系統,負責日誌儲存和查詢
  3. API 應用 - 透過 HTTP API 直接將日誌推送到 Loki(後續會介紹如何在 Django、FastAPI、Flask 中實作)

實作步驟

1. 環境準備

確保你的系統已安裝:

  • Docker
  • Docker Compose
  • 至少 2GB 可用記憶體
# 檢查 Docker 版本
docker --version
docker-compose --version

# 建立專案目錄
mkdir grafana-loki-stack
cd grafana-loki-stack

2. 建立 Docker Compose 配置

# docker-compose.yml
services:
  # Loki 日誌聚合服務
  loki:
    image: grafana/loki:3.0.1
    container_name: loki
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml
    volumes:
      - loki-data:/loki
      - ./loki-config.yaml:/etc/loki/local-config.yaml
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3100/ready"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 10s

  # Grafana 視覺化平台
  grafana:
    image: grafana/grafana:10.2.3
    container_name: grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_AUTH_ANONYMOUS_ENABLED=false
      - GF_INSTALL_PLUGINS=grafana-piechart-panel
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana-provisioning:/etc/grafana/provisioning
    ports:
      - "3000:3000"
    depends_on:
      loki:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

3. Loki 配置檔

# loki-config.yaml (適用於 Loki 3.0+)
auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9095

common:
  path_prefix: /loki
  storage:
    filesystem:
      chunks_directory: /loki/chunks
      rules_directory: /loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

query_range:
  results_cache:
    cache:
      embedded_cache:
        enabled: true
        max_size_mb: 100

schema_config:
  configs:
    - from: 2020-10-24
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  max_global_streams_per_user: 5000
  ingestion_rate_mb: 16
  ingestion_burst_size_mb: 32
  per_stream_rate_limit: 3MB
  per_stream_rate_limit_burst: 15MB

4. Grafana 自動配置

# grafana-provisioning/datasources/datasource.yml
apiVersion: 1

datasources:
  - name: Loki
    type: loki
    access: proxy
    orgId: 1
    url: http://loki:3100
    basicAuth: false
    isDefault: true
    version: 1
    editable: true
    jsonData:
      httpHeaderName1: "X-Scope-OrgID"
    secureJsonData:
      httpHeaderValue1: "tenant1"

部署和啟動

1. 啟動服務

# 啟動所有服務
docker-compose up -d

# 查看服務狀態
docker-compose ps

# 查看日誌
docker-compose logs -f

2. 服務驗證

檢查 Loki

# 檢查 Loki 健康狀態
curl http://localhost:3100/ready

# 查看 Loki 指標
curl http://localhost:3100/metrics

檢查 Grafana

  • 瀏覽器開啟:http://localhost:3000
  • 登入資訊:admin / admin123

3. 初始化設定

  1. 登入 Grafana

    • 使用設定的管理員帳號登入
  2. 驗證數據源

    • 前往 Configuration → Data sources
    • 確認 Loki 數據源已自動配置
  3. 測試查詢

    • 前往 Explore 頁面
    • 選擇 Loki 數據源
    • 執行查詢:{job="app-logs"}

上一篇
Day15 - 實戰演練:編寫 Locust 測試並執行分析
下一篇
Day17 - Django Middleware 實作 API 監控
系列文
Vibe Coding 後的挑戰:Locust x Loki 負載及監控20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言