Kubernetes 日志系统建设难点

典型的 Kubernetes 架构

Kubernetes 上的日志方案相比我们之前基于物理机、虚拟机场景的日志方案有很大不同,例如:

  1. 日志的形式变得更加复杂,不仅有物理机/虚拟机上的日志,还有容器的标准输出、容器内的文件、容器事件、Kubernetes 事件等等信息需要采集;
  2. 环境的动态性变强,在 Kubernetes 中,机器的宕机、下线、上线、Pod销毁、扩容/缩容等都是常态,这种情况下日志的存在是瞬时的(例如如果 Pod 销毁后该 Pod 日志就不可见了),所以日志数据必须实时采集到服务端。同时还需要保证日志的采集能够适应这种动态性极强的场景
  3. 日志的种类变多,上图是一个典型的 Kubernetes 架构,一个请求从客户端需要经过 CDN、Ingress、Service Mesh、Pod 等多个组件,涉及多种基础设施,其中的日志种类增加了很多,例如 K8s 各种系统组件日志、审计日志、ServiceMesh 日志、Ingress 等;
  4. 业务架构变化,现在越来越多的公司开始在 Kubernetes 上落地微服务架构,在微服务体系中,服务的开发更加复杂,服务之间的依赖以及服务底层产品的依赖越来越多,这时的问题排查将更加复杂,如果关联各个维度的日志将是一个困难的问题;
  5. 日志方案集成困难,通常我们都会在 Kubernetes 上搭建一套 CICD 系统,这套 CICD 系统需要尽可能的自动化的完成业务的集成和部署,其中日志的采集、存储、清洗等也需要集成到这套系统中,并和 K8s 的声明式部署方式尽可能一致。而现有的日志系统通常都是较独立的系统,集成到 CICD 中代价极大;
  6. 日志规模问题,通常在系统初期的时候我们会选择自建开源的日志系统,这种方式在测试验证阶段或公司发展初期是没有什么问题的,但当业务逐渐增长,日志量增长到一定规模时,自建的开源系统很多时候都会遇到各种各样的问题,例如租户隔离、查询延迟、数据可靠性、系统可用性等。日志系统虽不是 IT 中最核心的路径,但一旦关键时刻出现这些问题都将是非常可怕的影响,例如大促的时候出现紧急问题,排查时多个工程师并发查询把日志系统打爆,导致故障恢复时间变长,大促收到影响。

K8s 日志系统设计和实践

日志需求分解与功能设计

公司内各个不同角色对于日志的相关需求,总结起来有以下几点:

  1. 支持各种日志格式、数据源的采集,包括非K8s
  2. 能够快速的查找/定位问题日志
  3. 能够将各种格式的半结构化/非结构化日志格式化,并支持快速的统计分析、可视化
  4. 支持通过日志进行实时计算并获得一些业务指标,并支持基于业务指标实时的告警(其实本质就是APM)
  5. 支持对于超大规模的日志进行各种维度的关联分析,可接受一定时间的延迟
  6. 能够便捷的对接各种外部系统或支持自定义的获取数据,例如对接第三方审计系统
  7. 能够基于日志以及相关的时序信息,实现智能的告警、预测、根因分析等,并能够支持自定义的离线训练方式以获得更好的效果

,日志平台上必须具备的功能功能模

为满足上述这些功能需求,日志平台上必须具备的功能功能模块有:

  1. 全方位日志采集,支持DaemonSet、Sidecar各种采集方式以应对不同的采集需求,同时支持Web、移动端、IoT、物理机/虚拟机各种数据源的采集;
  2. 日志实时通道,这个是为了对接上下游所必备的功能,保证日志能够被多种系统所便捷的使用;
  3. 数据清洗(ETL: Extract,Transform,Load),对各种格式的日志进行清洗,支持过滤、富化、转换、补漏、分裂、聚合等;
  4. 日志展现与搜索,这是所有日志平台必须具备的功能,能够根据关键词快速的定位到日志并查看日志上下文,看似简单的功能却最难做好;
  5. 实时分析,搜索只能完成一些定位到问题,而分析统计功能可以帮助快速分析问题的根因,同时可以用于快速的计算一些业务指标;
  6. 流计算,通常我们都会使用流计算框架(Flink、Storm、Spark Stream等)来计算一些实时的指标或对数据进行一些自定义的清洗等;
  7. 离线分析,运营、安全相关的需求都需要对大量的历史日志进行各种维度的关联计算,目前只有T+1的离线分析引擎能够完成;
  8. 机器学习框架,能够便捷、快速的将历史的日志对接到机器学习框架进行离线训练,并将训练后的结果加载到线上实时的算法库中。

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 本身具有 LogDriver 功能,可通过配置不同的 LogDriver 将容器的 stdout 通过 DockerEngine 写入到远端存储,以此达到日志采集的目的。这种方式的可定制化、灵活性、资源隔离性都很低,一般不建议在生产环境中使用;
  • 业务直写是在应用中集成日志采集的 SDK,通过 SDK 直接将日志发送到服务端。这种方式省去了落盘采集的逻辑,也不需要额外部署 Agent,对于系统的资源消耗最低,但由于业务和日志 SDK 强绑定,整体灵活性很低,一般只有日志量极大的场景中使用;
  • DaemonSet 方式在每个 node 节点上只运行一个日志 agent,采集这个节点上所有的日志。DaemonSet 相对资源占用要小很多,但扩展性、租户隔离性受限,比较适用于功能单一或业务不是很多的集群;
  • Sidecar 方式为每个 POD 单独部署日志 agent,这个 agent 只负责一个业务应用的日志采集。Sidecar 相对资源占用较多,但灵活性以及多租户隔离性较强,建议大型的 K8s 集群或作为 PaaS 平台为多个业务方服务的集群使用该方式。

容器日志收集方案

总结下来:

  • 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 系统/运维组件中使用

日志收集开源方案设计

以ELK为核心的日志平台方案:

借助于强大的开源社区,我们可以很容易基于开源软件的组合来实现这样一套日志平台,上图是一个非常典型的以ELK为核心的日志平台方案:

  • 利用FileBeats、Fluentd等采集Agent实现容器上的数据统一收集。
  • 为了提供更加丰富的上下游以及缓冲能力,可以使用kafka作为数据采集的接收端。
  • 采集到的原始数据还需要进一步的清洗,可以使用Logstash或者Flink订阅Kafka中的数据,清洗完毕后再写入kafka中。
  • 清洗后的数据可以对接ElasticSearch来做实时的查询检索、对接Flink来计算实时的指标和告警、对接Hadoop来做离线的数据分析、对接TensorFlow来做离线模型训练。
  • 数据的可视化可以使用grafana、kibana等常用的可视化组件。

使用Filebeat收集Kubernetes的应用日志

Kubernetes官方提供了EFK的日志收集解决方案,但是这种方案并不适合所有的业务场景,它本身就有一些局限性,例如:

  • 所有日志都必须是out前台输出,真实业务场景中无法保证所有日志都在前台输出
  • 只能有一个日志输出文件,而真实业务场景中往往有多个日志输出文件
  • Fluentd并不是常用的日志收集工具,我们更习惯用logstash,现使用filebeat替代
  • 我们已经有自己的ELK集群且有专人维护,没有必要再在kubernetes上做一个日志收集服务

综合以上优缺点,我们选择使用Filebeat收集Kubernetes的应用日志。

filebeat日志收集架构图

该方案在扩展性、个性化、部署和后期维护方面都能做到均衡,因此选择该方案。

filebeat日志收集架构图

我们创建了自己的filebeat镜像。创建过程和使用方式见 https://github.com/rootsongjc/docker-images,您可以使用该仓库中的源码创建镜像。

filebeat日志收集测试

我们部署一个应用filebeat来收集日志的功能测试。

创建应用yaml文件filebeat-test.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:name: filebeat-testnamespace: default
spec:replicas: 3template:metadata:labels:k8s-app: filebeat-testspec:containers:- image: harbor-001.jimmysong.io/library/filebeat:5.4.0name: filebeatvolumeMounts:- name: app-logsmountPath: /log- name: filebeat-configmountPath: /etc/filebeat/- image: harbor-001.jimmysong.io/library/analytics-docker-test:Build_8name : appports:- containerPort: 80volumeMounts:- name: app-logsmountPath: /usr/local/TalkingData/logsvolumes:- name: app-logsemptyDir: {}- name: filebeat-configconfigMap:name: filebeat-config
---
apiVersion: v1
kind: Service
metadata:name: filebeat-testlabels:app: filebeat-test
spec:ports:- port: 80protocol: TCPname: httpselector:run: filebeat-test
---
apiVersion: v1
kind: ConfigMap
metadata:name: filebeat-config
data:filebeat.yml: |filebeat.prospectors:- input_type: logpaths:- "/log/*"- "/log/usermange/common/*"output.elasticsearch:hosts: ["172.23.5.255:9200"]username: "elastic"password: "changeme"index: "filebeat-docker-test"

filebeat-test.yaml说明

该文件中包含了配置文件filebeat的配置文件的ConfigMap,因此不需要再定义环境变量。

当然你也可以不同ConfigMap,通过传统的传递环境变量的方式来配置filebeat。

例如对filebeat的容器进行如下配置:

      containers:- image: harbor-001.jimmysong.io/library/filebeat:5.4.0name: filebeatvolumeMounts:- name: app-logsmountPath: /logenv: - name: PATHSvalue: "/log/*"- name: ES_SERVERvalue: 172.23.5.255:9200- name: INDEXvalue: logstash-docker- name: INPUT_TYPEvalue: log

目前使用这种方式会有个问题,PATHS只能传递单个目录,如果想传递多个目录需要修改filebeat镜像的docker-entrypoint.sh脚本,对该环境变量进行解析增加filebeat.yml文件中的PATHS列表。

推荐使用ConfigMap,这样filebeat的配置就能够更灵活。

注意事项

  • 将app的/usr/local/TalkingData/logs目录挂载到filebeat的/log目录下。
  • 该文件可以在manifests/test/filebeat-test.yaml找到。
  • 我使用了自己的私有镜像仓库,测试时请换成自己的应用镜像。
  • Filebeat的环境变量的值配置请参考https://github.com/rootsongjc/docker-images

创建应用

部署Deployment

kubectl create -f filebeat-test.yaml

查看http://172.23.5.255:9200/_cat/indices将可以看到列表有这样的indices:

green open filebeat-docker-test            7xPEwEbUQRirk8oDX36gAA 5 1   2151     0   1.6mb 841.8kb

访问Kibana的web页面,查看filebeat-2017.05.17的索引,可以看到filebeat收集到了app日志。

Kibana页面

点开每个日志条目,可以看到以下详细字段:

filebeat收集的日志详细信息
  • _index值即我们在YAML文件的configMap中配置的index值
  • beat.hostnamebeat.name即pod的名称
  • source表示filebeat容器中的日志目录

我们可以通过人为得使index = service name,这样就可以方便的收集和查看每个service的日志。

问题记录

如果index: "filebeat-docker-test"没有生效,需要参考filebeat的配置文档,对filebeat的配置进一步优化。

参考链接:

  • https://developer.aliyun.com/article/749468?spm=a2c6h.12873639.0.0.3e055f916C2XKH&groupCode=alisoftwaretech
  • https://jimmysong.io/kubernetes-handbook/practice/app-log-collection.html
  • https://qhh.me/2019/09/05/Kubernetes-%E5%9F%BA%E4%BA%8E-EFK-%E6%8A%80%E6%9C%AF%E6%A0%88%E7%9A%84%E6%97%A5%E5%BF%97%E6%94%B6%E9%9B%86%E5%AE%9E%E8%B7%B5/
  •  https://github.com/rootsongjc/kubernetes-handbook

Kubernets:容器日志收集方案相关推荐

  1. Nginx容器日志收集方案fluentd+elasticsearch+kilbana

    容器技术在发展到今天已经是相当的成熟,但容器不同于虚拟机,我们在使用容器的同时也有很多相关的技术问题需要解决,比如:容器性能监控,数据持久化,日志监控与分析等.我们不能像平时使用虚拟机一样来管理容器, ...

  2. k8s容器日志收集方案

    背景 由于以下容器本身特性和现有日志采集工具的缺陷,开发者在收集Kubernetes分布式集群日志时常常遇到困扰:容器本身特性:采集目标多:容器本身的特性导致采集目标多,需要采集容器内日志.容器std ...

  3. 容器内应用日志收集方案

    容器化应用日志收集挑战 应用日志的收集.分析和监控是日常运维工作重要的部分,妥善地处理应用日志收集往往是应用容器化重要的一个课题. Docker处理日志的方法是通过docker engine捕捉每一个 ...

  4. EKS日志收集方案-PLG(Promtail+Loki+Grafana)

    组件概述(什么是PLG?) Promtail:日志收集代理,它通常被部署到需要监视应用程序的每台机器/容器上.Promtail主要是用来发现目标.将标签附加到日志流以及将日志推送到Loki.截止到目前 ...

  5. 再见笨重的ELK!这套轻量级日志收集方案要火!

    之前一直使用的日志收集方案是ELK,动辄占用几个G的内存,有些配置不好的服务器有点顶不住!最近发现一套轻量级日志收集方案: Loki+Promtail+Grafana(简称LPG), 几百M内存就够了 ...

  6. 前端错误日志收集方案

    前言 公司的项目上线出现问题后难以定位错误,研究过现存的错误监控方案,受限于特殊条件只能定制自己的错误收集方案. 基于以上背景我撸出来一个错误日志收集方案 - Ohbug. 欢迎各位大佬 star ~ ...

  7. 基于filebeat + logstash的日志收集方案

    日志收集是一个很普遍的需求,各个服务的log日志,打点日志都需要收集起来做离线etl或实时分析.日志收集工具也有很多开源的可供选择,flume,  logstash, filebeat等等.  目前3 ...

  8. 看不到日志_Kubernetes中常用的日志收集方案

    在kubernetes中对日志的处理方式叫做cluster-level-logging,即这个日志处理系统跟容器,Pod,Node的生命周期无关,也就是无论是容器挂了,Pod被删除了还是Node宕机了 ...

  9. eas报错日记_EAS_RPC日志收集方案

    一.收集服务端 RPC 日志前的相关设置: 1 .打开服务器性能日志开关. http:// 对应 eas 应用服务端的 IP 地址 :port 用户名密码: admin/admin ( 例 : htt ...

  10. 一套标准的ASP.NET Core容器化应用日志收集分析方案

    点击上方蓝字 给一个关注吧 讲故事 关注我公众号的朋友,应该知道我写了一些云原生应用日志收集和分析相关的文章,其中内容大多聚焦某个具体的组件: 超级有用的TraceId,快点用起来吧! 如何利用NLo ...

最新文章

  1. Cell:浙大张兴/朱永群组揭示细菌鞭毛马达结构、组装与扭矩传输机制
  2. leetcode算法题--最长定差子序列
  3. PAT甲级1012 The Best Rank :[C++题解]4个成绩取排名最低:排序、二分(好题)
  4. C#代码的语法和格式(一)
  5. 为SAP Spartacus安装后台必须的Commerce Cloud
  6. [Java基础]反射获取成员变量并使用
  7. linux kvm图标需要安装的软件,KVM 图形化安装
  8. 中国内部折叠门市场趋势报告、技术动态创新及市场预测
  9. (第二部)程序员逆天改命之胜天半子
  10. 【硬刚Hive】MYSQL/HIVESQL笔试题(七):HIVESQL(七)
  11. 多目标启发式算法(NSGA2, MOEA, MOPSO)python实现
  12. vue UEditor集成秀米
  13. 数据库开发技术的课程记录
  14. 【最优方案】合唱队形
  15. csgo靠谱的开箱网站有哪些?csgo开箱网站大全
  16. SQL Server数据库-表
  17. c语言中常量有何作用,正确的C语言常量是什么?
  18. opengl全景图转换为天空盒图(成功)
  19. echarts水波球特效(附带外边框进度条)
  20. 黑客入侵网络的50种方法

热门文章

  1. mapboxgl绘制3D线教程
  2. 支持向量机---SVM 最小二乘支持向量机---LSSVM
  3. 如何用C语言实现原码一位乘法器?这里可能有你想要的答案....
  4. 根据经纬度查询距离并按距离进行排序
  5. 读《美国交通信号配时实践经验》后的感受
  6. 点微同城系统整站源码+带PC端与小程序端/49款插件
  7. 【NLP】第 2 章 访问文本语料库和词汇资源
  8. smartupload功能介绍
  9. matlab神经网络
  10. 全网软件:高级信息搜索数据采集软件 InfoSeek FastSeek