日誌系統 Loki - Promtail 詳解
主流的日誌收集架構一般採用 ELK/EFK/EFLK ,但是這些都比較適合在重量級、需要日誌數據清理的場景下使用。
雲原生環境下, Grafana + Loki + Promtail 橫空出世。
“Like Prometheus, but for logs.”
整體介紹
Loki 是受 Prometheus 啓發的水平可擴展、高可用、多租戶日誌聚合系統。非常適合採集 Kubernetes Pod 的日誌,關鍵 Loki 還易於操作且更加輕量級(相比 ELK/EFK/EFLK )。
在 Loki 架構中有以下幾個概念:
-
Grafana:相當於 EFK 中的 Kibana ,用於 UI 的展示。
-
Loki:相當於 EFK 中的 ElasticSearch ,用於存儲日誌和處理查詢。
-
Promtail:相當於 EFK 中的 Filebeat/Fluentd ,用於採集日誌並將其發送給 Loki 。
-
LogQL:Loki 提供的日誌查詢語言,類似 Prometheus 的 PromQL,而且 Loki 支持 LogQL 查詢直接轉換爲 Prometheus 指標。
Loki 整體架構
Promtail 介紹
Promtail 將本地日誌內容傳送到 Loki 實例。需要監控的應用程序的機器上都需要部署該組件。
它的主要工作流程可以劃分爲:
-
使用 fsnotify 監聽指定目錄下(例如:/var/log/*.log)的文件創建與刪除
-
對每個活躍的日誌文件起一個 goroutine 進行類似 tail -f 的讀取,讀取到的內容發送給 channel
-
有一個單獨的 goroutine 會讀取 channel 中的日誌行,分批並附加上標籤後推送給 Loki
promtail 原理
Loki 介紹
Loki 是用來接受、存儲、處理、查詢日誌的集合體。
Loki 採用讀寫分離架構,關鍵組件有:
-
Distributor 分發器:日誌數據傳輸的 “第一站”,Distributor 分發器接收到日誌數據後,根據元數據和 hash 算法,將日誌分批並行地發送到多個 Ingester 接收器上
-
Ingester 接收器:接收器是一個有狀態的組件,在日誌進入時對其進行 gzip 壓縮操作,並負責構建和刷新 chunck 塊,當 chunk 塊達到一定的數量或者時間後,就會刷新 chunk 塊和對應的 Index 索引存儲到數據庫中
-
Querier 查詢器:給定一個時間範圍和標籤選擇器,Querier 查詢器可以從數據庫中查看 Index 索引以確定哪些 chunck 塊匹配,並通過 greps 將結果顯示出來,它還會直接從 Ingester 接收器獲取尚未刷新的最新數據
-
Query frontend 查詢前端:查詢前端是一個可選的組件,運行在 Querier 查詢器之前,起到緩存,均衡調度的功能,用於加速日誌查詢
loki 組件通信
Loki 提供了兩種部署方式:
-
單體模式,ALL IN ONE:Loki 支持單一進程模式,可在一個進程中運行所有必需的組件。單進程模式非常適合測試 Loki 或以小規模運行。不過儘管每個組件都以相同的進程運行,但它們仍將通過本地網絡相互連接進行組件之間的通信(grpc)。使用 Helm 部署就是採用的該模式。
-
微服務模式:爲了實現水平可伸縮性,Loki 支持組件拆分爲單獨的組件分開部署,從而使它們彼此獨立地擴展。每個組件都產生一個用於內部請求的 gRPC 服務器和一個用於外部 API 請求的 HTTP 服務,所有組件都帶有 HTTP 服務器,但是大多數只暴露就緒接口、運行狀況和指標端點。
Loki 組件架構
使用 Helm 部署
以 Helm 部署 Loki (StatefulSet 方式) 和 Promtail(DaemonSet 方式)採集 k8s pod 應用的日誌爲例
# 添加 grafana 源
helm repo add grafana https://grafana.github.io/helm-charts
# 創建命名空間
kubectl create ns grafana
kubectl create ns loki
# 部署 grafana,並開啓 NodePort 訪問
# 用戶名 admin
# 密碼 kubectl get secret --namespace grafana grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
helm install grafana grafana/grafana --set "service.type=NodePort" -n grafana
# 部署 loki
helm install loki grafana/loki -f loki-config.yaml -n loki
# 部署 promtail
helm install promtail grafana/promtail -f promtail-config.yaml -n loki
loki-config.yaml
配置:
# loki 配置
config:
limits_config:
# Distributor 分發器的日誌接收速率限制
ingestion_rate_mb: 8
# 實例數
replicas: 1
# 限制使用資源
resources:
limits:
cpu: 2000m
memory: 2048Mi
# 掛載宿主機時間
extraVolumeMounts:
- name: host-time
mountPath: /etc/localtime
extraVolumes:
- name: host-time
hostPath:
path: /etc/localtime
promtail-config.yaml
配置:
extraArgs:
# 添加全局靜態標籤 cluster:dev
- -client.external-labels=cluster=dev
# 限制使用資源
resources:
limits:
cpu: 512m
memory: 512Mi
# 掛載宿主機時間
extraVolumeMounts:
- name: host-time
mountPath: /etc/localtime
extraVolumes:
- name: host-time
hostPath:
path: /etc/localtime
# promtail 配置
config:
lokiAddress: http://loki-ip:3100/loki/api/v1/push
snippets:
# 清除默認配置
scrapeConfigs: ""
# 自定義配置
extraScrapeConfigs: |
# 通過 kubernetes_sd_configs:pod 配置 pod 日誌,參考 https://grafana.com/docs/loki/latest/clients/promtail/configuration/#kubernetes_sd_config
- job_name: kubernetes-pods-app
# 流水線
pipeline_stages:
{{- toYaml .Values.config.snippets.podPipelineStages | nindent 4 }}
kubernetes_sd_configs:
- role: pod
relabel_configs:
# 把 pod 所有的標籤暴露出來
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
replacement: $1
target_label: $1
- action: drop
regex: .+
source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_name
- action: replace
source_labels:
- __meta_kubernetes_pod_ip
target_label: pod_ip
- action: replace
source_labels:
- __meta_kubernetes_pod_label_app
target_label: app
- action: drop
regex: ''
source_labels:
- app
- action: replace
source_labels:
- __meta_kubernetes_pod_label_component
target_label: component
{{- if .Values.config.snippets.addScrapeJobLabel }}
- action: replace
replacement: kubernetes-pods-app
target_label: scrape_job
{{- end }}
{{- toYaml .Values.config.snippets.common | nindent 4 }}
podPipelineStages:
- docker: {}
Grafana 添加 Loki 數據源:
Grafana 中按照標籤查詢日誌:
nginx 日誌示例:
日誌告警
=======
Loki 支持三種模式創建日誌告警:
-
在 Promtail 中的 pipeline 管道的 metrics 的階段,根據需求增加一個監控指標,然後使用 Prometheus 結合 Alertmanager 完成監控報警。
-
通過 Loki 自帶的報警功能( Ruler 組件)可以持續查詢一個 rules 規則,並將超過閾值的事件推送給 AlertManager 或者其他 Webhook 服務。
-
將 LogQL 查詢轉換爲 Prometheus 指標。可以通過 Grafana 自帶的 Alert rules & notifications,定義有關 LogQL 指標的報警,推送到 Notification channels( Prometheus Alertmanager , Webhook 等)。
以下主要介紹 LogQL 轉化爲 Prometheus 指標的方式實現告警。
首先,在 Grafana 添加 Prometheus 數據源,URL 只需要填入 http://loki-ip:3100/loki 即可將 LogQL 查詢轉換爲 Prometheus 指標。
在告警規則配置中配置 Notification channels
新建一個 Dashboard ,配置一個面板,例如:當 nginx 出現 404 狀態碼,觸發告警:
count_over_time({app="nginx-pod"} |= "404" [1m])
手動訪問 nginx 404 頁面,可以看到日誌已經產生告警:
關於更多 Loki 和 Promtail 配置,以及日誌的告警,推薦直接看官方文檔,已經很詳細了。這裏不過多介紹。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/qwv_4Q-QvxXBo7Qkt-Mqvw