本文整顿自:浅谈云原生系统日志收集在数栈的实际
数栈是云原生—站式数据中台 PaaS,咱们在 github 上有一个乏味的开源我的项目:FlinkX,欢送给咱们点个star!star!star!
https://github.com/DTStack/flinkx
FlinkX 是一个基于 Flink 的批流对立的数据同步工具,既能够采集动态的数据,比方 MySQL,HDFS 等,也能够采集实时变动的数据,比方 MySQL binlog,Kafka 等,是全域、异构、批流一体的数据同步引擎,大家如果有趣味,欢送来 github 社区找咱们玩~
一、惯例打法 ELK
谈到日志收集,预计大家第一个想到的就是 ELK 这个比拟成熟的计划,如果是特地针对云原生上的,那么将采集器略微变一下为 Fluentd 组成 EFK 即可。以上两种计划其实没有实质上的区别,采集器换了换而已。最终存储、查问等等采纳的还是 elasticsearch 这一套。
elasticsearch 的确功能丰富、十分弱小,然而代价也是极其低廉的,elasticsearch 采纳全文索引的形式,对存储以及内存的要求比拟高,而这些代价换来的性能对于日常日志治理来说却是不罕用的。这些毛病在主机模式下其实是能够容忍的,但在云原生模式下就显得比拟臃肿了。
二、不讲武德 PLG
PLG 是 promtail+loki+grafana 的合称,这是一套非常适合云原生下日志的采集计划。grafana 大家会比拟相熟,一个十分棒的可视化的框架,反对多种数据源。最常见的就是将 prometheus 的数据进行可视化展现。而 loki 就是明天咱们要谈的配角,这个也是 grafana 家的产品,promtail 则是 loki 的官网日志采集器。
与 elk 相比这一套计划十分轻量级,性能实用,应用起来简略易用,并且在展现上采纳 grafana 缩小引入可视化的框架,展现终端上的对立也有利于用户的应用。
(一)日志新贵 loki
Loki 是受 Prometheus 启发的程度可扩大,高度可用的多租户日志聚合零碎。它的设计具备很高的老本效益,并且易于操作。它不索引日志的内容,而是为每个日志流设置一组标签。
与其余日志聚合零碎相比,Loki
不对日志进行全文本索引。通过存储压缩的,非结构化的日志以及仅索引元数据,Loki 更加易于操作且运行老本更低。
应用与 Prometheus 雷同的标签对日志流进行索引和分组,从而使您可能应用与 Prometheus 雷同的标签在指标和日志之间无缝切换。
特地适宜存储 Kubernetes Pod 日志。诸如 Pod 标签之类的元数据会主动被抓取并建设索引。
Grafana 原生反对(须要 Grafana v6.0 以上)。
这段是 loki 在 GitHub 上的介绍,能够看出这是一款为云原生而打造的轻量级日志聚合零碎。目前社区十分沉闷。而且采纳 prometheus 相似的标签的思维,与 grafana 买通进行可视化展现,无论是思维还是用法都十分的“云原生”。
(二)♂️ 亲儿子 Promtail
promtail 是 loki 的官网日志采集器,自身代码就在 loki 我的项目中。原生反对 journal、syslog、file、docker 类型的日志。采集器的实质无非都是依据模式找到要采集的文件,而后对着个文件进行相似 tail 的监控,再把写入文件的内容发送给存储端 promtail 也是这样,下面这些类型的实质也都是文件,只不过这些类型的文件的格局是公开稳固的标准,promtail 能够事后对其进行进行更深解析与封装。
(三)Promtail 服务发现
1、找到文件 作为一个采集器,其第一步天然是要找到文件在哪里,而后能力做上面的收集与打标签推送等性能。一般动态类型的日志是很好发现的,间接将你在配置文件中写的门路信息进行匹配即可,比方 promtail 中 path 为 “/var/log/*.log” 行将 /var/log 目录下所有的以.log 结尾的后缀文件作为要采集的对象即可。而要采集 k8s 模式内的日志就稍显麻烦。
首先咱们想一下 k8s 上跑的服务的日志到底是在哪里?
-
文件类型的日志
这种天然是还在你自定义的门路上,如果这个门路目录没有被挂载进去,那么就在容器外部,如果挂载到了宿主机或者 pv 内,那么在 宿主机与 pv 内也是可见的,这种类型的日志 promtail 是无奈动静发现的,必须手工设置进去。
-
规范输入的日志
这类日志其实是 k8s 举荐的日志输入形式,这类日志其实是咱们日常用 kubectl log 看到的日志,这类日志存储门路在宿主机遵循 /var/log/pods/ {namespace}_/{pod_id}_UUID/{container_name}/*.log 这种格局
所以咱们须要将这 /var/log/pods 作为 hostpath 挂载进 k8s 的容器外部,能力让 promtail 拜访到这些日志。
2、打上标签
日志 promtail 能够拜访到了,然而还有一个问题还是如何为辨别这些日志,loki 采纳相似 prometheus 的思维,将数据打上标签。也就是将日志打上 pod 的标签,那么单单凭借这个门路天然是无奈晓得该 pod 上有哪些标签信息的。这里就须要用到服务发现了。
promtail 的服务发现是间接采纳的 prometheus 的服务发现做的。相熟 prometheus 的同学必定配置过 prometheus 的服务发现的配置,kubernetes_sd_configs 与 relabel_configs。
这里 promtail 间接引入 prometheus 的代码,与 prometheus 不同的是 prometheus 申请的资源对对象比拟多,node、ingress、pod、deployment 等等都有,最终拼接的是 metric 的申请 url,而 promtail 申请的对象为 pod,并且过滤掉了不在该主机上的 pod。
拿到该主机的 pod 的信息后,再依据 namespace,pod 的 id 拼接门路,因为这个目录曾经挂载进去容器了,那么 promtail 就能够关联起容器的标签与容器的日志了。剩下的就是监控与推送了。
(四)PLG 最佳实际
loki 官网举荐的最佳实际为采纳 DamonSet 部署 promtail 的形式,将 node 的 /var/lib/pods 目录挂载进容器外部,借助 prometheus 的服务发现机制动静的为日志加上标签,无论是资源的占用水平还是部署保护难度都是非常低。这也是支流的云原生日志采集范式。
三、数栈日志实际
(一)数栈日志需要
-
全局 grep
依据关键字,搜寻零碎中所有呈现的中央
-
疾速定位日志
依据机器名、ip、服务名等条件疾速定位日志
-
主机与云原生对立技术栈
缩小应用学习老本,升高零碎复杂性
(二)️ 主机模式
数栈主机模式日志聚合采纳相似 PLG DameonSet 的模式。每台主机部署一台 promtail,而后整个集群部署一套服务端 loki 与可视化端 grafana。
promtail 采纳 static_configs 定义采集的日志。然而 promtail 毕竟还是太年老了,定位偏差于云原生,所以针对主机性能还不够欠缺,因而咱们做了一些二次开发满足咱们的需要:
1、logtail 模式
原生 promtail 并不反对从文件尾部开始收集,当 promtail 启动后,会将监控的所有文件的内容都进行推送,这样的状况在云原生并没有太大问题.
主机模式下如果要监控的日志曾经存在并且有大量的内容的话,promtail 启动会将文件的内容从头开始推送,短时间内造成大量的日志往 loki 推送,很大的概率会被 loki 限流导致推送失败。
所以最好的形式就是有相似 filebeat 的 logtail 的模式,及只推送服务启动后的文件写入的日志。
这个中央咱们对此作了二次开发,减少一个 logtail 模式的开关,如果该开关为 true,这第一次启动 promtail 的时候将不会从头推送日志。
2、path 反对多路径
原生 promtail 不反对多路径 path 参数只能写一个表达式,然而事实的需要可能是既要看业务的日志还要看 gc 的日志。
然而他们又是属于同一类别的标签。单个 path 的匹配无奈涵盖其两个,不改代码的解决办法就是再为其写一个 target。
这样做繁琐且不利于保护。所以咱们这里也对其做了二次开发
(三)云原生模式
传统的云原生模式采纳 PLG 的支流模式就好了,然而数栈作为一整套系统对企业交付的时候有诸多限度会导致 demoset 模式并不可用,最大的挑战是权限,只有一个 namespace 的权限,不能挂载 /var/lib/pods
在这种状况下如何应用 PLG 呢?
其实次要变动的中央在于 promtail 的应用,这里首先要申明的一点是,数栈的服务的日志都为文件输入。
首先是抉择 damonset 模式部署还是 sidecar 模式部署,demonset 模式的长处是节俭资源,毛病是权限有要求。sidecar 模式与之相同,为了实用更严格的交付条件,咱们抉择采纳 sidecar 的模式进行采集。
sidecar 模式就是为当每个服务进行部署的时候就主动为其增加一个 log 容器,该容器与服务容器独特挂载一个独特的空的数据卷,服务容器将日志写入该数据卷中,log 容器对数据卷下的日志进行采集。
1、⛳ promtail 在数栈如何动静配置标签
通过 sidecar 的模式咱们让 log Container 与 Master Container 共享一个日志目录,这样就 promtail 容器内就能够拿到了日志的文件,然而 promtail 还不晓得要采集哪些日志,以及他的标签是什么。
因为你可能只想采集.log 的日志,也可能只想采集.json 的日志,或者都有的服务这个配置可能是不同的,所以也不能写死,那如何解决这个问题呢?
promtail 在 v2.10 中新减少了一个 feature,就是能够在配置文件中援用环境变量,通过这个个性咱们能够将 promtail 的 path 参数写成 ${LOG_PATH},而后将服务的 logpath 以环境变量的形式设置进去比方 LOG_PATH=/var/log/commonlog/*.log
既然咱们能够通过环境变量的形式在服务创立的时候设置 path,那么标签咱们也能够动静的设置进去。那么咱们都需什么维度的标签呢?这个不同的公司必定有不同的维度,然而必须遵循的一个准则就是能够惟一确定该 pod。个别的维度有 deployment、podid、node 等。这些标签在创立的时候就通过环境变量注入进去,而 podid 这些环境变量利用的是 k8s 的 downward api 的形式注入的。
留神:这里不可用应用 promtail 的服务发现机制配置标签,因为 promtail 的服务发现的原理是申请 APIServer 获取所有 pod 的标签。而后利用门路进行匹配,将标签与日志关联。在没有挂载宿主机 /var/log/pods 目录到 promtail 时,即便拿到了标签也无奈与日志进行关联。
2、⏰ promtail 在数栈如何部署
为每个服务减少一个 Log Container 如果手工操作的话切实是太繁琐了,而且不利于保护。最好的形式就将本来的服务形象为是注册一个 CRD,而后编写 k8s operator 通过 list&watch 该类型的对象,在该对象创立的时候,动静的注入一个 LogContainer,以及相应的环境变量和为其挂载独特目录。
这样当该 CR 创立的时候,promtail 就作为 sidecar 注入了其中。并且读到的环境变量就是 operator 动静设置的环境变量,灵便度十分高。
四、总结
(一)数栈日志收集劣势
- 一套日志聚合剖析框架解决主机与云原生两种场景,缩小了零碎复杂度
- 日志可视化采纳 grafana,可视化成果较好,而且 grafana 与 prometheus 曾经是云原生监控的是事实上的规范了,开发运维都比拟相熟,缩小了学习老本
- loki 查问语法简略,然而功能强大
- 与 ELK 相比,更加轻量级
(二)✈️将来布局
- 以后应用 sidecar 模式,资源占用较多,后续思考在进一步优化
- loki 分布式部署优化
最初给大家分享一下数栈以后日志模块可视化的成果,是不是超级酷炫?