一键采集上传常见的细节问题(Kubernetes日志处理的趋势与挑战的serveless化(组图))

优采云 发布时间: 2021-11-02 19:00

  一键采集上传常见的细节问题(Kubernetes日志处理的趋势与挑战的serveless化(组图))

  Kubernetes 日志处理对 Serverless Kubernetes 的趋势和挑战

  Kubernetes 容器技术促进了技术栈的解耦。通过引入堆栈的分层,开发者可以更加关注自己的应用和业务场景。从Kubernetes本身来看,这种技术解耦也在进一步发展。容器化的发展趋势之一是这些容器都将运行在无服务器基础设施上。

  说到基础设施,你首先会想到云。目前,AWS、阿里云、Azure 云上提供了无服务器 Kubernetes 服务。在无服务器 Kubernetes 上,我们不再关心集群和机器。我们只需要声明容器的镜像、CPU、内存和外部服务方法即可启动应用程序。

  

  如上图所示,左右两边分别是经典Kubernetes和serverless Kubernetes的形式。在从左到右发展的过程中,日志采集也变得复杂了:

  日志实时性要求越来越强

  首先要强调的是,并非所有日志都需要实时处理。目前,很多“T+1”时效性日志交付还是很重要的。比如BI延迟1天可能就够了,ctr估计可能会延迟1小时。.

  但是,在某些场景下,时效秒级或更高的日志是必要的前提条件。下图中从左到右的横坐标对比,可见实时数据对决策的重要性。

  

  我说一下两种场景下实时日志对决策的重要性:

  日志集中存储

  日志的来源有很多,常见的有:文件、数据库审计日志、网络包等。另外,对于同一条数据,对于不同用户(例如:开发、运维、运维等)和不同目的(例如:报警、数据清洗、实时检索、批量计算等)日志数据的状况。

  在日志数据的系统集成中,从数据源到存储节点再到计算节点,可以定义为一个管道。如下图,从上到下的变化是:日志处理从O(N^2)管道进化到O(N)管道。

  

  过去,各种日志都以特定的方式存储。计算的采集链接不具备通用和复用的条件。管道非常复杂,数据存储也可能是冗余的。在当前的日志数据集成中,通过依赖一个集线器(Hub)来简化日志架构的复杂性并优化存储利用率。这个基础设施级的Hub非常重要,需要支持实时pub/sub,能够处理高并发的读写请求,提供海量的存储空间。

  Kubernetes日志采集解决方案的演进

  上一节总结了Kubernetes日志处理的趋势,接下来就来看看Kubernetes上几种常见的日志实践。

  命令行工具

  在Kubernetes集群上查看日志,最基本的方式是登录机器,运行kubectl logs查看容器写入的stdout/stderr。

  

  基本的解决方案无法满足更需要:

  节点日志文件放置

  为了处理Kubernetes节点维度的日志,docker引擎将容器的stdout/stderr重定向到logdriver,在logdriver上可以配置多种形式的持久化日志,比如将文件以json格式保存到本地存储。

  与kubectl命令行相比,更进一步的是日志的本地化存储。您可以使用grep/awk 等Linux 工具来分析日志文件的内容。

  

  这个方案相当于回到了物理机时代,但是还有很多问题没有解决:

  基于该方案的演进版本是在节点上部署日志采集客户端,并将日志上传到集中式日志存储设施。这是目前推荐的模式,将在下一节介绍。

  Sidecar 模式日志客户端采集

  伴侣模式。在一个 Pod 中,除了业务容器之外,还有一个日志客户端容器。这个日志客户端容器负责将采集pod内容容器的标准输出、文件和指标数据上报给服务器。

  

  该方案解决了日志持久化等基本功能需求,但有两个方面需要改进:

  日志写入

  直写方案一般是通过修改应用程序本身,在程序内部组织几个日志,然后调用类似的HTTP API将数据发送到日志存储后端来实现的。

  

  好处是:日志格式可以按需DIY,日志源和目的地的路由可以任意配置。

  您还可以查看使用限制:

  Kubernetes 日志处理架构来源于社区的架构

  目前在很多架构中,采集的工作都是通过在每个Kubernetes节点上安装一个日志客户端来完成的:

  

  日志客户端将数据格式化并使用指定的协议上传到存储终端。一个常见的选择是 Kafka。Kafka 支持实时订阅和重复消费。后期数据可以根据业务需要同步到其他系统。比如将业务日志发送到Elastic Search进行关键词查询,结合Kibana进行日志可视化分析;金融场景日志必须长期保留,可以选择将Kafka数据发布到AWS S3等性价比高的存储。

  这种架构看起来简洁有效,但在Kubernetes下离完美还有一些细节需要解决:

  日志服务Kubernetes日志架构实践

  我们提出了基于阿里云日志服务的Kubernetes日志处理架构来补充社区的解决方案,尝试解决Kubernetes场景下日志处理的一些细节体验问题。这种架构可以概括为:“Logtail+日志服务+生态系统”。

  

  首先Logtail是日志服务的数据采集客户端,专门针对Kubernetes场景中的一些痛点而设计。按照Kubernetes官方推荐,每个节点只部署一个Logtail客户端,负责这个节点上的所有pod日志采集。

  其次,针对关键词搜索和SQL统计这两个基本的日志需求:日志服务提供了基本的LogHub功能,支持实时数据写入和订阅;在LogHub存储的基础上,可以选择开启数据索引分析功能,开启索引后可以支持日志查询和SQL语法分析。

  最后,日志服务的数据是开放的。索引数据可以通过JDBC协议对接第三方系统,SQL查询结果可以方便地与阿里云DataV等Grafana系统和开源社区集成;日志服务的高吞吐量实时读写能力支持与流计算系统的对接。Spark Streaming、blink、jstorm等流式计算系统都有connector支持;用户还可以通过全托管交付功能将数据写入阿里云的对象存储OSS。交付支持行存储(csv、json)、列存储(Parquet)格式,这些数据可以作为长期低成本备份,也可以通过“OSS存储+E-MapReduce计算”架构实现数据仓库。

  日志服务优势

  从四点描述日志服务的特点:

  

  回顾第一节提到的Kubernetes日志处理的趋势和挑战,日志服务的三大优势:

  日志服务结合社区力量分析Kubernetes日志

  Kubernetes 来自社区,使用开源软件来处理 Kubernetes 日志在某些场景下也是正确的选择。

  日志服务保证数据的开放性,在采集、计算、可视化等方面与开源社区对接,帮助用户享受社区的技术成果。

  

  如下图,一个简单的例子:使用流计算引擎flink实时消费日志服务的日志库数据,并发源日志库的shard和flink任务实现动态负载均衡,之后与MySQL meta完成数据join处理,然后通过connector Streaming到另一个日志服务日志库进行可视化查询。

  

  Kubernetes log采集场景下Logtail的设计

  在本文的第二部分,我们回顾了Kubernetes日志采集解决方案演进过程中遇到的问题。第三部分介绍了阿里云日志服务的功能和生态。本节将重点介绍Logtail采集端的设计和优化,详细介绍Logtail如何解决Kubernetes日志采集上的痛点。

  Kubernetes的难点采集

  采集可靠性

  动态扩展的挑战

  采集配置易用性

  Logtail 可靠性高采集

  Logtail至少支持至少一次采集的语义保证。文件和内存级别的检查点机制用于确保容器重启场景中的可恢复传输。

  日志采集过程中可能会遇到各种系统或用户配置错误。例如,当出现日志格式化和解析错误时,我们需要及时调整解析规则。Logtail提供采集监控功能,可以将异常和统计信息上报到日志库,支持查询和告警。

  优化计算性能,解决单节点*敏*感*词*日志采集问题。Logtail可以在不格式化日志字段(单行模式)的情况下,实现单CPU核100MB/s左右的处理性能。针对网络发送的慢速IO操作,客户端批量提交多条日志到服务器进行持久化,同时兼顾了采集的实时性和高吞吐能力。

  在阿里巴巴集团内部,Logtail目前有上百万的客户端部署,稳定性很好。

  丰富的数据源支持

  针对Kubernetes环境中采集复杂多样的需求,Logtail可以从采集的源头支持:stdout/stderr、容器、主机日志文件、syslog、lumberjack等开放协议数据采集。

  通过语义将日志划分为多个字段,可以获得多个键值对,从而将日志映射到表模型。这项工作使后续的日志分析过程更加有效。Logtail支持以下日志格式化方式:

  应对节点级容器的动态扩展

  

  容器天生就会正常膨胀和收缩。新扩展的容器日志需要及时采集,否则会丢失。这就要求客户端能够动态感知采集的来源,并且在部署和配置方面达到足够的易用性。Logtail从以下两个维度解决数据完整性问题:

  采集配置管理

  解决采集配置管理问题

  Logtail提供了两种采集配置管理方式,用户可以根据自己的喜好选择操作:

  我们将源到目标(日志库)的日志定义为 采集 路由。使用传统方案实现个性化采集路由功能非常麻烦,需要在客户端本地配置。每个pod容器都会写这个采集路由,会对容器的部署和管理产生很强的依赖。Logtail解决这个问题的突破点就是环境变量的应用。Kubernetes 的 env 由多个 key-value 组成,可以在部署容器时设置。Logtail的采集配置中,IncludeEnv和ExcludeEnv配置项用于添加或排除采集源。下图中,在pod业务容器启动时设置了log_type环境变量,

  

  Logtail自动标记Kubernetes采集上接收到的所有数据的pod/namesapce/contanier/image维度,方便后续数据分析。

  日志上下文查询的设计

  上下文查询是指:给定一条日志,查看该日志在原机上的上一条或下一条日志以及文件位置,类似于Linux上的grep -A -B。

  在devops等一些场景中,逻辑异常需要这个时机来辅助定位,上下文视图功能会事半功倍。那么在分布式系统中,很难保证源和目标上的原创日志顺序:

  传统的上下文查询方案一般会根据日志到达服务器的时间和日志业务时间字段做两个排序。这在大数据场景中存在:排序性能问题,时间精度不够,无法真正还原事件的真实时间。

  Logtail和日志服务(关键词查询功能)结合解决这个问题:

  采集上传容器文件的日志时,数据包由一批多条日志组成,多条日志对应一个特定文件的一个块,比如512KB。这个数据包中的多个日志是按照源文件的日志顺序排列的,也就是说某个日志的下一个日志可能在同一个数据包中,也可能在下一个数据包中。

  Logtail会在采集时为这个数据包设置唯一的日志源sourceId,并在上传的数据包中设置包自增Id,称为packageID。在每个包中,任何日志在包中都有偏移量。

  虽然数据包可能会在服务器端乱序存储,但日志服务有一个索引可以准确查找指定sourceId和packageId的数据包。

  当我们指定容器A的序列号2日志(source_id:A,package_id:N,offset:M)查看如下时,首先判断当前包的偏移量是否是包的结尾(在包定义为L,末尾的偏移量是L-1):如果偏移量M小于(L-1),那么它的下一个日志位置是:source_id:A,package_id: N, offset: M+1 ; 而如果当前日志是数据包的最后一条,则下一条日志的位置为:source_id: A, package_id: N+1, offset:0。

  

  在大多数场景下,通过关键词的随机查询得到的包可以支持当前包长度L次的上下文翻页,提高了查询性能,大大减少了后台服务的随机IO次数。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线