微服务早已是一个过时的热词,同时,容器 和 k8s 的出现让它更一步成为了一种时尚。同样会带来很多附赠的问题,日志收集就是其中一个比较重要的问题。当应用容器化之后,需要查看日志,如果还需要登录服务器,找到对应目录,然后 tail 查看,成本太高了,极大的影响效率。当前其实日志收集方案很多,在实践了多个方案之后,我终于能在今天写出我个人认为我最喜欢的一个方案了 loki

我的需求

技术上没有银弹,需要根据实际需求来选择方案,那么我的需求是这样的,你可以做个比较:

  1. 当前所有的应用是部署在 k8s 中的,需要收集所有的应用的日志到一个地方做展示
  2. 部署最好要轻量,对于性能要求并不高(当前日志量并不大)
  3. 日志展示方式友好,能支持基本的时间查询,或者是定位到某个关键字

可选方案

从之前的公司包括个人的一些项目上都尝试过很多不同的组合和方案,列举出三个最具有可比性的方案:(以下为个人使用案例,并不能代表所有大众观点,图片来源本地测试服,线上日志不允许公开,但同样禁止转载~)

ELK

ELK

这似乎是业界最成熟的日志收集方案之一了,因为无论你问哪个有点经验的程序员,提到日志收集,必然会给到这个,我当然不是说这个方案不行,因为我知道很多公司都采用了这个方案,并且稳定运行着,所以这个方案我也尝试去使用过,带来的问题有下面几个:

  1. 部署并不容易,当前现在已经好很多了,当年确实手工部署比较困难,会有很多意外
  2. 占用资源过多,特别是 logstash,懂得都懂
  3. ES 使用比较困难,上手成本比较高,因为并不是所有的开发对于 ES 的使用都是熟练的,包括我自己都是需要查看文档之后才能回忆起来很多操作

当然后面改进了:变成了 EFK

其中的 F 可以是 filebeat、fluentd、fluent-bit 这样日志采集的部分可以占用更少的资源,使用上会更加轻量一些,所以,其实现在 EFK 算是一个通用的商业日志收集的解决方案了。我觉得如果是一个中型或者大型的项目可以使用这样成熟的解决方案,没有问题。

FIC

FIC 可能小众一些,但是这是我第二个使用上来说对于我来说使用下来感觉不错的方案:fluentbit + influxdb + chronograf

其实我蛮喜欢 influxdb 这家公司出品的东西的,使用感觉还不错,因为 influxdb 作为一个时序数据库来说其实非常轻量了,部署也很方便,配置上面也比较简单,主要还是日志收集上面的配置,并且 influxdb 的使用比起 es 来说理解起来更加的简单一点,更容易上手

chronograf

部署方式:https://www.jianshu.com/p/c5faf3c10bce

在使用的 FIC 的时候,我发现它对于单体应用还是相当友好的,搭建使用都非常舒服,并且 chronograf 的页面比 kibana 个人认为要舒服很多,简洁。当然也有它自己的问题:

  1. influxdb 还是比较吃内存的
  2. 日志量大的时候 chronograf 明显第一次进去会卡,不知道现在优化没有,然后如果当入库数据异常的时候其实页面会报错的:之前我提过 issue 应该已经修复
  3. 日志关键字搜索的时候会卡,准确的说比较慢
  4. 其实 fluentbit 对于多行日志的处理很鸡肋,因为每家每户的日志格式其实不太一样,公司内部日志格式都不一样,我还尝试重新自己造过轮子,发送到 influxdb ,后面才发现 filebeat 也能满足要求。
  5. tag 会爆炸,塞日志的时候,如果日志量巨大,因为会根据日志级别打 tag 建立索引,而 influxdb 是有默认限制的,所以当时也踩了坑,调整了配置后得以解决

但是 其实 FIC 对于系统日志也就是 syslog 的监控还是有着自己独特的一面,有机会你可以尝试一下,还是相当不错的,这个方案我也使用了一段时间了。

Loki

这是我当前使用过一段时间之后,最终认可的一个方案:https://github.com/grafana/loki

其实在使用 FIC 的时候我就犹豫过当时要不要使用 loki 犹豫当时的公司内部没有大力推 k8s ,多数都是 docker-compose 的使用,更多的是小单体居多的。而当时 loki 也是没有很多的实际使用经验,不敢往上推,怕出问题。但是后面有了机会实践之后就真香了。

其实 loki 包含三个组件:

  1. Promtail:日志收集工具
  2. Loki:日志聚合系统
  3. Grafana:可视化工具

grafana 其实很熟悉了,很多监控展示都用到它了,用起来也相当的舒服,有很多的展示方式,当时在比较的时候,当初 grafana 还只有表格展示模式,所以就比较尴尬,后面出现了 log 模式就很舒服了。

grafana

我觉得 loki 让我舒服在下面几个点:

  1. k8s 内部署非常方便,几乎是一个 helm 就能部署好了,不需要额外的配置,默认的配置已经足够日常的使用了
  2. 能筛选到某应用,甚至到某个 pod 的日志,查问题的时候非常方便
  3. 支持关键字搜索,我甚至不需要调整原有的日志格式,就能有很好的支持,如果调整输出日志的格式为官方推荐的 logfmt 的话可能更加靠谱
  4. 日志数据本身会被压缩,使用成本低
  5. 几乎没有入侵:我没有调整日志格式,不需要建立特定的 sidecar 去监控日志也就不需要改动原有的 deployment 的 yaml 配置,就是使用 loki 不需要我改动什么就能用起来

但是毕竟没有 ES 那么多建立的索引,当日志量大的时候搜索没有那么快,但是也足够满足我的要求了,足够用了。(当然如果调整loki一些参数如缓存等可以大大加快查询速度,个人没有调整,已经足够使用)

虽然网上见到有吐槽过性能的,但是目前个人使用下来暂时没有遇到瓶颈。后面还会持续关注@TODO。

PS: 需要注意的是,你的应用日志需要输出到 stdout 中 这里有关 k8s 日志收集方案不做过多讨论,因为网上的方案大多三种,一种 stdout,一种挂 sidecar,一种用 DaemonSet 各有各的说法。

部署

官方已经给出了很多部署的方案,其中我选择的是 helm,非常轻松:https://grafana.com/docs/loki/latest/installation/helm/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 添加 repo 并更新
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update

# 注意这里后面是 -stack 的是默认打包好在一起的,没stack的是默认只有 loki 的,自定义安装请参考官网给出的命令
helm upgrade --install loki --namespace=loki grafana/loki-stack

# 安装 grafana
helm install loki-grafana --namespace=<YOUR-NAMESPACE> grafana/grafana

# 查看 grafana 的密码
kubectl get secret --namespace <YOUR-NAMESPACE> loki-grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

# 临时暴露 端口 进行访问测试
kubectl port-forward --namespace <YOUR-NAMESPACE> service/loki-grafana 3000:80

然后设置对应的 service 暴露出你需要使用的端口即可,其实非常容易操作。

使用 admin 和上面查看的 grafana 的密码即可进入,然后添加数据源选择 loki

loki-data-sources

注意这里的地址输入 http://loki:3100 即可,没有什么其他需要配置的。我真的觉得 so easy

如果没有意外,就可以使用 grafana 的 explorer 进行日志查看的了,前提是运行一段时间,让你的输出一些日志。

关键字检索

其实我一开始还担心没办法进行日志关键字检索,找了半天,才发现很简单,只需要在最上面的输入框中写入 {job="mysql"} |= "error" 其中的 error 就是你要找的关键字,就可以了,还有一些正则表达式这里就不多介绍了,explorer 打开的一开始有提示的。

总结

其他使用细节因为涉及具体生产使用,不方便截图,我将一些必要的的链接参考扔在下面,应该足够你使用了。

总的来说,我要的 loki 都有,并且部署方便,想要替换也很方便,直接删掉就好了,然后满足我日志查看的全部需求,而且占用资源情况也没有其他几个那么高,完美~ 后悔没有早点用上它。不过后面也会持续追踪使用情况,后面会再出一个有关使用过程中的坑点的博客。

参考链接

部署相关:https://blog.cong.moe/post/2020-07-27-use_loki_as_k8s_log_collector/

https://bbs.huaweicloud.com/blogs/200177

https://www.qikqiak.com/post/use-loki-monitor-alert/

https://www.qikqiak.com/post/grafana-loki-usage/

官方最佳实践:https://grafana.com/docs/loki/latest/best-practices/current-best-practices/

通过设定annotations只收集固定 pod 的日志:https://blog.csdn.net/kozazyh/article/details/102881301 (个人认为没有必要,这样对于 k8s 的 yaml 文件有入侵)

如何设置只收集固定 namespace 的日志:https://www.giantswarm.io/blog/grafana-logging-using-loki