日志服务架构设计

最近想把以前作过的日志项目及我的的思考梳理一下,因而有了本文。前端

背景

咱们这边应用部署的环境比较复杂,主要有如下几种:git

  • 机器直接部署
  • 经过原生docker部署
  • 经过kubernates集群部署

部署环境不统一,致使查看应用日志很不方便。github

业务需求

与部署环境对应,对于日志收集需求分为如下几类:docker

  • 机器上的文本日志(直接运行在物理机或者虚拟机中的应用日志)
  • 运行在docker容器中的应用日志
  • 运行在kubernates集群中的应用日志

具体业务需求能够拆分为:后端

  • 按照项目、应用、实例维度检索日志并支持搜索关键字高亮(由于你们检索日志的时候,确定是检索某个项目、某个应用、某个实例的日志)
  • 支持检索出某条想要的日志后,能够查看上下文(查看该日志所在日志文件的日志上下文)
  • 支持日志下载(目前支持两种场景:搜索结果下载、上下文下载;支持两种方式:在线下载、离线下载)
  • 支持自动化批量部署、卸载Agent,部署、卸载过程可视化
  • 单实例支持多elasticsearch集群
  • 支持文本日志、docker日志、k8s日志并能与将日志与其业务意义对应上。(即不论是哪一种日志形式、来源,最终都须要与业务意义上的项目、应用、实例对应起来,由于对于日志的使用者来讲,查询日志的出发点确定是查询某个项目、某个应用(能够不选)、某个实例(能够不选)、某段时间的日志。)
  • 支持部署到业务本身的集群中

需求已经明确了,下面看一下业界方案。安全

业界日志系统架构

  • Collector的做用是:
    • 清洗、汇聚数据,减小对于后端集群的压力。
    • 安全,不容许Agent直连kafka等内部集群,保证必定的安全性,即便后端发生调整也能保证对于Agent链接、认证方式的稳定。
  • MQ的做用是削峰填谷、解耦、屡次消费。

上图的架构是业界比较通用的一种架构,对于各类场景都考虑的比较全。微信

既然业界的架构已经这么完备,那么咱们是否就直接采用呢?网络

对于咱们而言,有如下几个问题:架构

  • 涉及的组件比较多,链路比较长,运维比较麻烦
  • 这一整套架构,不利于单独部署(好比某个业务应用部署机房网络是隔离的,并且项目又不大,只能提供有限的几台机器,这时候若是须要部署业界这套架构的话,资源就会比较受限,若是想作到即支持业界架构组件的可插拔(好比可灵活的决定是否须要Collector、MQ),那么就须要运维几套配置或代码)
  • 最关键的就是其中组件提供的功能,咱们目前用不到。好比MQ的削峰填谷、屡次消费。

组件选择

选择组件,咱们这边主要是从如下几个方面进行考量的:app

  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套件,梳理咱们场景中特有的东西:

  • docker日志的场景比较单一,都是经过以前一个产品A发布部署的,其docker命名规则比较统一,能够经过截取docker.container.name来获取应用名字;同时在部署的时候,能够知道部署目标机器的ip,这样就能够经过应用+ip来做为实例名称。
  • k8s场景也比较统一,都是经过以前一个产品B发布部署的,其pod命名规则比较统一,能够经过截取kubernetes.pod.name来获取应用名字(但须要经过namespaces关联到tenant,再经过tenant与项目一一对应);k8s中的pod.name就是惟一的,以此来做为实例名称便可。
  • 文本日志:由于文本日志主要的场景是已经裸机部署的应用,这种场景下,不存在应用自动迁移的状况,因此文本日志的应用名称、实例名称能够在部署的时候打上标签便可。

具体规则及解析见下图(实例部分处理暂未标注):

推荐写日志到文本文件中,使用标准输出就好。

到这里能够发现咱们选择Filebeat来做为日志的收集端,Elasticsearch来存储日志并提供检索能力。

那么,日志的清洗在哪里作呢?

日志的清洗通常有两种方式:

  • 先把日志收集到kafka,再经过Logstash消费kafka的数据,来清洗数据
  • 直接经过Elasticsearch的[Ingest Node]来清洗数据,由于Ingest Node也支持Grok表达式

对于,咱们的场景而言,咱们须要清洗数据的要求比较简单,主要是应用、实例名称的截取还有文本日志中日志时间的处理(@timestamp重置,时区处理),因此咱们选择了方案2。

在咱们的方案中,并无提供Kibana 的界面直接给用户用,而是咱们本身根据公司业务独立开发的。

前端界面为何不采用Kibana,而须要本身开发?

  1. kibana对于业务开发人员有必定的学习成本
  2. kibana界面没有很好的将日志内容与业务意义关联起来(界面选择总比一次次的输入要好,这也是咱们将日志的项目、应用、实例等业务信息解析出来的缘由)
  3. log-search支持Query String,所以对于熟悉kibana的开发人员来讲,在咱们本身开发的前端界面检索效果是同样的。

log-search提供的功能能够参见github:github.com/jiankunking…

若是日志须要清洗的比较多,能够采用方案1,或者先不清洗,先把数据落到Elasticsearch,而后在查询的时候,进行处理。好比在咱们的场景中,能够先把日志落到Elasticsearch中,而后在须要检索应用名称的时候,经过代码来处理并获取app名字。

监控、告警

其实基于日志能够作不少事情,好比:

  • 基于日志作监控(Google Dapper)
  • 基于日志作告警
  • 基于日志作Machine Learning

具体思路,能够参见下图:

前提:能要求使用方,按照某种规则打印日志。 监控发展:监控基本就是先打通链路trace,而后再在上报信息或者日志信息中,增强业务方面标识,即给监控添加业务维度方面的视角。

其它

DaemonSet

以DaemonSet方式部署Filebeat来收集日志,其实收集也是宿主机/var/lib/docker/containers目录下的日志。 Running Filebeat on Kubernetes

Sidecar

一个POD中运行一个sidecar的日志agent容器,用于采集该POD主容器产生的日志。

莫名想起了istio。

Filebeat能够以sidecar模式来进行容器日志的收集,也就是filebeat和具体的服务容器部署在同一个pod内,指定收集日志的路径或文件,> 便可将日志发送到指定位置或Elasticsearch这类的搜索引擎。 每一个pod内部署filebeat的模式,好处是和具体的应用服务低耦合,可扩展性强,不过须要在yaml进行额外配置。

我的微信公众号:

我的github:

github.com/jiankunking

我的博客:

jiankunking.com

相关文章
相关标签/搜索