Syslog与Filebeat日志采集平台搭建及存储设计 - 第3节
理解Syslog的两套“方言”
说起Syslog的消息格式,其实有两个标准在打架。老的是RFC 3164,新的是RFC 5424。我刚开始接触日志系统时,也被这两个格式搞晕过——明明都叫Syslog,解析起来却完全不一样。
说白了,RFC 3164是“野路子”出身。它更像一个约定俗成的格式,大家照着做就行。而RFC 5424是IETF后来正式制定的标准,结构清晰,扩展性强。
你想想看,如果日志格式都不统一,分析工具怎么工作?我在一个项目中就吃过这个亏。当时用Filebeat收集网络设备日志,结果一半能解析,一半直接报错。后来才发现,老设备走的是RFC 3164,新设备用的是RFC 5424。
RFC 3164——传统格式
RFC 3164最早在2001年发布。它的格式很简单,甚至有点简陋。
<PRI>Timestamp Hostname Message
一个典型的RFC 3164消息长这样:
<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8
我来拆解一下各部分:
- <34> —— PRI值,由Facility和Severity计算得出。公式是:PRI = Facility × 8 + Severity。
- Oct 11 22:14:15 —— 时间戳。不带年份,格式固定。嗯,这里要小心——没有年份信息,跨年日志处理起来会很头疼。
- mymachine —— 主机名。可以是短名称,也可以是FQDN。
- su: 'su root' failed for lonvick on /dev/pts/8 —— 消息体。剩下的全是内容,没有结构化字段。
我曾经遇到过的一个坑:RFC 3164的时间戳没有时区信息。如果你的设备分布在多个时区,时间对齐就会非常麻烦。我有个客户,美国的防火墙和中国的服务器混在一起,日志时间全靠猜。后来我建议统一用NTP对齐到UTC,才解决了这个问题。
RFC 5424——现代化格式
RFC 5424在2009年发布。它解决了老格式的诸多痛点。我个人习惯,只要条件允许,都会优先用这个格式。
一个完整的RFC 5424消息长这样:
<165>1 2003-10-11T22:14:15.003Z mymachine.example.com evntslog - ID47 [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] BOMAn application event log entry...
看着比老格式复杂多了吧?其实结构更清晰:
- <165> —— PRI值,和RFC 3164一样计算。
- 1 —— 版本号。固定为1,用于标识这是RFC 5424格式。
- 2003-10-11T22:14:15.003Z —— 时间戳。带时区、带毫秒,格式为ISO 8601。
- mymachine.example.com —— 主机名。必须是FQDN。
- evntslog —— 应用名称。用于标识产生日志的进程。
- - —— 进程ID。这里用“-”表示没有提供。
- ID47 —— 消息ID。可以用于关联同一类型的日志。
- [exampleSDID@32473 iut="3" eventSource="Application" eventID="1011"] —— STRUCTURED-DATA。这是新格式最牛的扩展点,可以携带键值对。
- BOMAn application event log entry... —— MSG。消息体,前缀BOM用于标识UTF-8编码。
RFC 5424的STRUCTURED-DATA部分,说白了就是一组标准化的键值对。你可以在里面放任何自定义字段,比如请求ID、用户ID、业务类型。解析器拿到后可以直接提取,不用再做正则匹配。
核心差异对比
我整理了一张表,两套格式的核心区别一目了然:
| 特性 | RFC 3164 | RFC 5424 |
|---|---|---|
| 发布时间 | 2001年 | 2009年 |
| 版本号 | 无 | 固定为1 |
| 时间戳格式 | Mmm dd hh:mm:ss | ISO 8601,含时区和毫秒 |
| 年份信息 | 无 | 完整4位年份 |
| 时区信息 | 无 | 包含 |
| 主机名 | 可短可长 | 强制FQDN |
| 结构化数据 | 不支持 | 支持SD-ID和键值对 |
| 字符编码 | 无明确约定 | UTF-8 |
| 消息长度 | 通常不超过1024字节 | 支持更长,可协商 |
为什么两个格式共存?
这不是技术问题,而是历史包袱问题。市面上大量网络设备、防火墙、老服务器还在跑RFC 3164。要它们升级固件支持新格式,成本太高。
我记得在给一家金融公司做日志方案时,他们的核心交换机就是RFC 3164的忠实用户。没办法,只能让Filebeat同时兼容两种格式。
实际项目中如何选择?
我的建议很直接:
- 新建系统:强制用RFC 5424。前期规范一点,后期省事很多。
- 老系统改造:如果可以升级软件,就升级。不行就继续用老格式,用解析器做兼容。
- 混合场景:用Filebeat或Rsyslog做格式统一。Filebeat可以在输入端自动识别PRI和版本号,判断走哪种解析逻辑。
关键经验:我曾经帮客户排查过一个诡异问题。他们的日志分析平台突然少了一半数据,查了两天才发现,某台服务器的Syslog从4.3升级到了5.0,默认输出的格式从3164变成了5424。解析器只支持老格式,新格式的日志全部被丢弃了。从那以后,我养成了一个习惯——在日志采集层做格式检测和报警,而不是默认信任所有输入。
SVG:Syslog消息格式演化流程图
下面这张图展示了从RFC 3164到RFC 5424的演化路径,以及现代应用中最常见的适配方案:
Filebeat中的配置实战
在Filebeat中处理两种格式,其实很简单。Filebeat会自动识别PRI值和版本号字段,不需要人工干预。但我建议你显式配置一下,确保兼容性。
filebeat.inputs:
- type: syslog
protocol.udp:
host: "0.0.0.0:514"
# 自动兼容两套格式
# RFC 3164 和 RFC 5424 都能解析
fields_under_root: true
fields:
log_type: syslog
嗯,这里要注意。Filebeat默认的syslog输入支持两种格式,但如果你需要从结构化数据中提取字段,就得加上自定义配置了:
processors:
- dissect:
tokenizer: "%{facility_severity} %{timestamp} %{hostname} %{process}: %{message}"
field: "message"
target_prefix: "parsed"
我个人习惯在测试环境先用一条真实日志验证解析结果。这是最稳妥的办法,别问我怎么知道的——我踩过太多坑了。
测试解析的命令:echo '<34>1 2003-10-11T22:14:15.003Z mymachine.example.com su - - BOMfailure' | nc -u localhost 514。发过去后,去Filebeat的日志里看字段是否完整。
最后说一句,两种格式的选择,本质上是兼容性和扩展性的权衡。如果你的日志需要被多种系统消费,RFC 5424是更安全的选择。如果只是内部简单使用,RFC 3164也够用。关键是要搞清楚你的设备支持什么,以及你的下游系统能解析什么。