资讯详情

Rsyslog 集中式日志转发实战:从协议选型到队列配置

📅 2026/10/15 23:08:56 | 华诺云谱 👁 阅读
Rsyslog 集中式日志转发实战:从协议选型到队列配置
1. 为什么值得花时间搞懂 Rsyslog 的转发链路日志这东西平时没人搭理一出事全公司都来找你。我做过好几个集中式日志平台的项目踩过最大的坑不是存储不够、不是查询太慢而是日志根本没送到。应用服务器上tail -f看得好好的一到中心节点就缺了几段排查半天发现是 rsyslog 的转发规则写错了或者 UDP 丢包了没人发现。Rsyslog 是 Linux 世界最主流的日志守护进程几乎所有的发行版都默认装着它。它的核心能力就两件事本地收集和网络转发。把几十上百台机器的日志汇聚到一台中心服务器上做统一存储、检索、告警这是运维里最基础也最刚需的一环。不管你后面接的是 Elasticsearch、Loki 还是自己写的分析脚本日志能稳定、完整、低延迟地到达中心节点是整个链路的地基。这篇文章面向的是需要搭建集中式日志系统的运维和开发人员不管你之前有没有接触过 rsyslog跟着走一遍都能把服务端和客户端的配置跑通。我会把配置文件的每一段拆开讲清楚它在干什么、为什么这么写再补充一些官方文档里不会告诉你的实操细节。整套方案基于 rsyslog 8.x 版本这是目前主流发行版自带的版本兼容性最好。2. 整体架构设计与协议选型思路2.1 集中式日志转发的三种典型拓扑在动手写配置之前先想清楚日志的流向。常见的拓扑有三种第一种是直连型所有客户端直接把日志发给中心服务器。结构最简单适合机器数量在几十台以内的场景。缺点是中心服务器是单点一旦挂了所有日志都丢。第二种是中继型客户端先发给区域中继节点中继节点再转发给中心。适合跨机房、跨网段的场景可以减少跨网络的连接数也能在中继节点做一层缓冲。第三种是混合型关键业务直连中心普通业务走中继。这种最灵活但配置管理复杂度也最高。我这次以最实用的直连型为主线来展开中继的配置会在后面单独提。你先把一条链路跑通再考虑扩展。2.2 UDP、TCP 还是 RELP协议选型的核心权衡这是整个方案里最重要的一个决策直接决定了日志的可靠性和性能。很多人默认用 UDP因为配置简单但生产环境里我强烈建议至少用 TCP。协议可靠性性能配置复杂度适用场景UDP低会丢包最高最低内网、日志量大且可容忍丢失TCP中有连接保障中中大多数生产场景RELP高应用层确认中低高审计日志、不可丢失场景UDP 的问题在于它是无连接的网络稍微拥塞或者接收端处理不过来数据包就直接被丢弃而且发送端完全不知道。我遇到过一台机器每秒产生上万条日志用 UDP 转发到中心高峰期丢了将近三成事后查问题发现关键的那几条恰好丢了非常被动。TCP 解决了丢包问题因为它有重传机制和流量控制。但 TCP 也有个坑如果中心服务器重启客户端在重连期间产生的日志可能会丢。这时候就需要 RELPReliable Event Logging Protocol它在应用层做了确认和重传能保证日志至少送达一次。代价是性能会下降配置也更复杂。我的建议是普通业务日志用 TCP审计类、合规类日志用 RELP。UDP 只在极端追求性能且能接受丢失的场景下用。2.3 消息格式的选择从 RFC3164 到 RFC5424日志消息的格式也影响后续的解析。老式的 RFC3164 格式就是传统的 syslog 格式时间戳精度只到秒没有结构化字段。RFC5424 是 2009 年发布的新标准支持毫秒级时间戳、结构化数据、UTF-8 编码。如果你的日志后面要进 Elasticsearch 做结构化分析建议在客户端就配置成 RFC5424 格式这样时间戳精度更高字段也更规范。配置上就是在模板里指定RSYSLOG_SyslogProtocol23Format。不过要注意有些老旧的接收端可能不认这个格式需要先确认对端兼容性。3. 服务端配置把中心节点搭起来3.1 基础环境准备与模块加载服务端我用的是一台 4 核 8G 的虚拟机系统是主流的 Linux 发行版。先确认 rsyslog 版本rsyslogd -v输出里能看到版本号8.x 以上都支持本文的配置。如果版本太老建议先升级因为老版本在 TCP 并发和队列管理上有不少已知问题。服务端的配置文件在/etc/rsyslog.conf但更好的做法是在/etc/rsyslog.d/目录下新建独立的配置文件比如10-server.conf。这样升级系统时不会覆盖你的配置也方便管理。首先要加载必要的模块。rsyslog 是模块化设计的不用的功能不加载减少资源占用# 加载 TCP 和 UDP 输入模块 module(loadimtcp) module(loadimudp) # 加载 RELP 输入模块如果要用 RELP module(loadimrelp)imtcp和imudp分别对应 TCP 和 UDP 的接收。这里有个细节模块加载是全局的但监听端口是在 input 里指定的两者要配合。3.2 监听端口与接收规则配置加载模块后要告诉 rsyslog 在哪个端口监听# TCP 监听 514 端口 input(typeimtcp port514) # UDP 监听 514 端口 input(typeimudp port514) # RELP 监听 2514 端口 input(typeimrelp port2514)514 是 syslog 的标准端口但它是特权端口小于 1024需要 root 权限才能绑定。rsyslog 默认以 root 启动所以没问题。如果你不想用标准端口改成 1514 之类的也可以客户端对应改一下就行。注意如果服务器开了防火墙记得放行对应端口。TCP 和 UDP 要分别放行很多人只放了 TCP 忘了 UDP结果用 UDP 的客户端一直连不上。接收规则决定了日志收到后怎么处理。最简单的做法是按来源 IP 分目录存储# 按客户端 IP 分目录存储 template(nameRemoteLogs typestring string/var/log/remote/%FROMHOST-IP%/%$YEAR%-%$MONTH%-%$DAY%.log) # 应用模板 if $fromhost-ip ! 127.0.0.1 then { action(typeomfile dynaFileRemoteLogs) stop }这段配置的意思是如果日志不是本机产生的就按来源 IP 和日期存到/var/log/remote/下然后停止后续处理。stop很关键不加的话日志会继续往下走可能被重复写入本地日志文件。%FROMHOST-IP%是 rsyslog 的属性变量代表发送方的 IP。类似的常用变量还有%HOSTNAME%主机名、%syslogtag%标签、%msg%消息内容。这些变量在模板里可以直接引用。3.3 磁盘存储策略与目录规划存储目录的规划直接影响后续的检索效率。我见过有人把所有日志堆在一个文件里几天下來文件几十个 Ggrep一次要几分钟。合理的做法是按维度分目录# 按主机名和日期分层 template(nameStructuredLogs typestring string/var/log/remote/%HOSTNAME%/%$YEAR%/%$MONTH%/%$DAY%.log)这样每个主机每天一个文件检索时先定位主机再定位日期速度快很多。缺点是文件数量多如果机器有几百台一年下来文件数量很可观。这时候可以考虑用dynaFile配合omfile的压缩功能或者直接接入 Elasticsearch 做索引。磁盘空间也要提前规划。假设 100 台机器每台每天产生 500MB 日志一天就是 50GB保留 30 天需要 1.5TB。这个量级用本地磁盘扛不住要么做定期清理要么直接写远程存储。rsyslog 支持输出到多种后端包括数据库、消息队列、对象存储等后面会提到。4. 客户端配置让日志可靠地发出去4.1 转发规则的编写与匹配客户端的配置核心是匹配规则加转发动作。匹配规则决定哪些日志要转发转发动作决定发到哪里、用什么协议。最简单的全量转发# 加载 TCP 输出模块 module(loadomfwd) # 所有日志转发到中心服务器 *.* action(typeomfwd target192.168.1.100 port514 protocoltcp)*.*表示所有设施facility和所有优先级priority的日志。设施包括 auth、cron、daemon、kern、mail 等优先级从 debug 到 emerg 共 8 级。实际使用中很少全量转发通常会有选择# 只转发 info 及以上级别的日志排除 debug *.info;*.!debug action(typeomfwd ...) # 只转发特定设施的日志 auth,authpriv.* action(typeomfwd ...)*.!debug里的感叹号表示排除这个语法容易记混多写几次就熟了。4.2 队列机制应对网络抖动和中心节点重启这是客户端配置里最容易被忽略、但最重要的部分。默认情况下如果中心服务器不可达rsyslog 会直接丢弃日志。加上队列配置后日志会先缓存在本地等网络恢复再发。action(typeomfwd target192.168.1.100 port514 protocoltcp queue.typeLinkedList queue.size10000 queue.filenamefwd_queue queue.saveOnShutdownon queue.maxdiskspace1g action.resumeRetryCount-1 action.resumeInterval30)逐项解释一下queue.typeLinkedList使用内存队列性能最好。如果对可靠性要求极高可以改成Disk但性能会下降。queue.size10000内存队列最多缓存 10000 条消息。queue.filenamefwd_queue磁盘队列的文件名前缀配合queue.typeDisk或内存队列溢出时使用。queue.saveOnShutdownon关机时把队列内容存盘重启后继续发送。queue.maxdiskspace1g磁盘队列最大占用 1GB。action.resumeRetryCount-1无限重试-1 表示不限制。action.resumeInterval30重试间隔 30 秒。这套配置下来即使中心服务器宕机几个小时客户端也能把日志缓存在本地恢复后自动补发。我实测过断网 2 小时、积压几十万条日志的场景恢复后几分钟内全部补发完成没有丢失。提示queue.size不要设得太大内存队列占用的是进程内存设成 100 万条可能直接把 rsyslog 进程撑爆。一般 10000 到 50000 之间比较稳妥超出的部分会溢出到磁盘队列。4.3 多目标转发与条件路由有时候日志需要同时发给多个目标比如一份发给中心日志服务器一份发给本地的分析程序。rsyslog 支持一个规则匹配多个动作*.info action(typeomfwd target192.168.1.100 port514 protocoltcp) *.info action(typeomfwd target192.168.1.101 port514 protocoltcp)两条 action 会依次执行日志发往两个目标。如果只想在特定条件下转发可以用 if 判断if $programname nginx then { action(typeomfwd target192.168.1.100 port514 protocoltcp) }$programname是产生日志的程序名nginx 的访问日志和错误日志都会带上这个标签。按程序名路由是实践中最常用的方式因为不同程序的日志价值和处理方式差异很大。5. 完整实操流程与验证方法5.1 服务端从零到可用的完整步骤我把服务端的搭建过程整理成可复制的步骤第一步确认 rsyslog 已安装并运行systemctl status rsyslog如果没有安装用包管理器装上。主流发行版都自带一般不用额外装。第二步创建服务端配置文件/etc/rsyslog.d/10-server.conf内容如下module(loadimtcp) module(loadimudp) input(typeimtcp port514) input(typeimudp port514) template(nameRemoteLogs typestring string/var/log/remote/%FROMHOST-IP%/%$YEAR%-%$MONTH%-%$DAY%.log) if $fromhost-ip ! 127.0.0.1 then { action(typeomfile dynaFileRemoteLogs) stop }第三步创建存储目录并设置权限mkdir -p /var/log/remote chown syslog:adm /var/log/remote不同发行版 rsyslog 的运行用户不同有的是syslog有的是root。用ps aux | grep rsyslog确认一下把目录权限给对应用户。第四步检查配置语法rsyslogd -N1这个命令会解析配置文件并报告错误不实际启动服务。配置有语法问题时它会明确指出哪一行出错非常实用。每次改完配置都应该跑一遍。第五步重启服务systemctl restart rsyslog第六步确认端口在监听ss -tlnp | grep 514 ss -ulnp | grep 514分别检查 TCP 和 UDP 的监听状态。5.2 客户端配置与连通性测试客户端的配置步骤类似第一步创建/etc/rsyslog.d/20-client.confmodule(loadomfwd) *.* action(typeomfwd target192.168.1.100 port514 protocoltcp queue.typeLinkedList queue.size10000 queue.filenamefwd_queue queue.saveOnShutdownon action.resumeRetryCount-1 action.resumeInterval30)第二步检查语法并重启rsyslogd -N1 systemctl restart rsyslog第三步手动产生一条日志测试logger test message from clientlogger是产生 syslog 消息的标准工具几乎所有 Linux 都有。执行后到服务端的/var/log/remote/下找对应 IP 的目录看日志有没有到。如果没到先检查网络连通性telnet 192.168.1.100 514TCP 能连上说明网络和端口没问题问题出在配置上。UDP 没法用 telnet 测可以用ncecho test | nc -u 192.168.1.100 5145.3 用 tcpdump 抓包定位转发问题配置都对但日志就是不到这时候抓包是最直接的排查手段。在服务端执行tcpdump -i any -nn port 514 -A-A参数会把包内容以 ASCII 形式打印出来能直接看到日志文本。然后在客户端执行logger命令观察服务端有没有抓到包。如果抓到了包但日志没落盘说明是服务端的处理规则有问题重点检查模板和 action 配置。如果没抓到包说明是客户端没发出来或者网络不通重点检查客户端的转发规则和防火墙。这个排查思路我用了很多次基本能在几分钟内定位问题所在。抓包看到的内容还能确认消息格式是否符合预期比如时间戳格式、主机名字段是否正确。6. 常见问题与排查技巧实录6.1 日志重复、丢失、乱序的根因分析日志重复是最常见的问题之一。原因通常是配置了多个匹配规则同一条日志被多个 action 处理。比如既配了*.*全量转发又配了*.info的转发info 级别的日志就会发两次。解决办法是理清规则优先级用stop及时终止后续处理。日志丢失的原因就多了。UDP 丢包是最常见的换成 TCP 基本能解决。队列配置不当也会丢比如queue.size太小、没配磁盘队列网络一抖动队列就溢出。还有一种隐蔽的情况是服务端的imtcp有并发连接数限制客户端多了之后新连接被拒绝日志自然就丢了。可以在服务端配置里加input(typeimtcp port514 maxsessions500)提高上限。日志乱序在 UDP 下很常见因为 UDP 不保证顺序。TCP 下一般不会乱序但如果用了多线程处理或者多个队列也可能出现。对顺序敏感的场景建议在消息里带上客户端的时间戳和序列号接收端按序列号排序。6.2 性能瓶颈的识别与调优当日志量上来后rsyslog 可能成为瓶颈。判断方法很简单看 CPU 和磁盘 IOtop -p $(pgrep rsyslogd) iostat -x 1如果 rsyslog 进程 CPU 占用持续很高通常是模板处理或者正则匹配太复杂。优化方向是简化模板避免在每条日志上做昂贵的字符串操作。如果磁盘 IO 是瓶颈说明写入速度跟不上可以考虑用内存队列缓冲或者把日志先写到 tmpfs 再异步落盘。还有一个容易忽略的点是日志文件的数量。如果按主机名和日期分目录文件数量会很多文件系统的 inode 和目录查找都会成为瓶颈。这种情况下建议用omfile的asyncWriting模式或者直接接入支持批量写入的后端。6.3 高频踩坑速查表现象可能原因排查方法解决方案日志完全不到防火墙拦截telnet 测端口放行 TCP/UDP 端口日志时有时无UDP 丢包tcpdump 抓包对比改用 TCP日志重复多条规则匹配检查配置文件加 stop 终止中心重启后日志缺失无队列缓冲检查 queue 配置加磁盘队列日志时间戳不对时区不一致对比两端时间统一时区配置磁盘写满无清理策略df -h 查看配 logrotate 或远程存储这张表里的每一条我都在实际项目中遇到过尤其是时区问题跨机房部署时特别容易踩。客户端和服务端时区不一致日志时间戳对不上排查问题时能把人逼疯。统一用 UTC 时间是最稳妥的做法。7. 进阶玩法从转发到结构化处理7.1 用模板定制日志格式默认的 syslog 格式信息量有限通过模板可以定制输出格式。比如输出成 JSON方便后续程序解析template(nameJsonFormat typestring string{\time\:\%timereported:::date-rfc3339%\,\host\:\%HOSTNAME%\,\program\:\%programname%\,\message\:\%msg%\}\n)%timereported:::date-rfc3339%里的:::date-rfc3339是属性选项把时间格式化成 RFC3339 标准。类似的选项还有date-rfc3164、date-mysql等。JSON 格式的日志直接喂给 Elasticsearch 或者 Loki省去了大量解析工作。7.2 接入消息队列做削峰填谷日志量特别大的时候rsyslog 直接写文件可能扛不住。这时候可以在中间加一层消息队列rsyslog 只负责把日志发到队列后面的消费和存储由专门的程序处理module(loadomkafka) action(typeomkafka broker192.168.1.200:9092 topicsyslog confParam[compression.codecgzip])omkafka是 Kafka 输出模块需要单独安装。类似的还有omrabbitmq、omelasticsearch等。这种架构的好处是解耦rsyslog 不用关心下游怎么处理队列本身也能缓冲流量高峰。7.3 日志轮转与长期归档策略日志不能无限增长必须配轮转。rsyslog 本身不负责轮转靠系统的 logrotate/var/log/remote/*/*.log { daily rotate 30 compress delaycompress missingok notifempty create 0640 syslog adm }这段配置表示每天轮转一次保留 30 天压缩旧文件。delaycompress表示延迟一天再压缩避免正在写入的文件被压缩导致问题。create指定新文件的权限和属主要和 rsyslog 的运行用户匹配。长期归档的话可以考虑把轮转后的日志同步到对象存储。用rclone或者awscli之类的工具配合 cron 定时执行。归档时建议按年月打包减少小文件数量检索时也方便定位。8. 我踩过的几个印象深刻的坑说几个配置文档里不会写、但实际部署时大概率会遇到的坑。第一个是主机名解析。rsyslog 默认会用%HOSTNAME%作为日志里的主机标识但如果客户端的/etc/hosts配置有问题或者 DNS 解析慢rsyslog 在启动时会卡住等解析。表现是服务启动特别慢日志延迟很高。解决办法是在客户端配置里加global(net.enableDNSoff)直接用 IP 标识不做反向解析。第二个是SELinux。在某些开启了 SELinux 的系统上rsyslog 绑定 514 端口或者写/var/log/remote/会被拒绝日志里能看到 AVC 拒绝记录。要么调整 SELinux 策略要么临时设为 permissive 模式测试。生产环境建议正确配置策略不要直接关掉。第三个是配置文件的加载顺序。/etc/rsyslog.d/下的文件是按文件名排序加载的10-server.conf会在20-client.conf之前加载。如果两个文件里有冲突的规则后面的会覆盖前面的。命名时用数字前缀就是为了控制顺序这个习惯要养成。第四个是队列文件残留。如果 rsyslog 异常退出磁盘队列文件可能残留下次启动时会尝试恢复。如果队列文件损坏rsyslog 可能启动失败。这时候需要手动清理队列文件目录通常在/var/spool/rsyslog/下。清理前确认没有重要日志积压否则会丢数据。这套配置我在多个项目里用过从几十台机器的小集群到上千台的大集群都跑得通。核心就是三点协议选 TCP 保可靠队列配磁盘防丢失模板分目录利检索。把这三点做到位日志转发这条链路基本不会出大问题。后面要扩展的话往上加消息队列、加结构化解析、加告警规则都是在这个稳定地基上做加法。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑