我们这套环境一共12台机器,最早是几台Web加两台数据库,再后来业务拆开,机器越加越多。到后面出了个故障,最难受的不是机器坏了,而是"日志找不着"。同一个时间点的报错,可能出现在前端Nginx、应用层、业务中间件、日志服务这几套系统里,我得一台台SSH上去,先 `tail` 再 `grep`,来回切七八个终端窗口,一个下午就过去了,还经常漏掉某一台。后来我把这12台机器的日志用Filebeat统一收集到Elasticsearch,再配上Kibana做检索,同样的故障,现在基本5分钟能定位到具体那台机器、那个时间点、那行报错。这篇就把整个落地过程、我踩过的坑和几个容易配错的地方写下来,服务器运维的朋友可以直接抄作业。
要搭集中日志采集,采集端和存储端的机器得先备好,别等日志量涨上来才发现扛不住,这两家可以重点看看:Zenlayer(全球多地区节点,日志中转和归档都能挑机房)、狗云DOGYUN(高性价比云服务器,做日志存储节点够用)。日志采集本身不挑机器,真正吃资源的是后面的存储和检索,先把存储节点的盘和带宽算清楚,比调采集参数管用得多。

一、先想清楚:到底要解决什么问题
动手装之前我把需求写了下来,就三条:一是故障时能按时间点和关键字跨机器搜;二是不能影响生产机器本身的性能;三是历史日志要留一段时间,别刚清完就出事故。前两条决定采集方式,第三条决定存储量和磁盘预算。
第一条是最容易被做复杂的地方。有人一上来就想做"全业务日志平台",要接Kafka、要接ClickHouse、要上日志脱敏规则,做了两个月没上线。我的做法是先跑通最小闭环:一台采集机装Filebeat,扫三四台业务机的日志目录,直发Elasticsearch,Kibana能搜到就完事。这个闭环跑通、验证了性能影响之后,再一条条加机器。这中间的差别是,两周能上线还是两个月能上线。
另外有一点要先想清楚:日志里什么都有。用户请求里带的参数、偶尔打印出来的手机号、内部服务的IP,这些原样收上去,等于给自己埋雷。真要长期跑,一定要在采集侧做一层过滤和脱敏,别指望以后再补。

二、采集端的配置:这几个参数配错就白干
Filebeat 的核心配置就一个 `filebeat.inputs`,类型选 `filestream`(老版本的 `log` 输入在新版里已经被标记为废弃,新装的话直接用 filestream)。这里有几个点是我实际踩过的。
第一是 `paths` 的通配符要够狠。我最初只配了 `/var/log/nginx/*.log`,结果应用自己写的日志在 `/data/app/logs/` 下面,完全没收到。后来改成 `/data/app/logs/*.log*`,带星号把轮转出来的历史文件也带上,这个漏采的问题才解决。注意 `*` 匹配的是同目录下的文件,多层目录要用更宽的写法。
第二是 `exclude_lines` 别偷懒。像 `#logins-guide` 这种调试注释行,直接加进排除列表,能省下一大块无意义的存储和索引开销。我第一版没配,索引里 40% 的文档是这玩意儿,白占空间。
第三是 采集端的内存和磁盘要给够。Filebeat 自己也要写队列文件(`queue.disk`),如果日志产生的速度超过它发送的速度,队列会堆在磁盘上。我有一台机器日志写入特别频繁,queue 堆到 8GB 还没发出去,后来把 `queue.disk.max_size` 调到 5GB 上限,超了就丢弃最旧的,配合采集端日志保留策略,磁盘才稳下来。
第四个坑最隐蔽:Filebeat 的服务账号要有读权限。日志目录属主如果是 root,Filebeat 用普通用户跑,启动不报错,但日志一条也收不到,因为它把读取失败当成文件暂时不可读,一直重试。这个现象是"启动了但没数据",很多人会去怀疑网络和端口,其实就是权限。我是把采集目录的组改成日志属组,再给服务账号加组权限解决的。

三、存储端:ES 的几个参数直接决定你能留多久
Elasticsearch 这边我没做复杂架构,就是单节点加几个数据节点,日志按天滚动索引。这种做法的好处是排查时可以直接按日期过滤,坏处是节点挂了会有一段时间查不了。日志检索对实时性要求没那么高,偶尔延迟几分钟完全可以接受。
几个关键参数我直接列出来,都是我调过的:
`index.lifecycle.ilm` 设成滚动模式,热节点保留7天,之后转温节点再转冷节点,冷节点可以放到便宜的大容量盘上。这个策略配好之后,存储成本比全放热节点低一大截。
`cluster.routing.allocation.disk.watermark` 默认是85%和90%,我调成了90%和95%。日志数据可压缩性很好,到85%就开始不分配副本是很激进的,容易出现副本节点红着、数据写不进去的情况。
单索引主分片数我定的是3,日志量大可以往上加,但别一上来就设成几十个。小分片会吃掉堆内存里的数据量,反而让查询变慢。
还有一个特别容易踩的:磁盘打满之后 ES 会进入 read-only 状态,这时候新日志写不进去,堆积在采集端队列里,等磁盘释放后一次性灌进来,很容易把机器再打满一次。我的做法是给 ES 节点挂了一块独立的数据盘,并且配了磁盘使用率告警,超过 75% 就有人工介入。日志系统自己把磁盘撑爆,是很讽刺的一件事。

四、检索:字段和索引模板决定你搜得爽不爽
日志收上来了,能不能用起来全看字段和映射。我一开始把所有日志用默认的动态映射塞进去,结果字段类型乱得离谱:同一个字段,有时候是 string 有时候是 long,ES 直接报冲突,索引写不进去。解决办法是给日志加一个固定前缀,比如 `app_` 开头,然后用 index template 提前把字段类型定死,日期字段直接指定成 date 类型。
时间字段千万别用默认的 `@timestamp` 就完事,得明确成 `date` 类型并且指定格式,不然跨时区或者夏令时的时候排序会错位。我见过凌晨查数据结果顺序错乱的,就是这个原因。
另外强烈建议给日志加上 `hostname`、`service`、`env` 这几个元数据字段。排查的时候按服务名和环境过滤,比全文搜索快一个量级。这一点在日志量到千万级之后差别特别明显。

五、现在一次故障的排查流程
说点实际的。上周一个下午,客服反馈下单接口大面积超时,我打开 Kibana,先按服务名过滤出 `order-service`,时间范围卡在那 10 分钟,然后关键字搜 `timeout`,几百条日志刷出来。再点开其中一条,看它的 `traceId`,用它去全局搜同一次请求的全部日志,链路就出来了原来是数据库连接池打满,等待队列超时。整个过程从接到反馈到找到原因,不到5分钟。
而半年前同样类型的故障,我是SSH上12台机器,一台台 `grep`,光翻日志就花了二十多分钟,最后还漏了一台机器,白白重来一次。这就是集中采集最实在的价值:它不是让日志更好看,是把"翻日志"这个动作从体力活变成了一个查询。
六、如果暂时不想上Filebeat
不是所有环境都值得上这一套。机器只有两三台、日志量很小的时候,用 `journalctl` 加 `grep` 加个定时脚本同步到一台机器,其实也够用了,没必要为了一个查询搞出一整套栈。
如果机器比较多但不想自己维护ES,也可以考虑用云厂商提供的日志服务(阿里云SLS、腾讯云CLS这类),采集端也是走Filebeat或对应Agent,上传这块省心,代价是数据要出网、有按量计费的成本,而且深度查询的自定义能力不如自己搭。数据敏感、或者日志量特别大的场景,我更倾向于自建。
写在最后
日志集中采集这件事,值不值得做,取决于你的机器数量和排查频率。两三台机器,不做也行;十几台机器、天天有人在上面排查,那这套东西基本是必需品。
如果刚开始,我建议按这个顺序走:先在两三台低风险机器上试跑 Filebeat,确认对生产性能没影响,再上存储端,最后再铺开到全部机器。中间一定要盯住采集端的 CPU 占用和队列堆积这两个指标,它们是"会不会拖慢线上"的直接信号。我自己是先在一台跑着看了三天,确认稳了才铺开的。
工具本身不复杂,坑主要在配置细节和容量预估上。把上面提到的权限、磁盘水位、字段映射这三块吃透,剩下的就是照着配了。


喜欢
顶
难过
囧
围观
无聊



