系列文章:Kubernetes日志采集最佳实践

优采云 发布时间: 2020-08-09 16:03

  前言

  上一期主要介绍Kubernetes日志输出的一些注意事项,日志输出最终的目的还是做统一的采集和剖析。在Kubernetes中,日志采集和普通虚拟机的方法有很大不同,相对实现难度和布署代价也略大,但若使用恰当则比传统方法自动化程度更高、运维代价更低。

  Kubernetes日志采集难点

  在Kubernetes中,日志采集相比传统虚拟机、物理机方法要复杂好多,最根本的缘由是Kubernetes把底层异常屏蔽,提供愈发细细度的资源调度,向上提供稳定、动态的环境。因此日志采集面对的是愈发丰富、动态的环境,需要考虑的点也愈发的多。

  例如:

  对于运行时间太短的Job类应用,从启动到停止只有几秒的时间,如何保证日志采集的实时性才能跟上并且数据不丢?K8s通常推荐使用大尺寸节点,每个节点可以运行10-100+的容器,如何在资源消耗尽可能低的情况下采集100+的容器?在K8s中,应用都以yaml的形式布署,而日志采集还是以手工的配置文件方式为主,如何才能使日志采集以K8s的方法进行布署?Kubernetes传统方法

  日志种类

  文件、stdout、宿主机文件、journal

  文件、journal

  日志源

  业务容器、系统组件、宿主机

  业务、宿主机

  采集方式

  Agent(Sidecar、DaemonSet)、直写(DockerEngine、业务)

  Agent、直写

  单机应用数

  10-100

  1-10

  应用动态性

  高

  低

  节点动态性

  高

  低

  采集部署形式

  手动、Yaml

  手动、自定义

  采集方式:主动 or 被动

  日志的采集方式分为被动采集和主动推送两种,在K8s中,被动采集一般分为Sidecar和DaemonSet两种形式,主动推送有DockerEngine推送和业务直写两种形式。

  

  总结出来:DockerEngine直写通常不推荐;业务直写推荐在日志量极大的场景中使用;DaemonSet通常在中小型集群中使用;Sidecar推荐在超大型的集群中使用。详细的各类采集方式对比如下:

  DockerEngine业务直写DaemonSet形式Sidecar形式

  采集日志类型

  标准输出

  业务日志

  标准输出+部分文件

  文件

  部署运维

  低,原生支持

  低,只需维护好配置文件即可

  一般,需维护DaemonSet

  较高,每个须要采集日志的POD都须要布署sidecar容器

  日志分类储存

  无法实现

  业务独立配置

  一般,可通过容器/路径等映射

  每个POD可单独配置,灵活性高

  多住户隔离

  弱

  弱,日志直写会和业务逻辑竞争资源

  一般,只能通过配置间隔离

  强,通过容器进行隔离,可单独分配资源

  支持集群规模

  本地储存无限制,若使用syslog、fluentd会有单点限制

  无限制

  取决于配置数

  无限制

  资源占用

  低,docker

  engine提供

  整体最低,省去采集开销

  较低,每个节点运行一个容器

  较高,每个POD运行一个容器

  查询便捷性

  低,只能grep原创日志

  高,可依照业务特性进行订制

  较高,可进行自定义的查询、统计

  高,可依照业务特性进行订制

  可定制性

  低

  高,可自由扩充

  低

  高,每个POD单独配置

  耦合度

  高,与DockerEngine强绑定,修改须要重启DockerEngine

  高,采集模块更改/升级须要重新发布业务

  低,Agent可独立升级

  一般,默认采集Agent升级对应Sidecar业务也会重启(有一些扩充包可以支持Sidecar热升级)

  适用场景

  测试、POC等非生产场景

  对性能要求极高的场景

  日志分类明晰、功能较单一的集群

  大型、混合型、PAAS型集群

  日志输出:Stdout or 文件

  和虚拟机/物理机不同,K8s的容器提供标准输出和文件两种形式。在容器中,标准输出将日志直接输出到stdout或stderr,而DockerEngine接管stdout和stderr文件描述符,将日志接收后根据DockerEngine配置的LogDriver规则进行处理;日志复印到文件的形式和虚拟机/物理机基本类似,只是日志可以使用不同的储存形式,例如默认储存、EmptyDir、HostVolume、NFS等。

  虽然使用Stdout复印日志是Docker官方推荐的方法,但你们须要注意这个推荐是基于容器只作为简单应用的场景,实际的业务场景中我们还是建议你们尽可能使用文件的形式,主要的缘由有以下几点:

  Stdout性能问题,从应用输出stdout到服务端,中间会经过好几个流程(例如普遍使用的JSON LogDriver):应用stdout -> DockerEngine -> LogDriver -> 序列化成JSON -> 保存到文件 -> Agent采集文件 -> 解析JSON -> 上传服务端。整个流程相比文件的额外开支要多好多,在压测时,每秒10万行日志输出都会额外占用DockerEngine 1个CPU核。Stdout不支持分类,即所有的输出都混在一个流中,无法象文件一样分类输出,通常一个应用中有AccessLog、ErrorLog、InterfaceLog(调用外部插口的日志)、TraceLog等,而这种日志的格式、用途不一,如果混在同一个流上将很难采集和剖析。Stdout只支持容器的主程序输出,如果是daemon/fork形式运行的程序将难以使用stdout。文件的Dump形式支持各类策略,例如同步/异步写入、缓存大小、文件轮转策略、压缩策略、清除策略等,相对愈发灵活。

  因此我们建议线上应用使用文件的形式输出日志,Stdout只在功能单一的应用或一些K8s系统/运维组件中使用。

  CICD集成:Logging Operator

  

  Kubernetes提供了标准化的业务布署形式,可以通过yaml(K8s API)来申明路由规则、暴露服务、挂载储存、运行业务、定义缩扩容规则等,所以Kubernetes很容易和CICD系统集成。而日志采集也是运维监控过程中的重要部份,业务上线后的所有日志都要进行实时的搜集。

  原创的形式是在发布以后自动去布署日志采集的逻辑,这种方法须要手工干预,违背CICD自动化的宗旨;为了实现自动化,有人开始基于日志采集的API/SDK包装一个手动布署的服务,在发布后通过CICD的webhook触发调用,但这些方法的开发代价很高。

  在Kubernetes中,日志最标准的集成方法是以一个新资源注册到Kubernetes系统中,以Operator(CRD)的形式来进行管理和维护。在这些形式下,CICD系统不需要额外的开发,只需在布署到Kubernetes系统时附加上日志相关的配置即可实现。

  Kubernetes日志采集方案

  

  早在Kubernetes出现之前,我们就开始为容器环境开发日志采集方案,随着K8s的逐步稳定,我们开始将好多业务迁移到K8s平台上,因此也基于之前的基础专门开发了一套K8s上的日志采集方案。主要具备的功能有:

  支持各种数据的实时采集,包括容器文件、容器Stdout、宿主机文件、Journal、Event等;支持多种采集部署方法,包括DaemonSet、Sidecar、DockerEngine LogDriver等;支持对日志数据进行富化,包括附加Namespace、Pod、Container、Image、Node等信息;稳定、高可靠,基于阿里自研的Logtail采集Agent实现,目前全网已有几百万的布署实例;基于CRD进行扩充,可使用Kubernetes布署发布的形式来布署日志采集规则,与CICD完美集成。安装日志采集组件

  目前这套采集方案早已对外开放,我们提供了一个Helm安装包,其中包括Logtail的DaemonSet、AliyunlogConfig的CRD申明以及CRD Controller,安装以后才能直接使用DaemonS优采云采集器以及CRD配置了。安装方法如下:

  阿里云Kubernetes集群在开通的时侯可以勾选安装,这样在集群创建的时侯会手动安装上述组件。如果开通的时侯没有安装,则可以自动安装。如果是自建的Kubernetes,无论是在阿里云上自建还是在其他云或则是线下,也可以使用这样采集方案,具体安装方法参考[自建Kubernetes安装]()。

  安装好上述组件然后,Logtail和对应的Controller都会运行在集群中,但默认这种组件并不会采集任何日志,需要配置日志采集规则来采集指定Pod的各种日志。

  采集规则配置:环境变量 or CRD

  除了在日志服务控制台上自动配置之外,对于Kubernetes还额外支持两种配置方法:环境变量和CRD。

  环境变量是自swarm时代仍然使用的配置方法,只须要在想要采集的容器环境变量上申明须要采集的数据地址即可,Logtail会手动将这种数据采集到服务端。这种方法布署简单,学习成本低,很容易上手;但才能支持的配置规则极少,很多中级配置(例如解析方法、过滤方法、黑白名单等)都不支持,而且这些申明的方法不支持更改/删除,每次更改虽然都是创建1个新的采集配置,历史的采集配置须要自动清除,否则会导致资源浪费。

  

  CRD配置方法是特别符合Kubernetes官方推荐的标准扩充方法,让采集配置以K8s资源的方法进行管理,通过向Kubernetes部署AliyunLogConfig这个特殊的CRD资源来申明须要采集的数据。例如下边的示例就是布署一个容器标准输出的采集,其中定义须要Stdout和Stderr都采集,并且排除环境变量中收录COLLEXT_STDOUT_FLAG:false的容器。

  基于CRD的配置方法以Kubernetes标准扩充资源的方法进行管理,支持配置的增删改查完整语义,而且支持各类中级配置,是我们非常推荐的采集配置方法。

  

  采集规则推荐的配置形式

  

  实际应用场景中,一般都是使用DaemonSet或DaemonSet与Sidecar混用形式,DaemonSet的优势是资源利用率高,但有一个问题是DaemonSet的所有Logtail都共享全局配置,而单一的Logtail有配置支撑的上限,因此难以支撑应用数比较多的集群。

  上述是我们给出的推荐配置形式,核心的思想是:

  一个配置尽可能多的采集同类数据,减少配置数,降低DaemonSet压力;核心的应用采集要给以充分的资源,可以使用Sidecar形式;配置方法尽可能使用CRD形式;Sidecar因为每位Logtail是单独的配置,所以没有配置数的限制,这种比较适宜于超小型的集群使用。

  实践1-中小型集群

  

  绝大部分Kubernetes集群都属于中小型的,对于中小型没有明晰的定义,一般应用数在500以内,节点规模1000以内,没有职能明晰的Kubernetes平台运维。这种场景应用数不会非常多,DaemonSet可以支撑所有的采集配置:

  绝大部分业务应用的数据使用DaemonS优采云采集器形式核心应用(对于采集可靠性要求比较高,例如订单/交易系统)使用Sidecar形式单独采集

  实践2-大型集群

  

  对于一些用作PAAS平台的小型/超大型集群,一般业务在1000以上,节点规模也在1000以上,有专门的Kubernetes平台运维人员。这种场景下应用数没有限制,DaemonSet难以支持,因此必须使用Sidecar形式,整体规划如下:

  Kubernetes平台本身的系统组件日志、内核日志相对种类固定,这部份日志使用DaemonS优采云采集器,主要为平台的运维人员提供服务;各个业务的日志使用Sidecar形式采集,每个业务可以独立设置Sidecar的采集目的地址,为业务的DevOps人员提供足够的灵活性。

  原文链接

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线