rsyslog 集中日志采集实战:多台服务器日志汇聚、TLS 传输与磁盘队列防丢

多台服务器的日志散落各处,出事时你根本拼不出真相

手上服务器一多,日志管理立刻变成灾难。A 机器的 Nginx 访问日志在 /var/log/nginx,B 机器的应用日志在 /opt/app/logs,C 机器只有 journalctl 里还留着点记录。某天网站被 CC 攻击,你想知道攻击从哪个 IP 来、打到了哪台机器、有没有同时打数据库,就得挨个 SSH 上去 grep,等拼完线索,攻击早结束了。更糟的是,服务器一旦被入侵,攻击者第一件事往往是清理本地日志,你原本指望的"证据"恰恰在攻击者手里。

解决方案是把日志集中采集到一台日志服务器。所有机器把系统日志、应用日志往一处发,本地即使被清理,日志服务器上还有一份。这不是 ELK 那种重量级方案——对个人站长来说,rsyslog 本身就是 Linux 默认自带的日志守护进程,用它做集中采集,几乎零额外依赖,一台小内存 VPS 就能扛住十几台机器的日志量。

本文把 rsyslog 集中日志从服务端接收、客户端转发、TLS 加密传输,到磁盘队列防丢、日志轮转与检索的全流程讲清楚,并对比它和 Loki/vector 的适用边界。

架构:谁收集、谁转发、谁存储

标准做法是三件套。日志服务器(collector)开启 TCP 5140 或 6514 端口接收;各业务机(client)配置 rsyslog 把本地日志转发过去;collector 按来源主机名或程序名分目录落盘到 /var/log/remote/。这样保证两点:一是日志不再依赖单机磁盘(业务机硬盘坏了日志还在),二是集中检索,一条 grep 覆盖所有机器。

传输协议上,传统的 UDP 514 会丢包且不加密,只适合内网且不看重的场景。生产建议用 TCP,并加上 TLS;中小规模、纯内网可用 TCP 明文,跨公网必须 TLS。

第一步:服务端开启接收并分目录存储

Debian/Ubuntu 的 rsyslog 默认只接收本地日志,不监听网络。需要写一个独立配置文件放在 /etc/rsyslog.d/ 下,避免改动主配置。

# /etc/rsyslog.d/10-remote.conf  —— 日志服务器端
# 加载 TCP 输入模块
module(load="imtcp")
input(type="imtcp" port="5140")

# 按来源主机名分目录,避免所有日志混在一个文件里
template(name="RemotePerHost" type="string"
    string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")

# 所有从网络收到的日志都按上面模板落盘
# 并设置合适权限,防止 rsyslog 无法创建目录
$FileCreateMode 0640
$DirCreateMode 0755
$Umask 0022
*.* action(type="omfile" dynaFile="RemotePerHost")

# 同时保留一份按日期滚动的总汇总,便于快速 grep
template(name="RemoteAll" type="string"
    string="/var/log/remote/all-%$YEAR%-%$MONTH%-%$DAY%.log")
*.* action(type="omfile" dynaFile="RemoteAll")

配置里 %HOSTNAME% 是发送方在日志头里带上的主机名,%PROGRAMNAME% 是产生日志的程序(如 sshd、nginx、cron)。按这两个维度分目录后,你想看某台机器的 SSH 登录记录,直接 tail /var/log/remote/web01/sshd.log,非常直观。

# 创建目录并重启
mkdir -p /var/log/remote
chown syslog:adm /var/log/remote
systemctl restart rsyslog
systemctl status rsyslog

# 确认在监听
ss -tlnp | grep 5140

第二步:客户端把日志转发出去

业务机上同样加一个配置文件。要点是只转发你关心的日志,不要把所有 debug 级日志都推过去把日志服务器撑爆;同时保留本地落盘,网络中断时本地还有备份。

# /etc/rsyslog.d/50-forward.conf  —— 业务机端
# 转发方式一:传统语法,把所有 auth 和 mail 及指定程序转发
authpriv.*,mail.*    @@LOG-SERVER-IP:5140
*.*;auth,authpriv.none @@LOG-SERVER-IP:5140

# 注意 @@ 表示 TCP,单 @ 表示 UDP,生产别用单 @

更推荐用现代 action 语法,可精确控制队列和重连:

# 现代语法,带磁盘队列防丢
action(
    type="omfwd"
    target="LOG-SERVER-IP"
    port="5140"
    protocol="tcp"
    # 队列:网络断了先把日志存本地磁盘,恢复后补发
    queue.type="LinkedList"
    queue.filename="fwd_queue"
    queue.spoolDirectory="/var/spool/rsyslog"
    queue.maxdiskspace="500m"
    queue.saveonshutdown="on"
    action.resumeRetryCount="-1"
    action.resumeInterval="30"
)

这里的磁盘队列是关键。如果不用队列,网络一抖,这段时间的日志直接丢;配上 queue.type="LinkedList" 和 queue.maxdiskspace,rsyslog 会先把日志写进本地 spool 文件,链路恢复后再发,最多容忍 500MB 的积压。日志服务器计划性维护重启时,这个机制保证不丢数据。

第三步:用 TLS 加密传输,跨公网必须做

纯文本 TCP 传输意味着日志在公网上裸奔,其中可能包含登录失败的用户名、内部 IP、甚至应用里的敏感字段。跨公网或跨机房时,用 TLS 保护。rsyslog 支持基于证书的双向认证,配置和 Nginx 的 TLS 类似,需要 CA、服务器证书、客户端证书。

# 服务端(collector)启用 TLS 接收
# /etc/rsyslog.d/10-remote-tls.conf
module(load="imtcp"
    StreamDriver.Name="gtls"
    StreamDriver.Mode="1"                      # 1=加密
    StreamDriver.Authmode="x509/name"          # 双向证书校验
)
input(type="imtcp" port="6514")

$DefaultNetstreamDriverCAFile /etc/rsyslog.d/certs/ca.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog.d/certs/server-cert.pem
$DefaultNetstreamDriverKeyFile  /etc/rsyslog.d/certs/server-key.pem
# 客户端启用 TLS 发送
# /etc/rsyslog.d/50-forward-tls.conf
action(
    type="omfwd"
    target="LOG-SERVER-IP"
    port="6514"
    protocol="tcp"
    StreamDriver="gtls"
    StreamDriverMode="1"
    StreamDriverAuthMode="x509/name"
    StreamDriverPermittedPeers="logserver.example.com"
    queue.type="LinkedList"
)
$DefaultNetstreamDriverCAFile /etc/rsyslog.d/certs/ca.pem
$DefaultNetstreamDriverCertFile /etc/rsyslog.d/certs/client-cert.pem
$DefaultNetstreamDriverKeyFile  /etc/rsyslog.d/certs/client-key.pem

StreamDriverPermittedPeers 是客户端的"只信任这台服务器"约束,防止日志被转发到假冒的收集端。服务端侧也可以用 StreamDriverPermittedPeers 限制只接受持有合法客户端证书的来源,等于双向锁死。

第四步:日志服务器自身的容量治理

集中日志最现实的敌人是磁盘。十几台机器全量转发,用不了多久 /var/log/remote 就能吃掉几十 GB。必须给日志服务器单独规划 /var/log/remote 的挂载点(或用独立数据盘),并配置轮转与保留策略。

# /etc/logrotate.d/remote-logs
/var/log/remote/*/*.log /var/log/remote/all-*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    # 日志服务器上的文件属主
    create 0640 syslog adm
    # 轮转后通知 rsyslog 重新打开文件,否则会继续往旧句柄写
    postrotate
        /usr/lib/rsyslog/rsyslog-rotate 2>/dev/null || true
    endscript
}

rotate 14 表示保留 14 天,配合 compress 压缩,一台 2GB 内存、40GB 磁盘的 VPS 足够存十几台小站两周的日志。日志服务器最怕的是"日志雪崩":某台机器出故障疯狂刷日志,瞬间打满磁盘。可以在服务端对单个来源做限速:

# 服务端限制单个 imtcp 连接的处理速率
input(type="imtcp" port="5140" rateLimit.interval="5" rateLimit.burst="2000")

第五步:让日志可检索,而不是躺在磁盘上

集中存储只是第一步,出事时能快速查出来才是目的。rsyslog 落盘的是纯文本,用 grep/awk 就能查,配合 journalctl 的本地冗余一起用。给几个高频检索套路:

# 查某时间段内所有机器上的 SSH 登录失败
grep -h "Failed password" /var/log/remote/*/sshd.log | awk '{print $1, $2, $11}'

# 找某个攻击 IP 出现在哪些机器上
grep -rl "203.0.113.66" /var/log/remote/

# 统计今天各机器出现的错误条数(按来源主机汇总)
grep -c "error" /var/log/remote/*/*.log | sort -t: -k2 -nr | head

# 查某台机器最近的内核告警
grep -i "oom\|panic\|segfault" /var/log/remote/web01/kernel.log | tail -20

如果日志量大、想要图形界面,可以在日志服务器上装 GoAccess 分析汇总的 Nginx 日志,或用 Loki+Grafana 做结构化检索。但对个人站长,纯文本 + grep 已经能覆盖 90% 的排障需求,且不增加任何运行时开销和内存占用——这是 rsyslog 方案最大的优势。

rsyslog vs Loki vs vector:怎么选

三者定位不同。rsyslog 是"系统自带、零依赖、纯文本、内存占用几 MB",适合十几台以内、以系统日志和文本日志为主、预算敏感的个人站。Loki 是"标签索引、按时间范围查询、和 Grafana 无缝集成",适合已经有 Prometheus/Grafana 监控栈、想要日志和指标联查的场景,但需要额外部署 Loki 和 Promtail,内存开销更高。vector 是"高性能、可编程转换、Rust 编写",适合日志量大、需要在采集端做字段解析和过滤的场景,配置灵活但心智负担比 rsyslog 高。

务实建议:如果你现在只有基础监控、日志以系统日志和 Web 访问日志为主,直接上 rsyslog 集中采集,别为了"技术先进"引入维护成本更高的栈。等日志量真的涨到 grep 查不动、需要按字段聚合分析时,再迁移到 Loki。rsyslog 转发的内容可以同时被 vector 或 Promtail 读取,迁移路径是平滑的。

常见故障速查

服务端收不到日志:先 ss -tlnp | grep 5140 确认监听;再在客户端 nc -zv 服务器 5140 测连通;然后看两边防火墙是否放行,最后看 journalctl -u rsyslog 有无报错。
日志写到了错误目录:模板里的 %HOSTNAME% 依赖客户端正确设置主机名,若多台机器主机名相同会互相覆盖,务必给每台机器规划唯一 hostname。
网络抖动后丢日志:客户端 action 没配磁盘队列,补上 queue.type="LinkedList" 与 queue.maxdiskspace。
日志服务器磁盘被写满:logrotate 未生效或轮转后 rsyslog 未重新打开文件,检查 postrotate 是否执行了 rsyslog-rotate。

FAQ

Q:日志服务器能不能和业务机共用一台?
A:可以但意义有限——业务机本身挂掉时日志也没了。如果预算只够一台,至少把日志目录挂到独立数据盘上,并在另一台机器做一次日志的定期 rsync 冷备。

Q:客户端转发会不会影响原有本地日志?
A:不会。rsyslog 支持边写本地边转发,转发配置只是新增一路 action,本地 /var/log/ 照常保留。

Q:TLS 证书到期后日志会静默中断吗?
A:会,而且是静默的。务必给 rsyslog 用的证书设置自动续期与到期告警,和网站证书一视同仁地纳入监控。

Last modification:October 1st, 2026 at 10:24 pm

Leave a Comment