2、日志采集体系:从标准化到高可用架构

日志采集,听起来好像就是把日志从A点搬到B点。但做过生产环境的人都知道,这里面的坑,一个比一个深。我刚开始搞PaaS平台那会儿,就被日志搞崩过好几次。今天咱们就聊聊,怎么把日志采集这件事,做得既稳当又高效。

2.1 日志标准化设计:别让脏数据毁了你的分析

你想想看,如果每个应用都按自己的喜好写日志,有的用JSON,有的用纯文本,有的时间戳格式还不一样。那后面的日志分析、告警、排障,基本就是一场灾难。

我个人的习惯是,在日志采集的源头就做标准化。 说白了,就是定一套规矩,所有应用都得遵守。

2.1.1 标准字段定义

一个标准的日志条目,至少应该包含这些字段:

字段名 类型 说明 示例
@timestamp datetime 日志产生时间,ISO8601格式 2025-01-15T10:30:00.123Z
level string 日志级别 INFO / WARN / ERROR
logger string 产生日志的类或模块名 com.example.UserService
message string 日志正文 用户登录成功,userId=12345
trace_id string 分布式链路追踪ID abc123def456
service string 服务名称 user-service
instance string 实例ID或IP 10.0.1.5:8080
我的小技巧: 在应用层就输出JSON格式的日志。这样采集端不需要做复杂的解析,性能更好,也避免了解析出错的问题。

2.1.2 日志格式规范

我建议统一使用JSON格式。为什么?因为JSON是自描述的,解析起来简单,扩展性也好。举个例子:

{
  "@timestamp": "2025-01-15T10:30:00.123Z",
  "level": "ERROR",
  "logger": "com.example.OrderService",
  "message": "订单支付超时",
  "trace_id": "abc123def456",
  "service": "order-service",
  "instance": "10.0.1.10:8080",
  "extra": {
    "order_id": "ORD20250115001",
    "amount": 299.00,
    "payment_method": "wechat"
  }
}
注意: 日志里不要包含敏感信息,比如密码、身份证号、银行卡号。我曾经见过一个项目,因为日志里打印了用户的明文密码,结果被安全团队通报了。嗯,那场面挺尴尬的。

2.2 Filebeat / Logstash / Fluentd 选型对比

选型这件事,没有绝对的好坏,只有合不合适。我这些年三个工具都用过,说说我的感受。

特性 Filebeat Logstash Fluentd
定位 轻量级采集器 重量级处理管道 统一日志层
资源占用 极低(10MB左右) 较高(Java,吃内存) 中等(Ruby/C)
处理能力 弱,仅采集和简单转发 强,支持复杂过滤和转换 中等,插件丰富
适用场景 边缘节点采集 中心化处理 Kubernetes环境
社区生态 ELK全家桶,成熟 ELK全家桶,成熟 CNCF项目,云原生友好

我个人习惯的搭配是:

  • 边缘节点用 Filebeat:因为它够轻,几乎不占资源。我在一个2000+节点的集群里,每台机器都部署了Filebeat,CPU和内存占用几乎可以忽略不计。
  • 中心处理用 Logstash:当需要对日志做复杂的解析、过滤、脱敏时,Logstash的插件生态是最全的。比如从日志里提取IP、解析User-Agent、做GeoIP地理定位,Logstash一把梭。
  • Kubernetes环境用 Fluentd:Fluentd对K8s的支持最好,可以自动采集Pod日志,还能通过标签做路由。如果你在用EFK(Elasticsearch + Fluentd + Kibana)栈,Fluentd是首选。

避坑指南: 我曾经在一个项目里,直接用Logstash做边缘采集。结果呢?每台机器上Logstash吃掉500MB内存,集群规模一大,内存直接爆了。后来全部换成Filebeat,问题迎刃而解。所以记住:边缘采集用轻量级工具,中心处理用重量级工具。

2.3 Kafka在日志链路中的缓冲作用

为什么要在日志链路里加Kafka?说白了,就是为了解耦和削峰。

你想想看,如果日志采集器直接往Elasticsearch写数据,一旦ES集群压力大、写入变慢,采集器就会被阻塞。严重的时候,采集器会挂掉,日志就丢了。

Kafka在这里扮演的角色,就是一个巨大的缓冲池。

2.3.1 典型架构

应用日志 -> Filebeat -> Kafka -> Logstash -> Elasticsearch

这个架构的好处是:

  • 解耦:采集端和处理端互不影响。Filebeat只管往Kafka写,Logstash只管从Kafka读。
  • 削峰填谷:业务高峰期日志量暴增,Kafka可以扛住百万级TPS的写入。等低谷期,Logstash再慢慢消费。
  • 数据持久化:Kafka的消息是持久化到磁盘的。就算Logstash挂了,数据也不会丢。等它恢复后,从上次的offset继续消费就行。
我的经验: Kafka的Topic分区数,建议设置为Logstash消费者线程数的整数倍。比如你有4个Logstash实例,每个实例开2个消费线程,那分区数可以设为8或16。这样能保证每个分区都被均匀消费,不会出现数据倾斜。

2.3.2 配置示例

Filebeat输出到Kafka的配置:

output.kafka:
  hosts: ["kafka1:9092", "kafka2:9092", "kafka3:9092"]
  topic: "app-logs"
  partition.round_robin:
    reachable_only: true
  required_acks: 1
  compression: gzip
  max_message_bytes: 1000000

Logstash从Kafka消费的配置:

input {
  kafka {
    bootstrap_servers => "kafka1:9092,kafka2:9092,kafka3:9092"
    topics => ["app-logs"]
    group_id => "logstash-group"
    consumer_threads => 4
    auto_offset_reset => "latest"
    codec => "json"
  }
}
注意: 如果日志量特别大,记得开启Kafka的压缩功能(比如gzip或snappy)。我见过一个场景,没开压缩时,Kafka的磁盘IO直接打满。开了gzip压缩后,磁盘使用率下降了70%。效果立竿见影。

2.4 日志采集高可用架构

日志采集的高可用,说白了就是:任何一个组件挂了,日志都不能丢。

我建议采用多级冗余的架构:

2.4.1 采集端高可用

  • Filebeat多输出:配置多个Kafka集群作为输出。如果主集群挂了,自动切换到备集群。
  • 本地缓存:Filebeat支持将未发送成功的日志缓存到本地磁盘。等网络恢复后,自动重发。
output.kafka:
  hosts: ["kafka-primary:9092", "kafka-secondary:9092"]
  topic: "app-logs"
  # 开启本地缓存
  queue.mem.events: 4096
  queue.mem.flush.min_events: 512

2.4.2 传输层高可用

  • Kafka集群:至少3个Broker,副本因子设为3。这样任何一个Broker挂了,数据都不会丢。
  • 多数据中心:如果条件允许,可以跨机房部署Kafka集群。一个机房挂了,另一个机房还能继续服务。

2.4.3 处理端高可用

  • Logstash多实例:部署多个Logstash实例,组成消费者组。Kafka会自动做负载均衡。
  • ES集群:Elasticsearch本身就有高可用机制,分片和副本可以保证数据不丢。

我曾经踩过的坑: 有一次Kafka集群的磁盘满了,导致所有日志都写不进去。Filebeat重试了几次后,本地缓存也满了,就开始丢日志。后来我加了一个监控:当Kafka的磁盘使用率超过80%时,自动告警并扩容。从那以后,再也没出过类似问题。

2.4.4 整体架构图(文字描述)

应用实例1 -> Filebeat -> Kafka集群 (3节点, 副本3) -> Logstash集群 (4实例) -> ES集群 (3节点)
应用实例2 -> Filebeat -> Kafka集群 (3节点, 副本3) -> Logstash集群 (4实例) -> ES集群 (3节点)
应用实例3 -> Filebeat -> Kafka集群 (3节点, 副本3) -> Logstash集群 (4实例) -> ES集群 (3节点)
                                |
                          监控告警 (磁盘、吞吐量、延迟)

这个架构里,任何一个单点挂了,都不会影响整体日志采集。Filebeat有本地缓存,Kafka有副本,Logstash有消费者组,ES有分片副本。嗯,这才是生产级别的日志采集体系。


好了,日志采集这部分就聊到这儿。下一章咱们聊聊日志存储和检索,那又是另一番天地了。

公众号:蓝海资料掘金营,微信deep3321