日誌聚合分析系統——Loki
什麼是Loki?
Loki 是 Grafana Labs 團隊最新的開源專案,是一個水平可擴充套件,高可用性,多租戶的日誌聚合系統。它的設計非常經濟高效且易於操作,因為它不會為日誌內容編制索引,而是為每個日誌流編制一組標籤,專門為 Prometheus 和 Kubernetes 使用者做了相關優化。
與傳統日誌收集系統(例ELK)相比,Loki的優勢有哪些?
- 不對日誌進行全文索引。通過儲存壓縮非結構化日誌和僅索引後設資料,Loki操作起來會更簡單,更省成本
- 通過與 Prometheus 相同的標籤記錄流對日誌進行索引和分組,這使得日誌的擴充套件和操作效率更高
- 特別適合儲存 Kubernetes Pod 日誌;諸如 Pod 標籤之類的後設資料會被自動刪除和編入索引
- 受 Grafana 原生支援,與 Prometheus 配合更加方便
解決痛點?
無需再去其他介面,或者終端上檢視單個Pod的日誌
整體架構
Loki的架構並不難,主要是以下三部分組成:
- Loki 為主伺服器。負責儲存日誌和處理查詢
- Promtail 是代理。負責收集日誌並將其傳送給Loki
- Grafana 用來UI展示。
Loki 使用與 Prometheus 相同的服務發現和標籤重新標記庫,編寫了 Promtail。在 Kubernetes 中 Promtail 以 DaemonSet 方式執行在每個節點中,通過 Kubernetes API 得到日誌的正確後設資料,並將它們傳送到Loki,如下圖:
可以看到,Loki中主要的元件有Distributor、Ingester和Querier三個。
負責寫入的元件有Distributor和Ingester兩個:
Distributor
Promtaif 一旦將日誌傳送給Loki,Distributor 就是第一個接收日誌的元件。由於日誌的寫入量可能很大,所以不能在它們傳入時並行寫入資料庫,要先進行批處理和壓縮資料。
- Distributor 接收到 HTTP 請求,用於儲存流資料
- 通過 hash 環對資料流進行 hash
- 通過hash演算法計算出應該傳送到哪個Ingester後,傳送資料流
- Ingester新建Chunks或將資料追加到已有的Chunk上
Ingester
Ingester 接收到日誌並開始構建 Chunk:
Ingester 是一個有狀態元件,負責構建和重新整理Chunk,當Chunk達到一定數量或者時間後,重新整理到儲存中去,每一個流日誌對應一個Ingester。index和Chunk各自使用單獨的資料庫,因為他們儲存額資料型別不同。
負責讀的元件則是Querier:
讀取就比較簡單,由 Querier 負責給定一個時間範圍和標籤選擇器,也就是收到讀請求:
- Querier 收到HTTP讀請求
- Querier 將請求傳送至Ingester讀取還未寫入Chunks的記憶體資料
- 隨後再去index+chunks中查詢資料
- Querier 遍歷所有資料並進行去重處理,再返回最終結果
搭建使用
上邊主要介紹的Loki的工作流程及元件,下面我們實際搭建操作下:
Loki專案地址:https://github.com/grafana/loki/
一、通過Helm部署:
## 新增chart helm repo add loki https://grafana.github.io/loki/charts ## 更新chart helm repo update ## 將loki template下載到本地 helm fetch loki/loki-stack ## 解壓並自定義修改引數 tar zxvf loki-stack-2.0.2.tgz cd loki-stack/ $$ ls charts Chart.yaml README.md requirements.lock requirements.yaml templates values.yaml cd charts/ $$ ls filebeat fluent-bit grafana logstash loki prometheus promtail
開始helm安裝前要注意幾個點:
1、可以修改values.yaml檔案,指定是否開啟Grafana、Prometheus等服務,預設不開啟的:
loki:
enabled: true
promtail:
enabled: true
fluent-bit:
enabled: false
grafana:
enabled: true
sidecar:
datasources:
enabled: true
image:
tag: 6.7.0
prometheus:
enabled: false
在此只開啟Grafana
修改Grafana的values.yaml,使其Service暴露方式為NodePort(預設為ClusterIp):
vim charts/grafana/values.yaml
service:
type: NodePort
port: 80
nodePort: 30002 # 埠範圍:30000-32767
targetPort: 3000
# targetPort: 4181 To be used with a proxy extraContainer
annotations: {}
labels: {}
portName: service
還有一處賬號密碼可以自定義修改下:
# Administrator credentials when not using an existing secret (see below)
adminUser: admin
adminPassword: admin
2、promtail服務在構建時會自動掛載:
- 宿主機docker主目錄下的containers目錄,一般預設都為/var/lib/docker/containers
- pod的日誌目錄,一般預設為/var/log/pods
這就需要特別注意一下,如果是修改過docker預設的儲存路徑的,需要將mount的路徑進行修改,promtail找不到對應的容器日誌
具體docker 儲存路徑,可以使用docker info 命令查詢
vim charts/promtail/values.yaml
volumes:
- name: docker
hostPath:
path: /data/lib/docker/containers ## 我的是放在了data下
- name: pods
hostPath:
path: /var/log/pods
volumeMounts:
- name: docker
mountPath: /data/lib/docker/containers ## 掛載點也要進行修改
readOnly: true
- name: pods
mountPath: /var/log/pods
readOnly: true
開始安裝:
helm install -n loki --namespace loki -f values.yaml ../loki-stack
2020/11/11 17:18:54 Warning: Merging destination map for chart 'logstash'. The destination item 'filters' is a table and ignoring the source 'filters' as it has a non-table value of: <nil>
NAME: loki
LAST DEPLOYED: Wed Nov 11 17:18:53 2020
NAMESPACE: loki
STATUS: DEPLOYED
RESOURCES:
==> v1/ClusterRole
NAME AGE
loki-promtail-clusterrole 1s
loki-grafana-clusterrole 1s
==> v1/ClusterRoleBinding
NAME AGE
loki-promtail-clusterrolebinding 1s
loki-grafana-clusterrolebinding 1s
==> v1/ConfigMap
NAME DATA AGE
loki-grafana 1 1s
loki-grafana-test 1 1s
loki-loki-stack 1 1s
loki-loki-stack-test 1 1s
loki-promtail 1 1s
==> v1/DaemonSet
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
loki-promtail 2 2 0 2 0 <none> 1s
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
loki-grafana 0/1 1 0 1s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
loki-0 0/1 ContainerCreating 0 2s
loki-grafana-56bf5d8d-8zcgp 0/1 Init:0/1 0 2s
loki-promtail-6r24r 0/1 ContainerCreating 0 2s
loki-promtail-fvnfc 0/1 ContainerCreating 0 2s
==> v1/Role
NAME AGE
loki-promtail 1s
loki-grafana-test 1s
loki 1s
==> v1/RoleBinding
NAME AGE
loki-promtail 1s
loki-grafana-test 1s
loki 1s
==> v1/Secret
NAME TYPE DATA AGE
loki Opaque 1 1s
loki-grafana Opaque 3 1s
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki ClusterIP 10.109.216.219 <none> 3100/TCP 1s
loki-grafana NodePort 10.100.203.138 <none> 80:30002/TCP 1s
loki-headless ClusterIP None <none> 3100/TCP 1s
==> v1/ServiceAccount
NAME SECRETS AGE
loki 1 1s
loki-grafana 1 1s
loki-grafana-test 1 1s
loki-promtail 1 1s
==> v1/StatefulSet
NAME READY AGE
loki 0/1 1s
==> v1beta1/PodSecurityPolicy
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
loki false RunAsAny MustRunAsNonRoot MustRunAs MustRunAs true configMap,emptyDir,persistentVolumeClaim,secret,projected,downwardAPI
loki-grafana false RunAsAny RunAsAny RunAsAny RunAsAny false configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim
loki-grafana-test false RunAsAny RunAsAny RunAsAny RunAsAny false configMap,downwardAPI,emptyDir,projected,secret
loki-promtail false RunAsAny RunAsAny RunAsAny RunAsAny true secret,configMap,hostPath,projected,downwardAPI,emptyDir
==> v1beta1/Role
NAME AGE
loki-grafana 1s
==> v1beta1/RoleBinding
NAME AGE
loki-grafana 1s
建立完成後,通過暴露的svc訪問Grafana:
[root@Centos8 loki-stack]# kubectl get svc -n loki
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
loki ClusterIP 10.109.216.219 <none> 3100/TCP 113s
loki-grafana NodePort 10.100.203.138 <none> 80:30002/TCP 113s
loki-headless ClusterIP None <none> 3100/TCP 113s
二、開始使用Loki
通過伺服器ip+30002訪問,登入成功後,有一點需要注意的地方,也是非常容易踩坑的地方!!!
如果是安裝Loki時採用的以上方法,開啟了Grafana,那系統會自動配置好Data sources,應該不會有什麼問題。
但是,如果是手動搭建的Grafana,需要手動新增Data Sources時,一定注意:
資料來源名稱中的Loki,L一定要是大寫!!!
如果不是大寫,會導致連線不到Loki源,一般回報錯:Error connecting to datasource: Loki: Bad Gateway. 502
如果是Loki,L大寫,結局完全不一樣
資料來源新增完畢後,開始檢視日誌
點選Explore,可以看到選擇labels的地方
以下是labels的展現形式
選擇一個app:grafana的標籤檢視一下
預設Loki會將stdout(正常輸出)型別和stderr(錯誤輸出)型別全部展示出來
如果只想檢視stderr錯誤輸出型別的日誌,可以點選stderr旁邊的放大鏡來展示:
此時顯示的全部為錯誤日誌
除了這種辦法,還可以直接通過上邊的搜尋欄,進行自定義的篩選,具體的語法問題,可以再自行查詢學習。
還可以檢視 Prometheus 的 metrics 資訊:
Loki的搭建及簡單的使用就到此結束了