霍秉杰、马丹 分布式实验室
日志通常含有非常有价值的信息,日志管理是云原生可观察性的重要组成部分。不同于物理机或虚拟机,在容器与 Kubernetes 环境中,日志有标准的输出方式(stdout),这使得进行平台级统一的日志收集、分析与管理水到渠成,并体现出日志数据独特的价值。本文将介绍云原生领域比较主流的日志管理方案 EFK、 KubeSphere 团队开发的 FluentBit Operator 以及 KubeSphere 在多租户日志管理方面的实践。此外还将介绍受 Prometheus 启发专为 Kubernetes 日志管理开发,具有低成本可扩展等特性的开源软件 Loki。近年来随着以 Kubernetes 为代表的云原生技术的崛起,可观察性(Observability)作为一种新的理念逐渐走入人们的视野。云原生基金会(CNCF)在其 Landscape 里已经将可观察性单独列为一个分类,狭义上主要包含监控、日志和追踪等,广义上还包括告警、事件、审计等。在此领域陆续涌现出了众多新兴开源软件如 Prometheus、Grafana、Fluentd、Loki、Jaeger 等。
日志作为可观察性的重要组成部分,在开发、运维、测试、审计等过程中起着非常重要的作用。著名的应用开发十二要素中提到:“日志使得应用程序运行的动作变得透明,应用本身从不考虑存储自己的输出流。不应该试图去写或者管理日志文件。每一个运行的进程都会直接输出到标准输出(stdout)。每个进程的输出流由运行环境截获,并将其他输出流整理在一起,然后一并发送给一个或多个最终的处理程序,用于查看或是长期存档。”
在物理机或者虚拟机的环境中,日志通常是输出到文件,并由用户自己管理,这使得日志的集中管理和分析变得困难和不便。而 Kubernetes 、Docker 等容器技术直接将日志输出到 stdout,这使得日志的集中管理和分析变得更为便捷和水到渠成。
Kubernetes 官网文档给出的通用日志架构如下图所示,包含日志 Agent,后端服务和前端控制台等三个部分。无论是成熟的日志解决方案如 ELK/EFK , 还是云原生领域 2018 年开源的 Loki 都具有相似的架构,下面将分别介绍 ELK/EFK、Loki 以及 KubeSphere 在这方面的贡献。
https://kubernetes.io/docs/concepts/cluster-administration/logging/
新旧*的联姻:从 ELK 到 EFK,从 Fluentd 到 Fluent Bit
https://docs.fluentbit.io/manual/about/fluentd_and_fluentbit
可以看到 Fluent Bit 比 Fluentd 占用资源更少,更适合作为日志收集器;而 Fluentd 插件非常多,更适合作为日志的聚合器。
FluentBit Operator 及其在 KubeSphere 中的应用
https://github.com/fluent/fluent-bit/pull/842
https://github.com/fluent/fluent-bit/issues/365
为了解决上述问题,KubeSphere 团队开发了 FluentBit Operator 并将其应用到 KubeSphere 中作为日志收集器。FluentBit Operator 架构及原理如下图所示:
在 FluentBit Pod 的主 Container 里加入 FluentBit Controller 进程控制 FluentBit 主进程的启停;
加入 ConfigMap Reload Sidecar Container 用于监控 FluentBit 配置文件所在 ConfigMap 的变化,并在监测到变化的时候调用 FluentBit Controller 的 reload 接口: http://localhost:24444/api/config.reload;
接下来 FluentBit Controller 将重启 FluentBit 主进程以达到加载新的配置文件的目的。
FluentBit Operator 架构图
在 KubeSphere 中,选择 Elasticsearch 作为日志后端服务,使用 Fluent Bit 作为日志采集器,KubeSphere 日志控制台通过 FluentBit Operator 控制 FluentBit CRD 中的 Fluent Bit 配置。(用户也可以通过 kubectl edit fluentbit fluent-bit 以 kubernetes 原生的方式来更改 FluentBit 的配置)
KubeSphere 日志系统架构图
通过 FluentBit Operator,KubeSphere 实现了通过控制台灵活的添加/删除/暂停/配置日志接收者。
KubeSphere 日志配置界面
KubeSphere 日志搜索界面
多租户日志管理
可以看到 KubeSphere 是基于 RBAC 的 3 层多租户架构,Cluster/Workspace/Project 三个层级均有不同级别的 Roles 与之对应。
在能访问到日志数据(或其他服务)之前,需要经过 API Gateway 的认证与授权:
KubeSphere 完整的日志解决方案如下:
云原生的亲儿子 Loki:Like Prometheus, but for logs
云原生领域一直期待有一款由 Go 开发的日志管理软件,Loki 应运而生。Loki 自 2018 年 12 月发布短短 10 个月的时间,Github 上的 Star 数已经达到了 7000+。Loki 由开发 Grafana 的 Grafana Labs 开发,Grafana Labs 中有著名云原生监控软件 Prometheus 的开发者并且提供了云端的 Prometheus 监控服务 Cortex , 而 Loki 正是受到 Prometheus 的启发而开发出来的。因此具有许多和 Prometheus 类似的特性比如:与 Kubernetes 紧密集成、与 Prometheus 共享 Label,与 Prometheus 有相似查询语法的查询语言 LogQL,与 Prometheus 类似的查询函数等,甚至同样可以在 Grafana 里直接查看检索 Loki 的日志数据。除此之外 Loki 的还与 Cortex 共享了很多组件,非常容易水平扩展。
Loki 最重要的特性是存储成本低,资源占用少。Loki 做到这点是在设计之初就有意解决 Elasticsearch 占用资源多的缺点,通过只对 Label 等元数据进行索引,对日志流数据进行压缩存储,并在用户搜索日志文本时通过索引的 Label 缩小查询范围后,实时解压并用类似 grep 一样的机制对日志流数据进行过滤。如下图所示,Loki 的组件包括收集数据的 Agent Promtail , 接收数据的 Distributor,缓存数据以便批量写入的 Ingester,用于查询数据的 Querier,这些组件均可以根据负载水平扩展并实现高可用。
Loki 架构(来源于 Grafana Labs 官方博客)
如下图所示,Loki 的实现了索引和日志数据块分别用不同的存储介质存储,索引可以存到 Cassandra, BoltDB 等;日志数据块可以存到本地磁盘或者云端对象存储或者兼容 S3 协议的 Minio。如此在实现海量日志数据的低成本存储的同时,还能够满足用户快速查询日志的需求。
Loki 存储(来源于 Grafana Labs 官方博客)
作为云原生时代出现的日志解决方案,Loki 以其低成本、可扩展和高可用以及与 Kubernetes, Prometheus 紧密集成等特性迅速获得了巨大关注,有望在 Kubernetes 上获得如同 Prometheus 一样的地位,成为云原生领域日志管理的事实标准。
展望