Logi-AM脱胎于滴滴内部多年的Agent运营实践经验,是面向Agent用户、Agent运维人员打造的Agent一站式采集平台。专注于日志采集、Agent运维管控、资源治理等核心场景,经历数年、各核心业务场景、超大规模Agent集群、海量数据的考验。
滴滴内部统一使用 Logi-Agent 作为日志采集器,当前滴滴共有100k+的Agent,20k+采集任务,每天万亿/PB级的日志采集量,单Agent线上最大持续采集流量达50mb+/s;Agent用户需要完成采集任务创建下发、指标查看等操作;运维人员还有大量Agent集群运维操作。因此我们需要构建一个Agent管控平台来承载这些需求。
在Logi-AM建设的初期,我们调研了社区同类产品的使用情况,在调研中发现,外部同类产品无论在采集可靠性、采集性能、数据完整性、数据采集有序性、采集任务级的租户隔离能力、监控指标的完善程度、运维管控的能力亦或是使用的体验上都无法很好的满足我们的需求,因此自建滴滴 Logi-AM 平台势在必行。
免费体验地址:http://116.85.23.35/agent。
在 Logi-AM 建设初期,我们对之前所面临的问题和需求进行了归纳分析,主要有如下方面:
-
高可靠
在持续的超大流量采集情况下如何确保稳定、可靠的数据采集,这是采集器首要解决的问题。
-
高性能
滴滴有部分场景日志量特别大,单机每秒持续产生待采集日志达50mb+,且需要保证高实时性。如何确保这些日志能被及时的采集上来,这就要求采集器的采集性能必须远超50mb+/s,并具备可持续性。
-
数据完整性
滴滴有部分场景日志用于财会、结算,这对数据完整性提出了极高的要求,Agent需要确保任意极端情况下的数据完整性。
-
数据有序性
滴滴有非常多的指标计算场景,但在计算某个指标前,需要确保计算这个指标所需的日志数据在某个时间点前是否已被Agent采集完?回答这个问题,需要两个前提条件:
- 用户打印日志需要按时序顺序打印,不可乱序
- 采集器采集日志时须按照用户打印顺序进行按序采集并输出到下游
因此,确保日志按打印顺序被Agent采集上来并输出到下游的能力,是采集器必须要做到的。
-
采集任务级的租户隔离
滴滴很多业务是混部的,同一台主机上,部署的不同业务的日志保障等级也不一样,这需要Agent具备采集任务级的租户隔离能力。
-
监控指标的完善程度
滴滴线上有100k+的Agent在7x24小时运行,覆盖所有的业务线,这给运维带来了极大的挑战。如何做到隐患及时感知、问题易于定位,这需要将Agent的运行过程数据化、指标化,这也是Agent智能运维的基础,如何将Agent运行过程数据化,如何定义黄金指标,这也是Agent监控指标体系构建的关键。
-
可靠性
滴滴内部Agent-Manager平台需要管控的Agent多达100k+、采集任务多达20k+,所有Agent每隔30秒会向Agent-Manager平台拉取一次采集配置,Agent-Manager平台需要周期性的对所管控的全量Agent与采集任务做健康度巡检、诊断,这种情况下如何确保Agent-Manager平台的稳定、可靠?这是Agent-Manager平台首要解决的问题。
-
可扩展性
可扩展性分为两种:
- 性能层面的水平扩展性:Agent-Manager必须具备良好的水平扩展性,以管控越来越大的Agent与采集任务规模。
- 代码实现层面的可扩展性:高内聚、低耦合、接口清晰、开放式API,这是Agent-Manager开源生命力的保证。
-
Agent运维便捷性、专家性
海量的Agent、采集任务给运维带来了极大的挑战,挑战主要来自两个方面:
- 在日常的运维中,会存在着大批量Agent运维操作(批量安装、升级、卸载),如:大批量Agent升级操作是一个危险且工作量极大的工作,如何引导用户进行灰度升级?升级失败如何引导用户查看失败原因进行排障并进行回滚?这也是Agent-Manager需要解决的问题。
- Agent-Manager如何定义全面、专业的Agent、采集任务指标看板?Agent-Manager如何做到事前感知可能存在健康隐患的Agent、采集任务?对于出现故障的Agent、采集任务,Agent-Manager如何快速诊断、定位故障点,并提供友好、便捷的人机交互界面,辅助运维人员快速解决故障?
-
云原生的支持
面向云原生的场景,如何通过接入的k8s元数据构建起“主机-容器-服务”三者之间的关系?如何让用户在Agent-Manager平台上针对容器方便的配置基于服务的日志采集?如何规范云原生日志的存储?如何在容器漂移的场景下,确保容器漂移后,漂移前生成的日志被可靠的采集完并正确下线针对漂移容器的采集任务?这是Agent-Manager平台必须具备的能力。
-
用户使用友好性
采集任务的配置是一个耗时费力的过程,如何减轻用户配置工作量,如何让用户配完后所见即所得?这个也是需要去重点考虑。
Logi-AM 整体架构如下:
Logi-AM 外部依赖组件有 3 个:
- MySQL:用于存储 Agent-Manager 元数据,Agent上报的指标、错误日志数据。
- Kafka:作为采集的日志数据,以及Agent上报的指标、错误日志数据的消息总线。
- 夜莺平台:非必须依赖,用于执行Agent-Manager下发的Agent安装、升级、卸载指令,Agent-Manager支持通过API方式扩展其他第三方自动化部署平台。
精简的依赖使得Agent-Manager在具备管控大规模Agent能力的同时兼顾易部署的特性。
Agent 有三个数据流:
- 日志数据流:用于将采集的日志数据上报至Kafka。
- 指标数据流:用于将Agent、采集任务运行指标上报至Kafka。
- 错误日志数据流:用于将Agent错误日志上报至Kafka。
Agent-Manager 启动后会持续消费Agent指标流、错误日志流对应Topic,然后将指标、错误日志数据根据配置写入对应存储(默认存储为MySQL,存储类型支持:MySQL、Elasticsearch,并支持通过API方式扩展其他存储),Agent-Manager 将根据这些数据对所管控的Agent、采集任务进行健康度巡检、故障诊断,以及指标展示。
概念释义:
- 文件组:一个文件组对应一个业务域,由一个指向文件的路径、以及规定文件名后缀的规则进行定义,示例如下:
- 文件路径:/home/logs/info.log
- 文件名后缀:.*
- Log2KafkaTask:表示一个日志文件采集任务,用于采集一个文件组对应的文件集,一个Log2KafkaTask仅对应一个文件组,一个Log2KafkaTask包括如下三种类型的组件:
- Source:用于按行读取日志并根据配置日志切片规则对日志进行切片成一个一个Event,存入Channel,一个Log2KafkaTask仅包含一个 Source。
- Channel:用于存储Source组件采集到的一个个Event,一个Channel仅对应一个Source。
- Sink:内置Kafka Producer,用于消费Channel中的Event,并将其发送至Kafka,以一个Channel可对应一个或多个Sink。
可以看到Agent采用的串行、条带化的日志采集方式,以文件组为隔离单位,进行日志采集。之所以采用串行化采集,主要原因有如下3点优势:
- 容易实现多个采集任务的租户隔离
- 运维复杂度低、问题定位效率高
- 可提升单个线程的采集效率,减少锁带来的性能开销
串行化也会带来如下弊端:
- 采集任务多,采集线程多,采集任务无法无限扩展
- 采集任务配置较多的情况下,资源难以控制
根据滴滴内部100k+个Agent在各场景的实践来看,单个Agent上文件组总数90分位不超过100个文件组,最多不超过200个文件组,百级规模的文件组,Agent完全可以承载,综上,权衡利弊以后,遂采用串行化方式实现Agent。
Agent的系统资源消耗主要体现为CPU、内存、FD消耗。
- CPU资源:Agent支持CPU使用量限制,通过限流的方式实现对Agent CPU使用量的限制。
- 内存资源:Agent的内存耗费与待采集的文件组数量相关,一个文件组对应的采集任务在极端情况下所耗费的最大内存使用量可量化出来,Agent通过对待采集文件组个数的管控实现对内存资源的精细化管控。 Source -> Channel -> Sink 任意组件出现故障,都会反压其上游组件,如下游Kafka出现故障导致数据无法被写入,此时,Sink将停止消费Channel中的数据,并不断重试发送下游Kafka,Channel将会被Source采集的数据填满,Channel填满后,Source将停止采集,以保证Agent的持续稳定运行。
- FD资源:类似内存资源,Agent的FD耗费主要也与待采集的文件组数量相关,一个文件组对应的采集任务在极端情况下所耗费的最大FD使用量可量化出来,Agent通过对待采集文件组个数的管控实现对FD资源的管控。
Agent有线程实时监控自身耗费的CPU、内存、FD使用量,超过预设警戒水位后,将会自爆以保证不影响宿主机其他业务进程。
性能体现在两个方面:
- 文件变更的感知速度:对于待采集文件特别多的场景,感知文件变更是一个资源 & 耗时消耗较多的动作,Agent采用
inotify + 轮询
的方式确保感知文件变更的及时性并减少资源消耗。 - 文件内容的采集速度:Agent单个采集任务的极限采集速率可达200MB/每秒,之所以能达到这个采集速率,得益于Agent良好的线程模型设计与借助CPU的SIMD指令得以充分发挥CPU的能力。Agent性能体现在一个个采集任务上,对于一个采集任务,由于其Sink组件可配置多个进行并发发送,不是性能瓶颈,性能瓶颈在Source组件上,通过分析,发现Source组件瓶颈点在按行读取上,通过借助CPU的SIMD指令,大幅提升按行读取性能,感兴趣的同学请位移《向量化计算加速LogAgent采集》。
影响数据完整性的原因主要有两种:
-
Agent层面问题,如:
-
inode复用问题:Agent通过采用
dev+inode+offset+文件头定长内容hash
来标定每一个文件来解决。 -
sink异步发送失败或发送过程中宕机问题:Agent通过在维护channel级、sink级的
fd-offset
信息以事务提交/回滚的方式进行解决,在确保数据完整性的同时保证采集的超高性能,即使在发送过程中Agent异常宕机,也可确保待采集数据at-least-once
完整性。 -
Agent异常宕机时带来的元数据完整性挑战:对于元数据,Agent采用定时刷盘策略,借助linux内核提供的原子命令rename,先将内存中缓存的元数据先刷盘至临时文件,然后将临时文件名进行变更,在确保元数据文件的可靠性的同时,确保待采集数据t
at-least-once
完整性。对于如何确保超高采集性能下的
at-least-once
完整性感兴趣的同学请位移《LogAgent如何实现超高性能下的at-least-once完整性》。
-
-
使用配置层面问题,如:
- 日志采集路径配置错误
- 日志切片规则配置错误
- 单条日志过长超限
- 日志乱序打印
- jvm内存参数配置不合理
- Agent 限流阈值配置不合理
对于上述问题,Agent将通过指标上报的方式,Agent-Manager平台基于Agent上报的指标数据实时计算各Agent、采集任务的健康度,并对非健康状态的Agent、采集任务进行问题诊断,找到根因,并通知Agent运维人员进行配置变更修复。
Agent对于每个待采集的文件组,由独立的pipeline按日志打印的时间顺序进行采集。对于部分场景要求消费端程序消费顺序与日志打印顺序严格一致的场景,可通过设置文件组 - key
一一对应的方式,满足下游(如:kafka)消费端程序消费顺序与日志打印顺序严格一致的需求。
Agent具备系统层、网络层、业务层三位一体全方位指标,系统层、网络层指标涵盖系统级、进程级。以Agent设计架构为基础,结合滴滴超大规模Agent运维场景的经验,以排障为目标、以终为始,抽象出一系列黄金指标,减少理解成本、降低使用门槛,方便使用者透视Agent运行过程、发现Agent运行风险,快速定位Agent运行问题。
-
可靠性
Agent-Manager在可靠性层面面临的压力主要来自于如下3个方面:
- 海量Agent采集配置拉取:滴滴内部Agent-Manager平台需要管控的Agent多达100k+,采集任务多达20k+,所有Agent每隔30秒会向Agent-Manager平台拉取一次采集配置,通过对Agent-Manager配置拉取接口的流程进行拆解、优化,单Agent-Manager实例可支撑现100k+Agent、20k+采集任务的配置拉取。
- 海量Agent、采集任务健康度巡检:Agent、采集任务健康度巡检是个比较耗时的动作,Agent-Manager通过多线程并发的手段进行提速,多个巡检线程间通过自动协商、确定好各自巡检的Agent、采集任务边界范围实现巡检任务的自动负载均衡,单Agent-Manager实例可支撑100k+Agent、20k+采集任务、10分钟每次的健康度巡检。
- 海量Agent指标、错误日志数据ETL:Agent-Manager通过多线程并发的手段进行ETL提速,单Agent-Manager实例可支撑100k+Agent、20k+采集任务的指标、错误日志数据秒级清洗、入库。
-
可扩展性
- 性能层面的水平扩展性:
- Agent采集配置拉取:仅需通过增加部署的Agent-manager实例个数与MySQL读库的个数即可成倍扩充配置拉取的负载能力,最高可支撑至千万级Agent的采集任务配置拉取。
- 海量Agent、采集任务健康度巡检:仅需通过增加部署的Agent-manager实例个数即可支撑成倍扩充的Agent、采集任务健康度巡检任务规模,以支撑更大规模的Agent、采集任务的健康度巡检能力。
- 海量Agent指标、错误日志数据ETL:仅需通过增加部署的Agent-manager实例个数即可支撑成倍扩充的Agent指标、Agent错误日志数据规模,以支撑更大规模的Agent指标、错误日志数据的ETL吞吐能力。需要注意的是,Agent-Manager扩充的最大实例个数须小于等于存放Agent指标、错误日志信息的kafka topic对应分区数。
- 代码实现层面的可扩展性:
- Agent-Manager具备清晰的项目结构、接口定义以及开放式API,代码层面实现层面遵循高内聚低耦合,使得Agent-Manager易于根据个性化需求进行功能扩展、二次开发。
- 性能层面的水平扩展性:
-
Agent运维便捷性、专家性
-
Agent运维便捷性
Agent-Manager抽象了一整套关于批量Agent的安装、卸载、升级操作以及这些操作对应的日志查看接口,并默认支持夜莺系统的集成,借助夜莺的能力完整实现这些功能(也支持用户根据自身实际情况实现对应接口以替换夜莺的实现),将滴滴内部多年沉淀的经验(诸如:灰度发布、升级失败安全回滚等功能)直接产品化。
-
Agent运维专家性
Agent-Manager将滴滴多年积累的海量Agent、采集任务场景下的运维经验进行抽象、流程化,并直接产品在Agent-Manager中,通过Agent、采集任务健康度巡检、问题诊断功能的形式加以体现,以大幅提运维效能。
对于Agent-Manager如何对Agent、采集任务进行健康度巡检、诊断感兴趣的同学请位移《Agent、采集任务的健康度巡检与诊断》。
-
-
云原生的支持
Agent-Manager支持对接原生k8s,通过pod模板预定义的方式,实现k8s元数据与Agent-Manager元数据的映射、互通,规范云原生日志存储的方式,自动解析、识别
服务-主机-容器
实体及其相互间的关联关系,容器内路径到宿主机路径的映射。对于容器漂移场景,Agent-Manager通过Agent上报的指标监控漂移前所产生的日志是否被采集完,确保漂移前容器生成的日志被可靠的采集完并及时、正确下线针对漂移容器的采集任务以释放对应资源。 -
用户使用友好性
Agent-Manager对于采集任务的配置,做了专门的优化,精简配置参数,即时预览,让用户配的快、配的稳。
Agent-Manager在社区没有可参考对象,此处拿Agent作为同类对比载体:
维度 | Flume | FileBeat | Logi-Agent |
---|---|---|---|
可靠性 | 一般 | 一般 | 高可靠 |
采集性能 | Mb级 | 十Mb级 | 百Mb级 |
数据完整性 | 无法确保数据完整性 | 无法确保数据完整性 | 可确保数据完整性 |
采集任务级的租户隔离 | 无法做到采集任务级的租户隔离 | 无法做到采集任务级的租户隔离 | 可做到采集任务级的租户隔离 |
监控指标的完善程度 | 较少指标 | 较少指标 | 指标丰富 |
资源消耗 | 高 | 低 | CPU消耗与FileBeat趋近(大采集量场景下CPU消耗较FileBeat更小),内存消耗较FileBeat略大(但在一个数量级上) |
未来我们会在以下几个方面对Logi-AM进行持续改进:
Agent侧
- 更高采集性能
- 支持更多的序列化协议
- 更丰富的监控指标
Agent-Manager侧
- 更好的采集任务配置体验
- 更优秀的可视化体验
- 更智能的故障预警、问题诊断
- 更丰富的内置场景化配置
持续回馈开源社区
作为在滴滴内部经过多年的大量复杂、核心场景验证过的采集引擎、管控平台,我们会持续对其进行核心业务抽象,剥离滴滴内部依赖,回馈社区,我们也希望热心的社区同学和我们交流想法,共同提升Logi-AM的功能和体验。