3、日志采集技术:日志来源、采集工具与架构设计
聊到日志采集,我脑子里第一个蹦出来的场景,是几年前帮一家金融科技公司做AI风控系统的安全合规审计。那会儿他们模型出了个误判,监管要求提供完整的推理日志。结果呢?日志散落在三台服务器上,格式五花八门,有的连时间戳都没对齐。嗯,那场面,真是让人头大。
所以你看,日志采集这件事,看着简单,其实门道不少。今天我就把这块掰开了讲清楚。
3.1 日志来源:系统、应用、模型
日志从哪来?说白了就三大类:系统层、应用层、模型层。每一层都有自己的脾气。
3.1.1 系统日志
系统日志是基础设施的「体检报告」。我习惯把它分成两类:
- 操作系统日志:比如Linux的
/var/log/messages、/var/log/secure。记录的是谁登录了、什么时候重启了、磁盘有没有报错。 - 容器与编排日志:Docker的
docker logs、K8s的kubectl logs。这些在微服务架构里特别重要。
我记得有一次排查模型训练节点的异常重启,最后就是在/var/log/kern.log里找到了OOM Killer的痕迹。嗯,内存不够用了。
3.1.2 应用日志
应用日志是业务逻辑的「监控摄像头」。常见的包括:
- API访问日志:谁调了哪个接口、参数是什么、返回了什么。
- 业务操作日志:用户做了什么事,比如「用户A修改了模型阈值」。
- 错误日志:异常堆栈、数据库连接失败、超时等。
我个人建议,应用日志一定要带上请求ID和用户ID。为什么?因为出问题的时候,你要能串起一条完整的调用链。我在项目中遇到过,没有请求ID,排查一个线上问题花了整整两天——后来加了ID,半小时定位。
3.1.3 模型日志
这是AI安全合规里最特殊的一层。模型日志记录的是「模型在想什么」。具体包括:
| 日志类型 | 记录内容 | 合规用途 |
|---|---|---|
| 推理日志 | 输入特征、模型版本、输出结果、置信度 | 可解释性审计 |
| 训练日志 | 训练数据来源、超参数、loss曲线 | 数据溯源 |
| 漂移日志 | 特征分布变化、预测偏差 | 模型监控 |
| 反馈日志 | 用户对模型输出的反馈(点赞/踩) | 持续改进 |
3.2 采集工具:Filebeat 与 Fluentd
工具选型这块,我踩过不少坑。目前用得最多的两个,一个是Filebeat,一个是Fluentd。它们各有千秋。
3.2.1 Filebeat
Filebeat是Elastic生态里的轻量级采集器。它的特点就一个字:轻。
- 资源占用极低:我测试过,采集10MB/s的日志流,CPU占用不到5%。
- 配置简单:一个YAML文件搞定。
- 原生支持Elasticsearch:如果你用ELK栈,Filebeat是首选。
来个简单的配置示例:
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/model-inference/*.log
fields:
log_type: model_inference
environment: production
output.elasticsearch:
hosts: ["http://elasticsearch:9200"]
index: "model-logs-%{+yyyy.MM.dd}"
你看,就这么几行,就能把模型推理日志采集到ES里。不过要注意,Filebeat对日志的解析能力有限。它只管采集和转发,复杂的日志解析得靠Logstash。
3.2.2 Fluentd
Fluentd就不一样了。它更像一个「日志路由器」。我习惯用它来做统一采集和预处理。
- 插件生态丰富:输入、输出、过滤,什么插件都有。
- 内置解析能力:支持JSON、正则、CSV等多种格式。
- 缓冲机制可靠:网络断了不会丢日志。
举个例子,假设你的模型日志是JSON格式,但需要脱敏后再发送:
<source>
@type tail
path /var/log/model-inference/*.log
format json
tag model.inference
</source>
<filter model.inference>
@type record_transformer
<record>
user_id ${record["user_id"].gsub(/.(?=.{4})/, "*")}
</record>
</filter>
<match model.inference>
@type elasticsearch
host elasticsearch
port 9200
logstash_format true
</match>
3.3 采集架构设计
架构设计这块,我总结了一个原则:分层采集,统一汇聚。说白了,就是每个节点只负责采集自己的日志,然后统一发到中心。
3.3.1 常见架构模式
我见过三种主流架构:
- 直连式:采集器直接写入存储。简单,但耦合度高。
- 代理式:采集器发给消息队列(Kafka),再由消费端写入存储。解耦,但多了个组件。
- 边车式:每个Pod里跑一个采集器。适合K8s环境。
我个人最推荐的是代理式。为什么?因为AI安全合规要求日志不能丢。Kafka的持久化机制能保证这一点。我曾经遇到过,直连式架构下ES集群挂了,日志直接丢了两个小时——从那以后,我再也不敢不用消息队列了。
3.3.2 一个实战架构
给你看看我现在用的架构:
+----------------+ +--------+ +-----------+ +----------------+
| 模型推理节点 | | | | | | |
| Filebeat采集 |---->| Kafka |---->| Fluentd |---->| Elasticsearch |
| 系统/应用/模型 | | | | 解析/过滤 | | 存储/检索 |
+----------------+ +--------+ +-----------+ +----------------+
|
v
+----------------+
| 合规审计平台 |
| 告警/可视化 |
+----------------+
这个架构的好处是:
- 解耦:采集和存储互不影响。
- 可扩展:加节点只需要部署Filebeat。
- 高可用:Kafka挂了,日志不会丢。
log.retention.hours是168小时(7天),但合规要求日志保留180天。结果呢?审计的时候发现日志已经被删了。所以,一定要根据合规要求调整Kafka的保留策略。
3.3.3 采集策略
最后说说采集策略。不是所有日志都要实时采集。我习惯分三级:
| 优先级 | 日志类型 | 采集频率 | 说明 |
|---|---|---|---|
| P0 | 模型推理日志、安全告警日志 | 实时 | 影响合规和安全的,一秒都不能等 |
| P1 | API访问日志、业务操作日志 | 近实时(1分钟内) | 用于监控和排查 |
| P2 | 系统性能日志、调试日志 | 批量(每小时) | 用于容量规划和事后分析 |
你想想看,如果所有日志都实时采集,带宽和存储根本扛不住。所以,分级采集是必须的。
嗯,日志采集这块就聊到这儿。说白了,就是搞清楚「采什么、用什么采、怎么采」。下一章我们聊聊日志存储和索引,那又是另一番天地了。