“主流的日志收集架构一般采用 ELK/EFK/EFLK ,但是这些都比较适合在重量级、需要日志数据清理的场景下使用。 云原生环境下, Grafana + Loki + Promtail 横空出世。 “Like Prometheus, but for logs.” ”
Loki 是受 Prometheus 启发的水平可扩展、高可用、多租户日志聚合系统。非常适合采集 Kubernetes Pod 的日志,关键 Loki 还易于操作且更加轻量级(相比 ELK/EFK/EFLK )。
在 Loki 架构中有以下几个概念:
Loki整体架构
Promtail 将本地日志内容传送到 Loki 实例。需要监控的应用程序的机器上都需要部署该组件。
它的主要工作流程可以划分为:
promtail原理
Loki 是用来接受、存储、处理、查询日志的集合体。
Loki 采用读写分离架构,关键组件有:
loki组件通信
Loki 提供了两种部署方式:
Loki组件架构
以 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 支持三种模式创建日志告警:
以下主要介绍 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 配置,以及日志的告警,推荐直接看官方文档,已经很详细了。这里不过多介绍。