前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >简易日志系统LPG生产环境实践指南 | 坑我已经帮你们踩好了

简易日志系统LPG生产环境实践指南 | 坑我已经帮你们踩好了

作者头像
Lu说
发布2022-06-07 20:22:09
1.7K0
发布2022-06-07 20:22:09
举报

简易日志系统LPG生产环境实践指南 | 坑我已经帮你们踩好了

前言

最近在构建日志系统,对比了ELK还有LPG,发现LPG更加适合我们系统。奈何网上可靠的文章真是太少了,大多都是抄来抄去,整个过程躺过无数坑,特记录一下,回馈给读者。文章的所有配置文件都可以直接使用,并且配置做了优化,不会出现莫名其妙的问题。

简介

LPG即:Loki,Promtail,Grafana。Loki日志收集器,Promtail日志收集器,Gafana日志的可视化展示和查询。重点组件是Loki,Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流配置一组标签。项目受 Prometheus 启发,官方的介绍就是:Like Prometheus, but for logs,类似于 Prometheus 的日志系统。

我们为什么需要日志系统?

可能很多人都会有这个疑问。查看日志直接上主机grep不就行了么。实则不然,但我们生产环境主机众多,服务众多,那ssh到各主机上看日志将会是个极其麻烦的一件事,然后你还要使用grep 层层过滤,有时候这台主机看了发现没有问题,又要去另外一台主机上看,况且你还不一定有权限。

所有日志系统可以大大简化这个过程,日志系统提供的日志聚合,可视化展示和查询,高效的查询和过滤语句等可以极大提升运维效率,所有日志只需一个查询入口即可。有了日志系统,运维排查问题的步骤变成了这样:

所以我们常说日志系统和监控系统一样,都是属于公司的基建。

因为我们目前系统规模不算大,不需要对日志进行太复杂的操作,加上ELK成本较高,所以我们采用了LPG来搭建日志系统。

LPG架构

了解构架和软件运行原理对运维排查问题至关重要。

我们将构建一个使用Promtail采集收集使用Loki存储日志,使用Grafana可视化查询日志的日志系统。Loki和prometheus类似,都可以通过labels来区分和检索日志,我们可以在Promtail收集时定义好日志标签。

Loki 内部架构

Distributor

distributor 服务负责处理客户端写入的日志,它本质上是日志数据写入路径中的第一站,一旦 distributor 收到日志数据,会将其拆分为多个批次,然后并行发送给多个 ingesterdistributor 通过 gRPC 与 ingester 通信,它们都是无状态的,可以根据需要扩大或缩小规模。

Igester

ingester 服务负责将日志数据写入长期存储后端(DynamoDB、S3、Cassandra 等)。此外 ingester 会验证摄取的日志行是按照时间戳递增的顺序接收的(即每条日志的时间戳都比前面的日志晚一些),当 ingester 收到不符合这个顺序的日志时,该日志行会被拒绝并返回一个错误。

query-frontend

查询前端是一个可选的服务,提供 querier 的 API 端点,可以用来加速读取路径。当查询前端就位时,应将传入的查询请求定向到查询前端,而不是 querier, 为了执行实际的查询,群集中仍需要 querier 服务

Querier

Querier 查询器服务使用 LogQL 查询语言处理查询,从 ingesters 和长期存储中获取日志。

查询器查询所有 ingesters 的内存数据,然后再到后端存储运行相同的查询。由于复制因子,查询器有可能会收到重复的数据。为了解决这个问题,查询器在内部对具有相同纳秒时间戳、标签集和日志信息的数据进行重复数据删除。

部署与配置

安装loki

代码语言:javascript
复制
wget https://github.com/grafana/loki/releases/download/v2.x.0/loki-linux-amd64.zip # 下载
unzip loki-linux-amd64.zip # 解压
mv loki-linux-amd64 /monitor/loki # 挪到 $PATH下

编写配置文件,vim loki-local-config.yml

代码语言:javascript
复制
auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096

ingester:
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 10m
  chunk_retain_period: 30s
schema_config:
  configs:
  - from: 2020-05-15
    store: boltdb
    object_store: filesystem
    schema: v11
    index:
      prefix: index_
      period: 168h
storage_config:
  boltdb:
    directory: /monitor/loki/index
  filesystem:
    directory: /monitor/loki/chunks  # 块存储路径

limits_config:
  enforce_metric_name: false
  reject_old_samples: true          # 是否拒绝老样本
  reject_old_samples_max_age: 168h  # 168小时之前的样本将会被删除
  ingestion_rate_mb: 200
  ingestion_burst_size_mb: 300
  per_stream_rate_limit: 1000MB
  max_entries_limit_per_query: 10000
chunk_store_config:
  max_look_back_period: 168h        # 为避免查询超过保留期的数据,必须小于或等于下方的时间值
table_manager:
  retention_deletes_enabled: true   # 保留删除开启
  retention_period: 168h            # 超过168h的块数据将被删除

ruler:
  storage:
    type: local
    local:
      directory: /monitor/loki/rules
  rule_path: /monitor/loki/rules-temp
  alertmanager_url: http://192.168.x.x:9093 # alertmanager地址
  ring:
    kvstore:
      store: inmemory
  enable_api: true
  enable_alertmanager_v2: true

更多配置项的解释看这里:https://grafana.com/docs/loki/latest/configuration/[1]

启动脚本

代码语言:javascript
复制
# cat restart-loki.sh 
#!/bin/bash
echo "stop loki"
ps -ef | grep loki-linux-amd64 | grep -v grep | awk '{print $2}'| xargs kill -9 

echo "Begin start loki"
sleep 1
str=$"\n"
nohup ./loki-linux-amd64 --config.file=loki-local-config.yml &
sstr=$(echo -e $str)
echo $sstr

在需要采集日志的主机上都安装Promtail

代码语言:javascript
复制
wget https://github.com/grafana/loki/releases/download/v2.x.0/promtail-linux-amd64.zip # 下载
unzip loki-linux-amd64.zip # 解压
mv promtail-linux-amd64 /usr/local/sbin/promtail # 挪到 $PATH下

编写配置文件,vim promtail-local-config.yml

代码语言:javascript
复制
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /opt/promtail/positions.yaml

clients:
  - url: http://192.168.xx.xx:3100/loki/api/v1/push # 填写好Loki地址

scrape_configs:
- job_name: messagelog
  static_configs:
  - targets:
      - localhost
    labels:
      #job: messagelog
      host: namenode01
      __path__: /var/log/messages

- job_name: agentlog
  static_configs:
  - targets:
      - localhost
    labels:
      #job: agentlog
      host: namenode01
      __path__: /ssd/ssd0/agentlog/agent.log
- job_name: datanodelog
  static_configs:
  - targets:
      - localhost
    labels:
#      #job: datanodelog
      host: namenode01
      __path__: /ssd/ssd0/datanodelog/*datanode*.log 

关于labels,官网建议labels个数越少越好,过多的labels将会影响Loki日志的检索速度。

启动脚本:

代码语言:javascript
复制
# cat restart-promtail.sh 
#!/bin/bash
echo "Begin stop promtail"
ps -ef | grep promtail-linux-amd64 | grep -v grep | awk '{print $2}' | xargs kill -9

echo "Begin start promtail...."
nohup ./promtail-linux-amd64 --config.file=promtail-local-config.yml > ./promtail-9080.log 2>&1 &

使用指南

除了使用Gafana查询Loki之外,它还提供了linux终端的查询客户端:logcli。实际上查询Loki的还有Alertmanager

Gafana对接Loki

我们可以使用Grafana对接Loki进行可视化的日志检索和分析,如果你更愿意使用命令行,那也可以使用logcli来查询日志,详见下一节《logcli的使用》。

首先我们需要添加Grafana Loki数据源

grafana上显示的日志行数与DataSource设置保持一致

loki datasource的设置查询显示行数:

但直方图上并不会显示所选时间内所有日志情况,只会显示5000行日志的情况,如果查询结果日志条数小于5000,直方图则会显示所有日志

这部分其实很简单,下面介绍一下Logql的语法:

其表达式主要分为两部分,日志标签匹配和条件过滤表示式。这里的标签可以在Grafana直接看到:

如果是命令行,可以使用logcli labels 查询。

日志流选择器(即第一部分:标签匹配)

  • =: 完全匹配
  • !=: 不匹配
  • =~: 正则表达式匹配
  • !~: 正则表达式不匹配

举例:

代码语言:javascript
复制
{name!~`hadoop-\d+`,env="prod"}

filter expression

  • |=:日志行包含的字符串
  • !=:日志行不包含的字符串
  • |~:日志行匹配正则表达式
  • !~:日志行与正则表达式不匹配

举例

代码语言:javascript
复制
{name="hadoop"} |~  `error=\w+`

Metric queries

区间向量

LogQL同样也支持有限的区间向量度量语句,使用方式也和PromQL类似,常用函数主要是如下4个:

  • rate: 计算每秒的日志条目
  • count_over_time: 对指定范围内的每个日志流的条目进行计数
  • bytes_rate: 计算日志流每秒的字节数
  • bytes_over_time: 对指定范围内的每个日志流的使用的字节

** 聚合函数**

  • sum:求和
  • min:最小值
  • max:最大值
  • avg:平均值
  • stddev:标准差
  • stdvar:标准方差
  • count:计数
  • bottomk:最小的k个元素
  • topk:最大的k个元素

对于需要对标签进行分组时,我们可以用without或者by来区分,比如:

代码语言:javascript
复制
#计算nginx的qps,并按照pod_name来分组
sum(rate({filename="/var/log/nginx/access.log"}[5m])) by (pod_name)

还有更多,可以阅读官网:https://grafana.com/docs/loki/latest/logql/[2] ,这里就不一一列举了。

一般日常工作上述语句差不多够用了。

logcli使用

安装logcli

https://github.com/grafana/loki/releases/tag/v2.4.2[3] 下载logcli-linux-amd64.zip文件,解压,重命名

代码语言:javascript
复制
mv logcli-linux-amd64 logcli

将解压的文件链接到/usr/local/bin/logcli

代码语言:javascript
复制
ln -s /your/path/to
查询有哪些labels
代码语言:javascript
复制
# logcli labels
__name__
filename
host

使用query功能,配合label查询对应的日志文件。日志显示顺序默认是时间倒序。

代码语言:javascript
复制
logcli query '{host="db04",filename="/ssd/ssd0/agentlog/P4-node2.log"}' --limit 1000

默认查询是返回30条日志,可以使用**--limit**** 参数来修改返回行数。不管行数设置的是多大,默认只打印一个小时的日志。可以使用****--since**** 参数来指定打印多长时间的日志。**

如果你将查询的--limit 参数(默认为30)设置为一个较大的数,比如 10000,那么 logcli 会自动将此请求分批发送到 Loki,默认的批次大小是 1000。

可使用-o jsonl 让日志输出为json格式。

指定时间输出日志
代码语言:javascript
复制
logcli query '{host="db04",filename="/var/log/messages"}' --limit=100000 --from="2022-03-17T14:00:05Z"  --to="2022-03-18T14:30:05Z"

以上时间是以UTC为时区的时间,如果需要中国时间,使用以下格式:

代码语言:javascript
复制
logcli query '{host="db04",filename="/var/log/messages"}' --limit=10000 --from="2022-03-12T14:00:05+08:00"  --to="2022-03-18T14:30:05+08:00"

--from--to 后面的时间需要符合IETF RFC-3339[4]格式。T 作为隔断日期和时间的标志,也可以使用空格来代替TZ 表示其时区为UTC + 0。更多详细的例子:

代码语言:javascript
复制
2019-10-12T07:20:50.52Z (UTC+0)
2019-10-12T07:20:50.52+00:00 (UTC+0)
2019-10-12T14:20:50.52-04:00 (UTC-4)

一开始并不明白为何要如此复杂的去设置时间,后面看到以下文章才明白这个标准的重要性。

对RFC 3339的时间、时区格式详解[5]

logcli query同样支持Logql语法
代码语言:javascript
复制
logcli query '{host="db04",filename="/var/log/messages"}|="Removed"' --limit=10000 --since=2h

注意:能查出来的最远的日志在Loki配置文件有定义,即块存储周期配置 retention_period: 168h # 超过168h的块数据将被删除。

排错

1. 日志量大推送错误

当你搭建完成 promtail,并且启动发送日志到 loki 的时候很有可能会碰到这个错误,因为你要收集的日志太多了,超过了 loki 的限制,所以会报429。

代码语言:javascript
复制
level=warn ts=2022-03-13T07:00:13.558415458Z caller=client.go:344 component=client host=10.101.249.246:5654 msg="error sending batch, will retry" status=429 error="server returned HTTP status 429 Too Many Requests (429): Ingestion rate limit exceeded (limit: 4194304 bytes/sec) while attempting to ingest '10793' lines totaling '1048548' bytes, reduce log volume or contact your Loki administrator to see if the limit can be increased"

loki 配置文件添加 ingestion_rate_mb: 15,旧版添加 ingestion_rate: 25000

代码语言:javascript
复制
limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h
  # 每秒允许promtail传输32MB,默认为4
  ingestion_rate_mb: 32
  ingestion_burst_size_mb: 64

一般用我的配置文件不会出现这个问题。

2. Grafana只显示1000行日志

1000行日志有时候1s钟的日志量都没有,需要显示更多可修改Grafana数据源的以下配置。

我的经验是大于10000行Grafana就会变得非常卡。

所以建议使用条件过滤。

总结

总而言之,对于一个小规模系统而言,LPG对我们定位问题起到了极大的作用,特别是当要检索多个日志文件是否存在某一条同样的日志时,可以给运维节约大量时间,再也不需要一个一个文件去grep了。连我们的乙方看到我们这个系统后都说要回去整一套。

注:

  • Storage中bolt-shipper与bolt的区别:

Loki2.0版本之后,对于使用boltdb存储索引部分做了较大的重构,采用新的boltdb-shipper模式,可以让Loki的索引存储在S3上,而彻底摆脱Cassandra或者谷歌的BigTable。此后服务的横向扩展将变得更加容易。详见:https://grafana.com/docs/loki/latest/operations/storage/boltdb-shipper/[6]

参考资料

[1]

https://grafana.com/docs/loki/latest/configuration/: https://grafana.com/docs/loki/latest/configuration/

[2]

https://grafana.com/docs/loki/latest/logql/: https://grafana.com/docs/loki/latest/logql/

[3]

https://github.com/grafana/loki/releases/tag/v2.4.2: https://github.com/grafana/loki/releases/tag/v2.4.2

[4]

IETF RFC-3339: https://www.rfc-editor.org/rfc/rfc3339

[5]

对RFC 3339的时间、时区格式详解: https://www.jianshu.com/p/f50005a2410c

[6]

https://grafana.com/docs/loki/latest/operations/storage/boltdb-shipper/: https://grafana.com/docs/loki/latest/operations/storage/boltdb-shipper/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Hadoop集群运维 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简易日志系统LPG生产环境实践指南 | 坑我已经帮你们踩好了
    • 前言
      • 简介
        • LPG架构
          • Distributor
          • Igester
          • query-frontend
          • Querier
        • 部署与配置
          • 使用指南
            • Gafana对接Loki
            • logcli使用
          • 排错
            • 1. 日志量大推送错误
          • 总结
            • 参考资料
        相关产品与服务
        Grafana 服务
        Grafana 服务(TencentCloud Managed Service for Grafana,TCMG)是腾讯云基于社区广受欢迎的开源可视化项目 Grafana ,并与 Grafana Lab 合作开发的托管服务。TCMG 为您提供安全、免运维 Grafana 的能力,内建腾讯云多种数据源插件,如 Prometheus 监控服务、容器服务、日志服务 、Graphite 和 InfluxDB 等,最终实现数据的统一可视化。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档