iT邦幫忙

2023 iThome 鐵人賽

DAY 15
1
資訊處理流程 生成 收集 儲存 使用
Promtail

Promtail 是 Grafana Labs 專為 Loki 打造的 Log Agent,主要任務是收集、處理 Log 並將之送至 Loki。Promtail 是由 Prometheus 加上 tail 組成,它使用跟 Prometheus 相似的設定檔與 Label 概念:透過設定檔來定義要收集的 Log 來源,利用 tail 的方式持續監控 Log 檔案的內容,並將收集到的資料加上 Label 後送至 Loki。

Pipeline

Concepts

Tail

對於不熟悉 Linux 的人可能不知道什麼是 tailtail 是 Linux 系統中常用的一個指令,它可以用來查看檔案最後的內容,預設是顯示最後 10 行內容,可以透過 -n 參數來指定要顯示的行數,例如:

tail -n 20 /var/log/messages # 顯示 /var/log/messages 檔案最後 20 行的內容

如果想要持續與即時查看檔案的新內容,可以透過 -f(follow 跟蹤)參數來達成。當檔案有新的內容加入在最後面時,會自動顯示在畫面上,例如:

tail -f /var/log/messages

此外,tail 還有一個巧妙的用法:它可以作為一個佔用資源極少,卻能永遠運行而不會失敗的程式。這樣的程式被設定為 Container 的 CMD 時,可以讓 Container 永遠存活,避免 Container 因為 CMD 完成或是失敗而停止,使用範例如下:

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

tail -f 會跟蹤並印出指定檔案的最末端,而 /dev/null 為 Linux 中一個特殊的檔案,檔案內容永遠只有 EOF(文件的結束符號,即沒有任何內容)。因此,tail -f /dev/null 的效果就是持續跟蹤一個永遠是空的檔案。這樣我們便可以隨時進入這個 Container 執行任何指令,這在 Debug Container Image 時非常有用,也可以透過這樣的方式把 Container 當成一個虛擬環境來使用,不必擔心 Container 會被停止。

Service Discovery

Promtail 透過 Service Discovery 決定要收集哪些 Log。其設定方式與 Prometheus 類似,使用 scrape_configs 來定義要收集的 Log 來源,可設定多個不同 Job,再針對各自的 Job 設定對應的參數,例如:

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

  - job_name: kubernetes
    kubernetes_sd_config:
      - ...

在 Prometheus 主要都使用 static_configs 定義要收集的目標的 URL,但在 Promtail 中 static_configs 只能用於收集該台機器上的 Log File,例如:

scrape_configs:
  - job_name: local
    static_configs:
      labels:
        __path__: /var/log/*.log # /var/log/*.log 的 Log 都會被收集,以 __ 開頭的 Label 在送至 Loki 時會被移除,並不會被 Loki 使用

除了 static_configs 之外,還有其他的 config 可以使用,例如:

  1. docker_sd_config:專為收集 Docker Container 的 Log 設計,並將 Docker 的相關資訊轉換成 Label,本篇 Lab 就是使用 docker_sd_config 作為範例。
  2. kubernetes_sd_config:透過 Kubernetes API 收集 Container 的 Log,並將 Kubernetes 的相關資訊轉換成 Label。
  3. kafka:從 Kafka Topic 中收集 Log。

各種 config 除了收集 Log 之外,也會將與 Log 有關的 Label 一併加上。例如使用 docker_sd_config 會加上 __meta_docker_container_name 的 Label,但由於這些 Label 都是以 __ 開頭,在送至 Loki 時會被移除。如果要保留這些 Label,可以使用 relabel_configs 設定,例如:

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

透過這組設定,就可以將 __meta_docker_container_name 轉為新的名為 container 的 Label,並且使用正規表達式取出 Container Name。

Pipeline

Promtail 在將 Log 送至 Loki 之前,可以選擇是否要進行額外的處理,這一連串的處理稱作 Pipeline。而這些處理步驟稱作 Stages,有四種主要類型的 Stages,每種都可以有多個,並且可以自由搭配:

  1. Parsing stages:解析 Log 內容,解析出的資料供其他 Stages 使用,例如:json 可以將 Log 中的 JSON 資料依據 Key 解析出來成為額外的資料。
  2. Transform stages:將額外的資料進行轉換,例如:decolorize 可以移除 Log 中的 ANSI Color Code。
  3. Action stages:修改 Log 或 Label 的內容,例如:labels 可以將 Parsing stages 解析出來的資料變成 Label。
  4. Filtering stages:根據條件排除或保留 Log,例如:match

Lab

範例程式碼:15-promtail

Quick Start

  1. 啟動所有服務

    docker-compose up -d
    
  2. 檢視服務

    1. Nginx: http://localhost:8080
      1. 瀏覽 Nginx 時會生成 Access Log
    2. Grafana: http://localhost:3000,登入帳號密碼為 admin/admin
      1. 點擊左上 Menu > Explore,左上 Data Source 選擇 Loki,在 Label Filter 中 Label 選擇 container,Value 選擇 nginx,即可看到 nginx Container 的 Log

      2. 若要生成更多 Log 也可以使用 k6 發送更多 Request

        k6 run --vus 1 --duration 300s k6-script.js
        
  3. 關閉所有服務

    docker-compose down
    

Goals

  1. 建立 Promtail,並 Mount Docker Socket 至 Promtail Container,讓 Promtail 可以讀取 Label 為 logging=promtail 的 Container 的 Log
  2. 建立 Loki,負責收取 Promtail 傳送的 Log
  3. 建立 Grafana,讀取 Loki 的資料

Promtail Configuration

# ./etc/promtail.yaml
server:
  http_listen_port: 9080 # promtail port,預設為 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml 

clients:
  - url: http://loki:3100/loki/api/v1/push # Loki 的 URL

scrape_configs:
  - job_name: container_scrape # Job Name
    docker_sd_configs: # 使用 Docker Service Discovery
      - host: unix:///var/run/docker.sock # Docker Socket 的位置
        refresh_interval: 5s # 每 5 秒重新掃描一次 Docker Socket
        filters: # 只收集 Label 為 logging=promtail 的 Container
          - name: label
            values: ["logging=promtail"]
    relabel_configs: # 將 Docker 相關的資訊轉換成 Label
      - source_labels: ['__meta_docker_container_name'] # 將 __meta_docker_container_name 轉為新的名為 container 的 Label
        regex: '/(.*)' # 使用正規表達式取出 Container Name
        target_label: 'container'
      - source_labels: ['__meta_docker_container_log_stream'] # 將 __meta_docker_container_log_stream 轉為新的名為 logstream 的 Label
        target_label: 'logstream'

小結

Promtail 作為 Loki 專屬的 Log Agent,其概念與設定相對簡單,也高度與 Loki 相關。如果 Log Aggregation System 決定要使用 Loki,Promtail 或許是你收集 Log 時的首選。

參考資料

  1. Promtail agent

上一篇
Loki — 解開日誌空間與時間束縛的法杖
下一篇
Fluent Bit — 資料收集界的萬能瑞士刀
系列文
時光之鏡:透視過去、現在與未來的 Observability30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Blueswen
iT邦新手 2 級 ‧ 2023-09-30 22:20:57

賽程終於過了一半了,但已經沒有任何庫存稿了 Orz

我要留言

立即登入留言