Loki 的核心理念:只索引 Label,不索引內容#

Loki 是 Grafana Labs 推出的日誌聚合系統,它的設計哲學可以用一句話概括:「像 Prometheus,但用於 Logs」。

傳統的日誌系統(如 Elasticsearch)會對日誌內容做全文索引——每個單詞都建立倒排索引,讓你可以搜尋任意關鍵字。這很強大,但代價是儲存成本極高,因為索引本身可能比原始資料還大。

Loki 走了一條完全不同的路:它只對 Label(標籤)建索引,日誌內容以壓縮的 Chunk 形式儲存,查詢時才逐行掃描

這個決策背後的洞察是:在實際的除錯場景中,你通常已經知道要查哪個服務、哪個環境、哪個時間範圍——這些都是 Label。你不會漫無目的地全文搜尋。

為什麼不做全文索引#

全文索引的成本問題在規模化時會變得非常顯著:

  • Elasticsearch 的索引儲存開銷通常是原始資料的 1.5 到 3 倍,意味著 1 TB 的日誌需要 2.5 到 4 TB 的儲存空間
  • Loki 只索引 Label,日誌內容用壓縮演算法儲存,儲存成本可以降到原始資料的數分之一
  • 在大規模環境下,儲存成本的差距可達 5 到 10 倍

這不代表 Loki 一定比 Elasticsearch 好——而是兩者針對不同的使用模式做了不同的取捨。

Loki 的查詢效能取決於 Label 的設計品質。如果你的 Label 過於粗糙(例如只有 env=production),查詢時需要掃描的資料量就會很大,效能會下降。反之,Label 過於細緻會造成太多 Stream,也會影響效能。設計好的 Label 體系是用好 Loki 的關鍵。

Label:Loki 的核心概念#

Loki 的 Label 與 Prometheus 的 Label 共用相同的設計理念:一組 Key-Value 對,用來標識日誌流(Log Stream)

常見的 Label 包括:

  • job:應用程式名稱(如 user-api
  • namespace:Kubernetes Namespace
  • node:節點名稱
  • level:日誌等級(infoerror

Label 的設計原則#

  • 低基數(Low Cardinality):Label 的值不能太多。user_id 有數百萬種值,絕對不適合當 Label;env 只有 dev/staging/prod 幾種,很適合
  • 與 Prometheus 對齊:使用相同的 Label 命名,讓你可以從 Grafana 的 Metrics 面板直接跳轉到對應的 Logs
  • 靜態優先:Label 應該是相對穩定的屬性(服務名稱、環境、區域),而不是每筆日誌都不同的值

Loki 與 Prometheus 共用 Label 體系是一個極大的優勢。當你在 Grafana 的 Dashboard 上看到某個服務的錯誤率上升時,可以直接帶著相同的 Label 查詢對應的日誌——不需要在兩個系統之間手動對應。

LogQL:日誌的查詢語言#

LogQL 是 Loki 的查詢語言,語法受 PromQL 啟發,讓已經熟悉 Prometheus 的使用者能快速上手。

LogQL 的查詢分為兩大類:

Log 查詢#

用來搜尋和過濾日誌內容:

  • Label 篩選{job="user-api", level="error"} — 選出特定 Stream
  • 行過濾|= "timeout" 包含特定文字、!= "health" 排除特定文字
  • 解析| json| pattern 將非結構化日誌轉為可查詢的欄位

Metric 查詢#

將日誌轉換為數值指標:

  • rate():計算每秒的日誌行數(例如每秒錯誤日誌數)
  • count_over_time():計算時間範圍內的日誌總數
  • bytes_rate():計算每秒的日誌資料量

這意味著你可以用 Loki 的日誌資料來建立 Grafana Dashboard——不需要額外的 Metrics 系統就能追蹤日誌趨勢。

儲存架構:Chunk 與 Index 分離#

Loki 的儲存分為兩層:

  • Index:記錄「哪些 Label 組合存在」以及「對應的 Chunk 在哪裡」。體積小,可以存在 BoltDB、Cassandra 或 DynamoDB
  • Chunk:日誌內容的壓縮區塊。體積大,適合存在物件儲存(S3、GCS、MinIO)或本地檔案系統

這種分離架構帶來兩個好處:

  • 成本最佳化:Index 需要快速讀取但體積小,可以用較貴但快速的儲存;Chunk 體積大但不需要頻繁隨機讀取,用廉價的物件儲存即可
  • 彈性擴展:讀取和寫入可以分別擴展,不會互相影響

Loki 的適用場景#

最適合 Loki 的情境

  • 團隊已經在用 Grafana + Prometheus,想要將 Logs 整合到同一個平台
  • 成本敏感的環境,不需要全文搜尋,查詢時通常知道要找哪個服務的日誌
  • 中小規模的 Kubernetes 叢集,日誌量在可控範圍內

Loki 可能不是最佳選擇的情境

  • 需要對日誌做複雜的全文搜尋(如安全團隊搜尋特定攻擊模式)
  • 日誌主要用於商業分析,需要豐富的聚合與視覺化功能
  • 團隊不熟悉 Label 的設計模式,且沒有 Prometheus 背景

Loki vs Elasticsearch:如何選擇#

比較維度LokiElasticsearch
索引策略只索引 Label全文索引
儲存成本低(壓縮儲存、物件儲存)高(索引 + 副本)
查詢靈活度需要知道 Label,內容搜尋較慢任意全文搜尋,速度快
學習曲線熟悉 Prometheus 則很低需要學習 Elasticsearch 生態系
運維複雜度相對簡單叢集管理較複雜
生態整合與 Grafana 深度整合與 Kibana 深度整合(ELK Stack)

一個簡單的決策框架:如果你的日誌查詢 80% 以上都是「某個服務在某個時間範圍的日誌」,Loki 就夠了。如果你經常需要在所有日誌中搜尋任意關鍵字,Elasticsearch 更適合。

Loki Docker Driver#

Loki 提供了 Docker Log Driver,讓 Docker 容器的日誌可以直接送到 Loki,不需要額外的收集 Agent。

這在開發環境或小規模部署中很方便,但在 Production 環境中通常不建議使用——因為 Docker Log Driver 是同步的,如果 Loki 暫時不可用,可能會影響容器的日誌輸出甚至容器本身的運作。

在 Production 環境中,建議使用獨立的 Log 收集 Agent(如 Promtail、Fluent Bit)而非 Docker Log Driver。Agent 可以做本地緩衝,即使後端暫時不可用也不會影響應用程式。

小結#

Loki 的設計取捨清晰明確:用查詢靈活度換取成本與複雜度的大幅降低。如果你已經在 Grafana 生態系中,Loki 是最自然、最經濟的日誌解決方案。但它不是萬能的——理解它的限制(依賴 Label 品質、不適合全文搜尋)才能正確評估它是否適合你的場景。