拳打 ES 脚踢 Loki,VictoriaLogs 正式版来了

巴辉特 2024-11-26 08:46:36

VictoriaLogs 是 VictoriaMetrics 团队发布的日志存储系统,声称可以用单节点替代之前 30 个节点的 ElasticSearch 集群,查询速度快,节省 CPU 和内存,具备极高的压缩比大幅节省存储。2024.11 发布了正式版,我们一起来了解一下。

VictoriaLogs特性

VictoriaLogs 特性

  • 它可以接受来自流行日志收集器的日志。比如对接 Vector、Logstash、Fluentbit、Promtail 等等
  • 与 Elasticsearch 和 Grafana Loki 相比,它的设置和操作要容易得多。组件比较少。
  • 它提供简单而强大的查询语言,可在所有日志字段中进行全文搜索。其检索语法称为 LogsQL,和 ElasticSearch 新提供的 EQL 有点像。
  • 它提供了用于查询VictoriaLogs的交互式命令行工具 - vlogscli。让你像是使用 UNIX 工具一样来查询日志。
  • 它可以与用于日志分析的优秀旧 Unix 工具无缝结合,例如 grep、less、sort、jq 等。其实大部分用户最核心的需求场景就是分布式检索。
  • 在相同的硬件上运行时,它可以处理比 Elasticsearch 和 Grafana Loki 大 30 倍的数据量。
  • 它为具有高基数(例如大量唯一值)的日志字段(例如 trace_id 、 user_id 和 ip 提供开箱即用的快速全文搜索。
  • 支持多租户。
  • 它支持无序日志的摄取,也称为回填。
  • 支持选择所选日志前后的周围日志。就类似 grep 的 -A -B 参数。
  • 它提供了用于查询日志的 Web UI。
  • 它提供了Grafana插件用于查询日志。
  • 它支持警报。

如上是从 VictoriaLogs 官方文档中摘录的特性,可以看到 VictoriaLogs 作为后起之秀,针对日志场景做了很多考虑。

VictoriaLogs 调优

VictoriaLogs 声称自己的默认参数基本就是最优的,默认值会根据可用的 CPU 和 RAM 资源自动调整,无需额外调整。操作系统也无需额外调优,只需要把允许打开的文件句柄数量调大即可。

推荐的文件系统是 ext4 ,推荐的持久存储是 GCP 上基于 HDD 的持久磁盘,因为它自身提供高可用机制,并且可以动态调整大小。如果您计划在 ext4 分区上存储超过 1TB 的数据或计划将其扩展至超过 16TB,则建议将以下选项传递给mkfs.ext4 :

mkfs.ext4 ... -O 64bit,huge_file,extent -T huge

VictoriaLogs 监控

VictoriaLogs 在 http://localhost:9428/metrics 暴露了其自身监控指标(符合 Prometheus 协议),可以通过 Prometheus 或者 vmagent 采集。VictoriaLogs 也提供了 Grafana 仪表盘Prometheus 告警规则

VictoriaLogs 将自己的日志发送到标准输出。建议在故障排除期间调查这些日志。

VictoriaLogs 升级

VictoriaLogs 只有一个二进制,只要 changelog 不做额外说明就可以直接替换二进制升级。停进程的时候别 kill -9,用 kill -INT 优雅退出。

VictoriaLogs 日志保留时间

默认情况下,VictoriaLogs 存储时间戳在时间范围 [now-7d, now] 内的日志条目,同时删除给定时间范围之外的日志。例如它使用7天的保留。可以使用 -retentionPeriod 命令行标志配置保留。该标志接受从 1d (一天)到 100y (100 年)的值。

例如,以下命令启动 VictoriaLogs 并保留 8 周:

/path/to/victoria-logs -retentionPeriod=8w

如果日志的时间戳超出配置的保留时间,VictoriaLogs 会在数据摄取阶段自动删除日志。删除的日志示例会与WARN消息一起记录,以简化故障排除。每次由于时间戳超出保留而删除摄取的日志条目时, vl_rows_dropped_total 指标都会递增。建议设置以下警报规则,以便在将具有错误时间戳的日志引入 VictoriaLogs 时收到通知:

rate(vl_rows_dropped_total[5m]) > 0

默认情况下,VictoriaLogs 不接受时间戳大于 now+2d 日志条目,即未来 2 天。如果您需要接受具有更大时间戳的日志,请通过 -futureRetention 命令行标志指定所需的“未来保留”。例如,以下命令启动 VictoriaLogs,它接受带有最多未来一年时间戳的日志:

/path/to/victoria-logs -futureRetention=1y

如果 -storageDataPath 目录中的数据总大小大于给定阈值,则可以将 VictoriaLogs 配置为自动删除较旧的每日分区 -retention.maxDiskSpaceUsageBytes 命令行标志。例如,以下命令启动 VictoriaLogs,如果总存储大小大于 100GiB,它将删除旧的每日分区:

/path/to/victoria-logs -retention.maxDiskSpaceUsageBytes=100GiB

VictoriaLogs 通常将日志压缩 10 倍或更多倍。这意味着就上面的参数而言 VictoriaLogs 在运行时可以存储超过 1 TB 的未压缩日志。

VictoriaLogs 至少保留最后两天的数据,以保证查询时可以返回最后一天的日志。这意味着,如果最近两天的数据大小超过 -retention.maxDiskSpaceUsageBytes,总磁盘空间使用量可能会超过 -retention.maxDiskSpaceUsageBytes

注意,-retentionPeriod-retention.maxDiskSpaceUsageBytes 独立生效。如果你设置了 -retention.maxDiskSpaceUsageBytes,如果每天的数据量比较少,你肯定希望存储尽量多时间的数据,此时你可以设置 -retentionPeriod 为一个较大的值。比如:

/path/to/victoria-logs -retention.maxDiskSpaceUsageBytes=10TiB -retentionPeriod=100y

VictoriaLogs 存储目录

VictoriaLogs 将其所有数据存储在一个目录中 victoria-logs-data 。可以通过 -storageDataPath 命令行标志更改目录的路径。例如,以下命令启动 VictoriaLogs,它将数据存储在 /var/lib/victoria-logs

/path/to/victoria-logs -storageDataPath=/var/lib/victoria-logs

如果 -storageDataPath 目录丢失,VictoriaLogs 会在第一次运行时自动创建该目录。

VictoriaLogs 高可用

目前 VictoriaLogs 没有提供集群版本,只有单机版本,所以高可用主要是靠双写来实现。

  • 日志收集器:日志收集器应支持将传入数据复用到多个输出(目的地)。 Fluent Bit、Logstash、Fluentd 和 Vector 等流行的日志收集器已经提供了此功能。
  • VictoriaLogs 单节点实例:使用两个或更多实例来实现HA。
  • vmauth 或负载均衡器:用于从副本之一读取数据,以确保平衡和冗余访问。

VictoriaLogs 高可用

VictoriaLogs 安装体验

VictoriaLogs 提供了多种安装方式,我这里使用二进制的方式安装,从下面的地址下载其发布包:

https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v1.0.0-victorialogs

我的环境是 Macbook M1 芯片,所以下载 victoria-logs-darwin-arm64-v1.0.0-victorialogs.tar.gz 这个包,解压后就是一个二进制文件 victoria-logs-prod,直接运行即可。

./victoria-logs-prod -syslog.listenAddr.tcp=:29514

我在运行的时候加了一个 -syslog.listenAddr.tcp=:29514 参数,这样 VictoriaLogs 就会监听 29514 端口接收 syslog 数据。可以方便我快速体验。启动 VictoriaLogs 之后,可以通过 http://localhost:9428/ 访问其 Web UI。

使用 rsyslog 发送日志到 VictoriaLogs

我本地还有一个虚拟机,我在虚拟机里配置一下 rsyslog,把日志发送到 VictoriaLogs。在 /etc/rsyslog.d/50-default.conf 最下面加了一行配置:

*.* @@10.211.55.2:29514

重启 rsyslog 服务,然后我们就可以通过 VictoriaLogs 的 UI 查到相关日志了:

VictoriaLogs UI

上面的例子里,我查询的条件是 *,后面有个 limit 参数,默认是 50,点击查询,立马就可以出结果。结果分两部分,上面一部分是图表,展示的是不同时间的日志量,分成多了多条线,每个线代表一个 log stream。下面的区域就是日志详情了。

何为 log stream

log stream 是 VictoriaLogs 中的一个概念,它是一组具有相同标签的日志条目。例如,所有来自相同应用程序的日志条目都可以组成一个 log stream。log stream 可以包含任意数量的日志条目。log stream 可以包含来自不同标签集的日志条目。

log stream 的标签和 Prometheus 生态的标签类似,都是键值对。例如上图中:

app_name="kernel", hostname="ubuntu-linux-22-04-desktop"

上面两个标签就是某个 log stream 的标签。这俩标签是 VictoriaLogs 从 syslog 的日志流中自动解析出来的。VictoriaLogs 会给 log stream 的标签做索引,检索速度很快。通常来讲,为了提升日志检索速度,都是在检索时提供尽量细化的筛选条件,最有效的检索条件就是时间范围和 log stream 的标签。

日志记录的结构

日志记录的结构

上图是我截取的一条日志,这个日志从大面上看,包含两部分,一个是日志文本(说是从 [1015282.725324]peer="unconfined" 的那大段字符串),一个是日志元信息(说的是 _time_stream_idseverity 等结构化字段)。

实际上日志文本也是一个特殊字段,叫 _msg。结构化字段中,可以拿来作为 log stream 标识的字段,单独提取出来,作为 log stream 的标签,即上面的 app_name 和 hostname,标签计算哈希得到 log stream 的 ID,即 _stream_id

除了 _msg 特殊字段外,_time 是另一个特殊必备字段,因为日志嘛,对于每个条目,至少需要时间戳和日志原文两部分。其他的字段都是可选的,用户在采集日志的时候,可以通过 vector、logstash 等工具对日志做结构化,并在推送给 VictoriaLogs 的时候,通过参数告知 VictoriaLogs 哪个字段作为 _time、哪个字段作为 _msg,哪些字段拼成 log stream 的标签,即 _stream

上面这么讲比较抽象,我们看看日志中转的时候,具体是怎么配置的。以 Vector 来举例,Vector 可以把日志发给 ElasticSearch,而 VictoriaLogs 恰恰提供了 ElasticSearch 的兼容接口,所以我们可以把 Vector 的日志发给 VictoriaLogs。

sinks:
  vlogs:
    inputs:
      - your_input
    type: elasticsearch
    endpoints:
      - http://localhost:9428/insert/elasticsearch/
    mode: bulk
    api_version: v8
    healthcheck:
      enabled: false
    query:
      _msg_field: message
      _time_field: timestamp
      _stream_fields: host,container_name

上面的 query 部分中,_msg_field 是指定日志原文字段,_time_field 是指定时间戳字段,_stream_fields 是指定哪些字段作为 log stream 的标签。这样配置后,Vector 就会把日志发送给 VictoriaLogs,VictoriaLogs 会自动解析日志,提取出 _msg_time_stream 等字段。

VictoriaLogs 查询语法

VictoriaLogs 查询语法称为 LogsQL,比如最常见的需求,我们要查看最近 5 分钟内的 error 日志:

error AND _time:5m

上面的查询语法中,error 是日志文本中的关键字,_time:5m 是时间范围,表示最近 5 分钟。这样查询出来的结果就是最近 5 分钟内包含 error 关键字的日志。其中的 AND 可以省略掉,直接写成:

error _time:5m

很清晰吧。

该查询可能以任意顺序返回日志,因为对大量日志进行排序可能需要大量的 CPU 和 RAM。这样的做法可以很快的返回结果,即 VictoriaLogs 去检索的时候只要检索到一条就可以立马返回到 response 中,不需要等待所有的日志都检索完再返回。

但有时我们还是希望能够按时间排序,毕竟过去 5 分钟的数据不会特别多,这时候可以使用 sort 命令:

_time:5m error | sort by (_time) desc

上例使用管道符,对日志结果继续使用 sort 进行排序。当然,我们也可以使用 limit 命令限制返回的日志数量:

_time:5m error | sort by (_time) desc | limit 10

这种管道的查询方式,和 UNIX 的体验很像,是一个很有意思的设计。ElasticSearch 8 开始,支持的 EQL 就是类似这个方式,大家可能都是从 Splunk 借鉴的。更多的 LogsQL 语法可以参考 VictoriaLogs 官方文档,这里就不赘述了。

总结

大家苦于 ElasticSearch 的成本和性能问题,社区出现了 ClickHouse、Doris 等众多日志存储方案,VictoriaLogs 作为挑战者,性能强劲,即将推出集群版本和支持 S3 的版本,感觉非常值得关注。VictoriaMetrics 在指标存储方面已经做得很好,其团队挺值得信赖,大家可以持续关注。

联系我们交流

快猫星云 联系方式 快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云 联系方式
快猫星云
OpenSource
开源版
Flashcat
Flashcat