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 負載及監控 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言