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 Namespacenode:節點名稱level:日誌等級(info、error)
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:如何選擇#
| 比較維度 | Loki | Elasticsearch |
|---|---|---|
| 索引策略 | 只索引 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 品質、不適合全文搜尋)才能正確評估它是否適合你的場景。