搭可观测性平台,为什么是 LGTM 拼出来的,不是一个 all-in-one
可观测性平台不是选一个"最强工具"就能搭起来的,日志、指标、告警、采集这几层每一层的取舍标准都不一样。这篇讲清楚为什么放弃 all-in-one 方案改用 LGTM 拼装、为什么指标选 VictoriaMetrics、告警为什么要拆成两套、OTel Collector 的采集层怎么分工。
搭可观测性平台,最开始会被”要不要选一个大而全的方案”这个问题绊住——市面上确实有把日志、指标、链路一锅端的产品,看起来能省掉拼装几个组件的麻烦。但真正落地之后发现,日志、指标、告警、采集这几层各自的取舍标准完全不一样,硬塞进一个方案里,早晚要在某一层上吃亏。
整体架构大致是这样,从上到下走一遍数据流转:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Pod stdout/stderr Pod 持久化文件日志 K8s API / Events 应用 Traces (OTLP)
│ │ │ │
▼ ▼ ▼ │
Node Collector fluent-bit Cluster Collector │
(DaemonSet, Helm) | (Deployment, Helm) │
主机指标 / 日志 | 集群事件 / 集群级指标 │
│ │ │ │
└────────────────────┴──────────────────┴──────────────────┘
│
▼
OTel Gateway (CRD)
采样 / 脱敏 / 路由 / 凭证收敛
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
Loki VictoriaMetrics Tempo
(日志) (指标) (链路追踪)
│ │ │
└───────────────────┼───────────────────┘
▼
Grafana
Node Collector 和 Cluster Collector 是平级的两个采集器,分别对应节点级和集群级两类数据,都用 Helm Chart 部署;Pod 自己写到磁盘上的持久化日志文件另有一条路径,走 fluent-bit 采集;应用产生的链路追踪数据走 OTLP 直接上报。这几路数据最终都汇总到 Gateway 这一层,再由 Gateway 分流到 Loki、VictoriaMetrics 和 Tempo。
为什么选 OTel 做采集层
先要说清楚一点:OTel 和 LGTM 不是二选一,两个不在同一层。LGTM 是存储和查询层,OTel 是采集和传输层,架构上是”OTel 采集 → LGTM 存储”,两个都用了,而且 Loki/VictoriaMetrics/Tempo 现在都原生接收 OTLP,OTLP 本身就是 LGTM 的入口协议。真正要决策的是采集层用什么,不是要不要 LGTM。
采集层选 OTel 而不是给每个后端配一个专用采集器(Promtail 配 Loki、vmagent 配 VictoriaMetrics),核心考量是:后端换起来容易,重新接一份数据、Grafana 改个数据源就行,业务侧无感;采集层换起来是灾难,它散布在每个节点的 DaemonSet、每个 Pod 的 sidecar、每个应用的插桩代码里。用专用采集器就等于把后端和采集层焊在一起,后端一换,所有节点的配置都要跟着改。OTel 作为厂商中立的标准协议,采集层和后端解耦,换后端不用动采集这一层。这跟下面选 LGTM 拼装、不选 all-in-one 是同一个判断标准,只是这次用在了采集层上。
为什么是 LGTM,不是 all-in-one
选型阶段对比过几个 all-in-one 方案:
| 方案 | 优势 | 短板 |
|---|---|---|
| OpenObserve | Rust 实现,性能好、资源占用低,支持 SQL 语法查询,日志/指标/链路/看板/告警这些基础功能开源版本身是齐全的 | RBAC、SSO 这类多租户权限能力开源版不支持(所有用户拥有全部权限),要用得靠自托管 Enterprise 版,且免费额度有用量上限 |
| SigNoz | Go 后端 + React 前端,功能齐全 | 强绑 ClickHouse,等于把平台稳定性又绑到另一个重型组件上 |
| SkyWalking + BanyanDB | 概念上简单 | 不通用也不成熟,实际部署过程中一直报错没能跑起来;BanyanDB 到现在还没发布 1.0,社区原计划的 GA 时间也已经推迟,生产用还太早 |
最后选的是 LGTM 拼装方案,各组件分工:
| 组件 | 管什么 |
|---|---|
| Loki | 日志,压缩率高 |
| Grafana | 统一可视化 |
| Tempo | 链路追踪 |
| M(VictoriaMetrics) | 指标 |
拼装的代价是多一层组件间的对接工作,换来的是每个组件在自己的领域里都是经过大规模验证的成熟方案,不用担心某个小众组件在生产里掉链子。这跟”选一个够用的独立组件,比选一个大而全但某一块不够硬的方案更稳”是同一个判断标准。
指标为什么选 VictoriaMetrics,不是 Prometheus 或 Mimir
三者都能存指标、跑 PromQL,但适用场景不一样:
| Prometheus | Mimir | VictoriaMetrics(集群版) | |
|---|---|---|---|
| 定位 | 单机时序数据库,原生不支持长期存储和透明的水平扩展(federation、分片这些手段存在,但用起来麻烦) | 在 Prometheus 生态上做了长期存储和水平扩展,支持 monolithic 单进程模式(-target=all),也能横向部署多个该模式实例做扩展,不强制走全套微服务拆分 | 独立实现的时序数据库,天生支持集群模式 |
| 多租户 | 不支持,一套实例对应一套数据 | 支持,按租户隔离 | 开源版支持基础隔离,读写都带 accountID;但按租户设不同保留期、按租户限流这类更精细的多租户能力是 Enterprise 功能 |
| 协议/许可 | Apache 2.0 | AGPL-3.0,商业化上有额外限制,选型时要单独评估 | 集群版 Apache 2.0 开源 |
| 生态兼容 | PromQL 生态的源头,兼容性最好 | 兼容 PromQL,接口对齐 Prometheus | 兼容 PromQL 和 Prometheus 的 remote_write/HTTP API,迁移成本低 |
| 部署复杂度 | 简单,单体即可 | monolithic 模式下不比 VictoriaMetrics 复杂,但要用到 store-gateway/compactor 这类长期存储能力时会趋向微服务拆分 | 中等,读写分离,组件数量比 Mimir 全量微服务模式少 |
选 VictoriaMetrics 的核心权衡是:比 Prometheus 多了长期存储和多租户能力,又不用为了拿到 Mimir 那种水平扩展能力而承担 AGPL-3.0 的许可限制。读写路径是分离的,写入压力大的时候不会拖累查询,查询复杂的时候也不会拖累写入,两条链路互不干扰。多租户在开源版里也是原生支持的,上报和查询都带一个 accountID,不同业务线的指标从物理上就是隔离的,不需要在应用层自己拼前缀去区分——如果诉求进一步到”不同业务线要设不同保留期”或”按租户限流”,那部分能力目前只在 Enterprise 版里。
告警为什么拆成两套,而不是一套管到底
告警没有走”一个系统管所有规则”的路子,按告警的性质拆成了两层:
| vmalert | Grafana Alerting | |
|---|---|---|
| 管什么 | 机器 CPU/内存/磁盘、K8s 节点状态、Grafana 自身存活检测 | 错误日志数量、接口响应变慢、业务订单量下跌 |
| 改动频率 | 低,配置好基本不用再动 | 高,业务变化时需要开发自己调整 |
| 设计目标 | 跟 UI 解耦,保命 | 协作方便,规则迭代快 |
| 依赖 | 部署位置独立于被监控对象——vmalert 只做规则求值,通知交给 Alertmanager,链路不经过 Grafana,Grafana 挂了不影响这条链路 | 依赖 Grafana 的 UI 做规则维护 |
拆开的核心逻辑是:谁该稳定、谁该灵活,不是同一套标准。保命的告警链路要尽量少依赖可视化层,追求的是可靠;业务告警改动频率高,需要开发自己上手改,追求的是好用。需要说清楚的是,vmalert 这条链路也不是零依赖——它查询的数据本身来自 VictoriaMetrics,如果磁盘满到连 VictoriaMetrics 都写不进去,vmalert 一样会查不到数据、跟着哑掉,”保命”说的是不依赖 Grafana 这层可视化,不是不依赖任何组件。把这两种诉求塞进同一套告警系统里,要么牺牲可靠性,要么牺牲协作效率。
OTel Collector:Agent 层和 Gateway 层为什么用不同工具管
采集层用的是 OpenTelemetry Collector,分 Agent 和 Gateway 两层部署,这两层选的部署工具也不一样:
| Agent 层 | Gateway 层 | |
|---|---|---|
| 部署工具 | Helm Chart | Operator CRD |
| 职责 | 采集,细分两个采集器:一个 DaemonSet,每个节点一份,采主机指标和日志;一个单副本 Deployment,采集群级别的 metrics 和事件 | 集中做采样、脱敏、路由 |
| 选型理由 | preset 把常见的 K8s 采集场景封装成了开箱即用的配置项,DaemonSet 那份靠 preset 采主机指标、日志,Deployment 那份靠 preset 采集群事件和集群级 metrics,两者都不用从零手写 receiver 和权限配置 | 弹性伸缩和配置变更是声明式托管的,贴合这层”规则本身会经常调整”的特点,同时把往后端写数据用的认证凭证收敛到这一层集中管理——不然认证方式一变,所有节点上的 Collector 配置都要跟着改一遍 |
Agent 层内部按”节点级”和”集群级”拆成了两个采集器,是因为这两类数据的采集方式本来就不一样:主机指标、日志是每个节点各采各的,天然适合 DaemonSet;集群事件、集群级 metrics 只需要采一份,起一个 Deployment 单副本就够,起多份反而会重复采集。这两个采集器都是标准化程度很高的场景,用 Helm Chart 的 preset 覆盖就够了。
同一个 OpenTelemetry 生态,Agent 层和 Gateway 层选了两种部署工具,依据不是谁更先进,是两层各自要解决的问题不一样:一层要的是标准化采集的现成能力,一层要的是配置常变时的弹性和凭证集中管理。
小结
从日志/指标/链路选 LGTM 拼装,到指标选 VictoriaMetrics 的读写分离,到告警拆成保命层和业务层两套,再到采集层 Agent/Gateway 用不同工具管——每一层的选型标准都不一样,共同点是没有哪一层是照抄一份”最佳实践”配置就定下来的,都是先看清楚这一层真正要解决什么问题,再决定用什么工具、用什么架构去管它。
这篇讲的是集群侧怎么把数据采起来、送到哪,应用自己那一侧要怎么配合——日志该走 stdout 还是显式挂卷、链路追踪怎么接入 SDK——是另一个问题,留给下一篇讲应用侧的采集选型和方案。