背景
为什么需要日志管理系统?
- 分布式系统的日志查看比较复杂,因为多对节点的系统,要先找到正确的节点,才能看到想看的日志。日志系统把整个集群的日志汇总在一起,方便查看
- 因为节点上的日志滚动机制,如果有应用打印太多日志,如果没有日志系统,会导致关键日志丢失。
- 日志系统的重要意义在于解决:节点出错导致不可访问,进而丢失日志的情况。
常用数据系统构建模式
- 数据采集
- push:节点上的进程需要采集日志并推送到日志系统
- pull:业务日志输出到标准输出,标准输出到日志就到了console log,容器又会把console log转储到本地的日志文件中,docker和contained都有日志驱动器,负责把日志落盘。采集器去节点上扫描日志目录,拉取到日志系统。
pull用的比较多。
- 数据采集到日志系统后,需要进行预处理。
- 去重
- 塑形:通过标准格式来格式化日志
- 预处理过后,日志数据需要保存。
- TSDB:时序数据库,比如Influxdb,opentsdb等。
- Hadoop:存储到HDFS中,用来做日志分析。
- 日志消费:
- 按需查询:时间点,ip地址等。
- 告警:超出阈值进行告警。
- 分析:奇异点分析,统计分析,预测分析。
介绍
Grafana Loki 是可以组成功能齐全的日志记录堆栈的一组组件。
- Loki 是一个为有效保存日志数据而优化的数据存储。日志数据的高效索引将 Loki 与其他日志系统区分开来。与其他日志系统不同,Loki 索引是根据标签构建的,原始日志消息未编入索引。
- 日志数据本身被压缩并存储在对象存储(例如 S3 或 GCS)中的块中,甚至存储在文件系统本地。
- 小索引和高度压缩的块简化了操作,并大大降低了 Loki 的成本。
Loki和ELK/EFK的对比
基于Loki的日志管理系统
Loki-stack子系统
- Promtail
将容器日志发送到 Loki 或者 Grafana 服务上的日志收集工具。
发现采集目标以及给日志流添加上 Label,然后发送给 Loki。
Promtail 的服务发现是基于 Prometheus 的服务发现机制实现的,可以查看configmap loki-promtail了解细节。 - Loki
Loki 是可以水平扩展、高可用以及支持多租户的日志聚合系统。
使用和 Prometheus 相同的服务发现机制,将标签添加到日志流中而不是构建全文索引。
Promtail 接收到的日志和应用的 metrics 指标具有相同的标签。 - Grafana
Grafana 是一个用于监控和可视化观测的开源平台,支持非常丰富的数据源。
在 Loki 技术栈中它专门用来展示来自 Prometheus 和 Loki 等数据源的时间序列数据。
允许进行查询、可视化、报警等操作,可以用于创建、探索和共享数据 Dashboard。
架构
采集日志架构
组件
- Promtail:客户端负责采集并上报日志;
- Distributor:分配器,将数据转发到Ingester;
- 负责处理客户端写入的日志gzip。
- 一旦分配器接收到日志数据,它就会把它们分成若干批次,并将它们并行地发送到多个采集器去。
- 分配器通过gRPC 和采集器进行通信。
- 它们是无状态的,基于一致性哈希判断日志到哪个采集器,可以根据实际需要对他们进行扩缩容。
- Ingester:采集器,保存日志和写入存储;
- 接收到日志并开始构建chunk,将日志进行压缩并附加到chunk上面,一旦chunk满了,采集器负责将日志数据写入存储(DynamoDB、S3、Cassandra 等等)。
- 采集器会校验采集的日志是否乱序。
- 采集器验证接收到的日志行是按照时间戳递增的顺序接收的,否则日志行将被拒绝并返回错误。
- 接收到日志并开始构建chunk,将日志进行压缩并附加到chunk上面,一旦chunk满了,采集器负责将日志数据写入存储(DynamoDB、S3、Cassandra 等等)。
- Querier:查询器,执行搜索请求。
- 查询器服务负责处理 LogQL 查询语句来查询存储中的日志数据。
- 查询器服务负责处理 LogQL 查询语句来查询存储中的日志数据。
查询LogQL语法
选择器
对于查询表达式的标签部分,将放在{}中,多个标签表达式用逗号分隔:
{app="nginx",name="nginx"}
支持的符号有:
- =:完全相同。
- !=:不平等。
- =~:正则表达式匹配。
- !~:不要正则表达式匹配。
过滤表达式
编写日志流选择器后,您可以通过编写搜索表达式进一步过滤结果。搜索表达式可以文本或正则表达式。
比如:
{job=“mysql”} |= “error”
支持多个过滤:
{job=“mysql”} |= “error” !=“timeout”
目前支持的操作符:
- != line包含字符串。
- != line不包含字符串。
- !~ line匹配正则表达式。
- !~ line与正则表达式不匹配。
部署
- 添加chart
helm repo add grafana https://grafana.github.io/helm-charts helm search repo loki
- 下载chart
helm pull grafana/loki-stack tar -xvf loki-stack-*.tgz cd loki-stack
- 修改value.yaml
loki: enabled: true isDefault: true promtail: enabled: true grafana: enabled: true prometheus: enabled: true isDefault: true
- 修改chart目录中的各组件value.yaml
persistence: type: pvc enabled: true storageClassName: nfs-client ingress: enabled: true ingressClassName: nginx hosts: - grafana.xxx
- 安装
k create ns loki helm install loki . -n loki
- 修改loki-kube-state-metrics的镜像,或者下载后修改tag
ctr -n k8s.io i pull lank8s.cn/kube-state-metrics/kube-state-metrics:v2.3.0 ctr -n k8s.io i tag lank8s.cn/kube-state-metrics/kube-state-metrics:v2.3.0 k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.3.0 k delete po loki-kube-state-metrics-5c6b9ddd4f-dh679 -n loki
- 修改loki-grafana的deployment
readinessProbe: timeoutSeconds: 5
- 查看pod,svc,ingress
k get po,svc,ingress -n loki
- 访问grafana
获取grafana用户名密码k get secret loki-grafana -oyaml -n loki echo 'xxx' | base64 -d
- 修改密码
- 访问prometheus,查看target
登录ecs控制台,修改安全组,放开9100端口
- 添加loki数据源
URL为loki pod的地址,端口为loki svc的端口。
- 添加prometheus数据源
- 查看日志
点击Log browser,app,选择应用,show logs。
日志系统可能遇到的问题
- 利用率低:
日志大多数目的是给管理员做问题分析用的,但管理员更多的是登陆到节点或者Pod 里做分析,因为日志分析只是整个分析过程中的一部分,所以很多时候顺手就把日志看了。 - filebeats 出现过锁住文件系统,docker container 无法删除的情况。
- 与监控系统相比,日志系统的重要度稍低。
- 出现过多次因为日志滚动太快而使得日志收集占用太大网络带宽的情况。