Promtail 是 Grafana Labs 為 Loki 量身打造的 Log Agent,名字來自 Prometheus 與 Linux 指令 tail 的結合。它的工作很單純:從本機檔案或容器抓 Log、補上 Label,再送到 Loki。設定檔風格延續 Prometheus 的習慣,對於熟悉 Prometheus scrape_configs 的使用者來說幾乎是無痛上手。

Promtail 已併入 Grafana Alloy。依官方公告,自 2025-02-13 起進入長期支援(LTS),僅提供安全性更新與重大錯誤修復;2026-03-02 將達到生命週期終點(EOL)。新建專案建議直接評估 Grafana Alloy,本章內容仍保留作為理解既有系統與概念的參考。

核心概念#

Tail#

對不熟 Linux 的讀者,先簡單說明 tail。它是預設顯示檔案最後 10 行的工具,可以用 -n 控制行數:

tail -n 20 /var/log/messages

加上 -f(follow)後,可以持續追蹤檔案新增的內容,這正是 Promtail 持續讀取 Log 檔案的核心動作:

tail -f /var/log/messages

順帶一提,tail -f /dev/null 是一個經典寫法,常被用來讓 Container 永久存活、方便進入除錯:

docker run -d python tail -f /dev/null

Service Discovery#

Promtail 透過 Service Discovery 決定要抓哪些 Log,設定方式跟 Prometheus 一樣,集中在 scrape_configs,可以同時定義多個 Job:

scrape_configs:
  - job_name: local
    static_configs:
      - ...

  - job_name: kubernetes
    kubernetes_sd_config:
      - ...

不同於 Prometheus,static_configs 在 Promtail 是用來描述本機的 Log 檔案:

scrape_configs:
  - job_name: local
    static_configs:
      labels:
        __path__: /var/log/*.log

__ 開頭的 Label 屬於內部使用,送到 Loki 之前會被自動移除。除了 static_configs,Promtail 還支援多種來源:

  • docker_sd_config:對應 Docker Container 的 Log,並把 Docker 相關資訊轉換為 Label。
  • kubernetes_sd_config:透過 Kubernetes API 抓 Container Log,自動帶上 Pod、Namespace 等 Metadata。
  • kafka:從 Kafka Topic 訂閱 Log。

各種 SD 都會帶上 __meta_* 系列 Label。如果需要保留為實際 Label,必須透過 relabel_configs 改名:

scrape_configs:
  - job_name: container_scrape
    docker_sd_configs: ...
    relabel_configs:
      - source_labels: ["__meta_docker_container_name"]
        regex: "/(.*)"
        target_label: "container"

Pipeline#

Promtail 在送出 Log 之前,可以串接一連串 Stages 進行加工,整體稱為 Pipeline。Stages 大致分為四種,可以自由組合:

  • Parsing:解析 Log 內容,例如 json 把 JSON 結構拆出來,作為後續階段使用的中介資料。
  • Transform:對解析後的資料做轉換,例如 decolorize 移除 ANSI 顏色碼。
  • Action:實際修改 Log 或 Label,例如 labels 把 Parsing 出來的欄位升格為 Label。
  • Filtering:根據條件保留或丟棄 Log,例如 match

設計 Pipeline 時可以借鏡 LogQL 的觀念:先讓 Parsing 與 Filtering 把資料量壓下來,Action 再用較少的事件去動 Label。這樣可以避免高基數欄位被誤升格成 Label,拖累下游 Loki。

範例設定#

以下是一份從 Docker Service Discovery 抓取 Log,並送往 Loki 的 Promtail 設定:

# ./etc/promtail.yaml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: container_scrape
    docker_sd_configs:
      - host: unix:///var/run/docker.sock
        refresh_interval: 5s
        filters:
          - name: label
            values: ["logging=promtail"]
    relabel_configs:
      - source_labels: ["__meta_docker_container_name"]
        regex: "/(.*)"
        target_label: "container"
      - source_labels: ["__meta_docker_container_log_stream"]
        target_label: "logstream"

幾個關鍵點:

  • clients.url 指向 Loki 的 push API 端點。
  • docker_sd_configs.filters 限制只收 Label logging=promtail 的 Container,避免把不相干的 Log 一起送進 Loki。
  • relabel_configs__meta_docker_container_name 改寫成乾淨的 container Label,方便在 LogQL 中使用。

小結#

Promtail 概念精簡、設定模式延續 Prometheus,對於已經選定 Loki 的團隊而言,是過去最直接的搭檔。雖然官方已宣布合併進 Grafana Alloy,但理解 Promtail 的設計思路(Service Discovery、Pipeline、Label 策略)依然會直接轉化為對 Alloy 的理解,因此它仍是學習 Loki 生態時值得認識的一站。

原文出處#

  • 原書/iThome:https://ithelp.ithome.com.tw/articles/10331661