日志服务架构设计

最近想把之前做过的日志项目及个人的思考梳理一下,于是有了本文 。
背景我们这边应用部署的环境比较复杂,主要有以下几种:

  • 机器直接部署
  • 通过原生Docker部署
  • 通过kubernates集群部署
部署环境不统一,导致查看应用日志很不方便 。
业务需求与部署环境对应,对于日志收集需求分为以下几类:
  • 机器上的文本日志(直接运行在物理机或者虚拟机中的应用日志)
  • 运行在docker容器中的应用日志
  • 运行在kubernates集群中的应用日志
具体业务需求可以拆分为:
  • 按照项目、应用、实例维度检索日志并支持搜索关键字高亮(因为大家检索日志的时候,肯定是检索某个项目、某个应用、某个实例的日志)
  • 支持检索出某条想要的日志后,可以查看上下文(查看该日志所在日志文件的日志上下文)
  • 支持日志下载(目前支持两种场景:搜索结果下载、上下文下载;支持两种方式:在线下载、离线下载)
  • 支持自动化批量部署、卸载Agent,部署、卸载过程可视化
  • 单实例支持多elasticsearch集群
  • 支持文本日志、docker日志、k8s日志并能与将日志与其业务意义对应上 。(即不管是哪种日志形式、来源,最终都需要与业务意义上的项目、应用、实例对应起来,因为对于日志的使用者来说,查询日志的出发点肯定是查询某个项目、某个应用(可以不选)、某个实例(可以不选)、某段时间的日志 。)
  • 支持部署到业务自己的集群中
需求已经明确了,下面看一下业界方案 。
业界日志系统架构
日志服务架构设计

文章插图
 
  • Collector的作用是:
  • 清洗、汇聚数据,减少对于后端集群的压力 。
  • 安全,不允许Agent直连kafka等内部集群,保证一定的安全性,即使后端发生调整也能保证对于Agent连接、认证方式的稳定 。
  • MQ的作用是削峰填谷、解耦、多次消费 。
上图的架构是业界比较通用的一种架构,对于各种场景都考虑的比较全 。
既然业界的架构已经这么完备,那么我们是否就直接采用呢?
对于我们而言,有以下几个问题:
  • 涉及的组件比较多,链路比较长,运维比较麻烦
  • 这一整套架构,不利于单独部署(比如某个业务应用部署机房网络是隔离的,而且项目又不大,只能提供有限的几台机器,这时候如果需要部署业界这套架构的话,资源就会比较受限,如果想做到即支持业界架构组件的可插拔(比如可灵活的决定是否需要Collector、MQ),那么就需要运维几套配置或代码)
  • 最关键的就是其中组件提供的功能,我们目前用不到 。比如MQ的削峰填谷、多次消费 。
组件选择选择组件,我们这边主要是从以下几个方面进行考量的:
  1. 组件对应的开源生态完整、活跃度高
  2. 对应的技术栈是我们所熟悉的,我们这边语言技术栈主要是JAVA、Go,如果组件语言是C、Ruby,应该就被排除了 。
  3. 运维成本
  4. 易部署、性能好
Agent
一提到日志收集方案,大家第一个想到的肯定是ELK(Elasticsearch、Logstash、Kibana ),但Logstash依赖于JVM不管是性能还是简洁性,都不是日志收集agent的首选 。
个人感觉一个好的agent应该是资源占用少,性能好,不依赖别的组件,可以独立部署 。而Logstash明显不符合这几点要求,也许正是基于这些考虑elastic推出了Filebeat 。
Collector、MQ
Elasticsearch集群在部署的时候,一般都是提前估计好容量、机器、shard等信息,因为Elasticsearch集群运行后,再水平拓展,比较麻烦,而我们这边由于业务及成本限制无法很好的预估容量,所以就结合公司实际要求:使用日志服务的业务方自带机器,也就是业务方会有独立的Elasticsearch集群 。
每个业务方都使用自己的Elasticsearch集群,所以集群压力不会很大,从而Collector、MQ这两个组件对于我们的作用也就很小了 。
ETL
因为Elasticsearch Ingest Node完全可以满足我们的解析需求,所以就没有必要再引入Logstash等相关组件了 。
到这里,基本可以看出我们的架构如下:
日志服务架构设计

文章插图
 
架构设计的几个原则:
  • 合适优于业界领先
  • 简单优于复杂
  • 演化优于一步到位
具体实现基于需求及EFK套件,梳理我们场景中特有的东西:


推荐阅读