深入 Kibana 00 - 导读:Kibana 的状态存在 Elasticsearch 里
Kibana 常被介绍为"Elasticsearch 的图形界面"或"ES 的可视化前端"。这个说法把 Kibana 的位置放低了一层,也解释不了几个基本现象:为什么 Kibana 要自带一个 Node.js 服务,而不是像 Kibana 3 那样纯浏览器直连 ES?为什么在浏览器里保存一张 Dashboard,会往 Elasticsearch 里写一条数据,而这条数据又不出现在业务索引里?为什么升级 Kibana 大版本时,它会在启动阶段做一轮"迁移",动的却是 ES 里的某些系统索引?
更准确的说法是:Kibana 是一个后端在 Elasticsearch、前端在浏览器、而自身状态也存在 Elasticsearch 里的三层应用平台。用户在界面上建的每一个 Data View、拖的每一张可视化、组的每一个 Dashboard、配的每一条告警规则,都不是存在浏览器本地、也不是存在某个独立数据库,而是以 Saved Object 的形式写进以 .kibana 为前缀的系统索引。Kibana 把 Elasticsearch 同时当成两样东西用:业务数据的查询后端,以及自身配置的持久化存储。
本系列只抓一个问题:Kibana 这套"把自身状态托管在 Elasticsearch 里、把 ES 的查询与聚合能力包装成数据视图 + 交互式查询 + 可复用保存对象"的应用平台,是如何在 Discover、Lens、Dashboard、Alerting 等场景里具体展开的,每个机制里有哪些可以迁移到其他 BI、可观测性、低代码平台的设计模式。
Kibana 不是一直有 server 的
理解 Kibana 当前的架构,要先看它没有 server 的那个版本。
Kibana 3 是一个纯前端应用。它是一堆 Angular 写的静态 HTML/JS,部署方式就是丢到任意 Web 服务器(甚至可以直接塞进 Elasticsearch 的 site plugin)里。浏览器加载页面后,直接向 Elasticsearch 的 REST 接口发查询请求,把返回的聚合结果画成图。这个架构没有任何服务端逻辑,也就没有地方存放"这张 Dashboard 长什么样"——早期 Kibana 3 把 Dashboard 定义反过来存进了 Elasticsearch 的一个索引(kibana-int),这已经埋下了后来"状态存在 ES 里"的种子。
从 Kibana 4 起,架构里多了一个 Node.js server。这一步不是为了好看,而是几个纯前端架构解决不了的需求推着走的:
浏览器直连 ES 意味着 ES 的地址和凭据必须暴露给浏览器,任何打开页面的人都能拿到直连集群的能力。加一个 server 之后,浏览器只和 Kibana server 说话,凭据留在服务端。
Dashboard、可视化这类配置需要一个统一的、带版本管理的持久化和迁移机制,而不是散落在前端各自为政地读写索引。server 端出现后,这套逻辑被收拢成后来的 Saved Object 服务。
报表导出(headless Chromium 渲染 PDF)、告警规则的定期执行、后台任务调度这类工作天然属于服务端,浏览器关掉页面它们还得继续跑。
到了 New Platform(Kibana 平台重构,7.x 期间逐步落地),server 端和前端都被组织成统一的插件模型,每个插件有对称的 setup / start 生命周期,Discover、Lens、Alerting 全部是平台上的插件。这一步是把"Kibana 是一个应用平台"这件事在代码结构上坐实。
一个必须避免的常见错误是:拿 Kibana 3 的纯前端架构去描述今天的 Kibana。当前版本的 Kibana 一定有一个 Node.js server,浏览器不直连 ES,所有查询和保存都经过 server 中转。
Saved Object:Kibana 一切状态的统一模型
把"状态存在 ES 里"这件事讲清楚,需要一个统一的数据模型。Kibana 的答案是 Saved Object。
一个 Saved Object 有三段结构:
1 | |
type 决定这是什么东西。attributes 是它自己的内容。references 是它指向的其他对象——这一段是关键。在 Kibana 里保存一张 Dashboard,本质是往 .kibana 系统索引写一条 type 为 dashboard 的 Saved Object,它的 references 数组指向若干个 visualization,而每个 visualization 又通过自己的 references 指向一个 data view。整个 Kibana 的状态因此不是一堆孤立记录,而是一张以 references 连起来的有向图。
这张引用图解释了几个平时看起来奇怪的行为。删掉一个被 Dashboard 引用的 Data View,Dashboard 不会跟着消失,只会在打开时报"找不到引用的对象",因为 references 里那条指针悬空了。导出一张 Dashboard 时,Kibana 默认会顺着 references 把它依赖的 visualization、data view 一起打包,因为只导出 Dashboard 自身,换一个集群就是一堆断掉的指针。
Saved Object 还解决了升级问题。Kibana 大版本升级时,可视化配置的字段结构可能变化。Kibana 在启动阶段跑一套 Saved Object 迁移框架,按对象 type 逐条把旧结构改写成新结构,写进新的系统索引。这就是升级时那轮"迁移"动的东西——不是业务数据,是 Kibana 自己的状态。
需要区分 Saved Object 和普通 ES document。普通 document 是业务数据,schema 由用户的 mapping 决定,Kibana 只负责查询它。Saved Object 是 Kibana 的内部状态,有固定的类型体系、有引用关系、走 Kibana 的迁移框架,用户通常不直接读写它对应的索引,而是通过 Kibana 的 Saved Objects API。
关于存储位置有一个版本敏感的细节需要说明。早期 Kibana 把几乎所有状态放在单个 .kibana 索引里。随着功能变多,这些系统索引被按用途拆分:task manager 的任务很早就独立成 .kibana_task_manager,8.x 期间又进一步按分析、告警、安全等用途拆成多个以 .kibana 为前缀的索引。本系列在需要精确到索引名时,会以当前 Kibana 官方文档的 saved objects 页面为准,不对具体拆分做全称断言。可以稳定依赖的事实是:Kibana 的状态存在以 .kibana 为前缀的一组系统索引里,而不是别的地方。
一条主线压住整个系列
把这个观察压成一句话:
1 | |
后续每篇都在展开这条主线下的一个子问题。平台架构篇(01-04)展开 server 结构、Saved Object 模型、Data View 字段抽象和三种查询语法到 Query DSL 的翻译。查询与可视化篇(05-09)展开 Discover 的执行模型、聚合式可视化、Lens 的自动推断和 Dashboard 的 Embeddable 组合。告警上报篇(10-12)展开 Alerting 的 Rule/Connector/Action 三段契约、Reporting 的渲染链路和 Task Manager 调度。平台安全扩展篇(13-15)展开 Spaces、RBAC、插件生命周期和性能模型。演进对比篇(16-17)把 Kibana 和 Grafana 放在一起看两种可视化平台的设计取舍,并回顾从纯前端到 Serverless 的演进。
实验:让 .kibana 现身
有两个零成本的观察,能把"状态存在 ES 里"从说法变成看得见的东西。第一个是查询系统索引的存在,第二个是用 Saved Objects API 看一个对象的三段结构。
在 Kibana 的 Dev Tools(Management → Dev Tools)里,先确认这组系统索引的存在和规模:
1 | |
输出会列出若干以 .kibana 开头的索引,以及它们的文档数。这些文档就是当前 Kibana 的全部配置状态。需要注意,8.x 起系统索引受保护,不建议也不总是允许直接对 .kibana 发 _search 去改数据;查看和管理 Saved Object 的受支持方式是 Kibana 的 Saved Objects API 或界面上的 Stack Management → Saved Objects。
接着用 Saved Objects API 看一个具体对象的结构。下面这个请求(走 Kibana 的 HTTP 接口,不是直接打 ES)列出所有 data view 类型的 Saved Object:
1 | |
返回的每条记录都能看到 type、attributes、references 三段。找一张 Dashboard 看得更清楚:
1 | |
在返回的 references 数组里,可以直接读到这张 Dashboard 指向了哪些 visualization 和 index-pattern。这就是前面说的引用图的一条边。
第三个是思想实验,不需要真的执行:如果删掉 .kibana* 这组系统索引会发生什么。答案是 Kibana 里所有 Data View、可视化、Dashboard、告警规则全部消失,Kibana 会像全新安装一样重建空的系统索引;但业务数据索引一条不少,因为那是另一回事。反过来,删掉某个业务索引,Dashboard 定义还在,只是打开时查不到数据。这一对照精确地划出了 Kibana 状态和业务数据的边界。
模式提炼
Kibana 的整套设计可以提炼成一个可迁移到其他平台的模式:
1 | |
这个模式不是 Kibana 独有。低代码平台把每个页面、组件、数据源建模成节点,用引用关系组成组件树,是同一套思路在应用搭建场景的具体化。BI 工具把数据集、图表、看板做成可复用对象并管理它们之间的依赖,是同一套思路在报表场景的具体化。把配置当作"托管在主存储里的一等对象"而不是散落的文件,这一点比 Kibana 任何一个具体面板都更值得带走。
工程迁移表
| Kibana 概念 | Grafana 对应 | BI 工具对应 | 低代码平台对应 |
|---|---|---|---|
| Saved Object(统一状态模型) | Dashboard JSON model | 报表 / 数据集对象 | 页面 / 组件节点 |
| references(对象引用图) | Panel → DataSource 引用 | 图表 → 数据集依赖 | 组件树父子 / 数据绑定 |
| Data View(查询前的字段抽象) | DataSource + query | 数据集 / 语义层 | 数据源配置 |
| Kibana server(服务端中转) | Grafana server | BI server | 低代码运行时 |
| Saved Object 迁移框架 | schema 版本迁移 | 元数据升级 | schema/DSL 版本迁移 |
.kibana 系统索引(状态存储) |
Grafana 自带 DB(SQLite/PG) | 元数据库 | 元数据库 |
注意 Kibana 和 Grafana 在最后一行的差异。Grafana 默认把自身状态存在一个独立的关系型数据库里(SQLite 或 PostgreSQL 等),数据源是外挂的、多种多样的。Kibana 把自身状态存回它唯一深度绑定的后端 Elasticsearch。这一个选择的分叉,后面对比篇(第 16 篇)会展开:它同时是 Kibana 与 ES 深度集成的红利,也是 Kibana 不能像 Grafana 那样轻松接多种数据源的代价。
常见误解
误解一:“Kibana 就是 ES 的 GUI”。这个说法忽略了 Kibana 自带服务端、自带状态存储、自带告警和上报这一整层。ES 的 GUI 只需要浏览器直连查询即可,那是 Kibana 3 的形态。当前的 Kibana 是一个有独立生命周期的应用平台,ES 是它的后端之一(既是业务数据后端,也是自身状态后端)。
误解二:“我保存的 Dashboard 存在浏览器 / 本地”。它存在 Elasticsearch 的 .kibana 系统索引里,是一条 Saved Object。换一台电脑、换一个浏览器登录同一个 Kibana,Dashboard 还在,就是这个原因。
误解三:“Data View 就是 ES 索引”。Data View(7.x 及更早叫 Index Pattern)是 Kibana 侧的一层抽象,它绑定一个或一组索引,额外定义了时间字段、字段格式化、运行时字段等。删掉一个 Data View 不会删掉底层索引,只是 Kibana 少了一个查询入口。第 03 篇会专门展开这层抽象。
误解四:“KQL 就是 Elasticsearch 的查询语言”。KQL 是 Kibana 提供的查询语法,它最终会被翻译成 Elasticsearch 的 Query DSL。同样能在搜索框里用的还有 Lucene query string。三者的翻译关系是第 04 篇的主题。把 KQL 当成 ES 原生查询语言,会解释不了为什么同样的过滤条件在 Dev Tools 里要写成完全不同的 JSON。
练习
-
在能访问的 Kibana 上打开 Dev Tools,运行
GET _cat/indices/.kibana*?v,记下当前有几个以.kibana为前缀的系统索引、各自多少文档。再运行GET api/saved_objects/_find?type=dashboard,挑一张 Dashboard,读它的references数组,画出它指向的 visualization 和 data view 的引用图。 -
建一个新的 Data View,再基于它建一张可视化并保存。用 Saved Objects API 找到这张可视化,确认它的
references里确实有一条指向刚才那个 Data View。然后删掉这个 Data View,重新打开可视化,观察 Kibana 报什么错——把报错和"references 指针悬空"对上。 -
思考题:Grafana 把自身状态存在独立数据库、数据源外挂,Kibana 把自身状态存回 Elasticsearch。分别列出两种选择在"多数据源支持"“升级迁移”“部署复杂度”"与后端的集成深度"四个维度上的得失。这个对比会在第 16 篇展开,先自己给一版答案。
系列导航
| 序号 | 主题 | 状态 |
|---|---|---|
| 00 | 导读:Kibana 的状态存在 Elasticsearch 里 | 本篇 |
| 01 | Kibana 架构:浏览器、Node.js server 与 New Platform | 下一篇 |
| 02 | Saved Object:Kibana 一切状态的统一模型 | |
| 03 | Data View(Index Pattern):查询之前的字段抽象 | |
| 04 | Search Source 与查询翻译:KQL、Lucene 与 Query DSL | |
| 05-09 | 查询与可视化(Discover / Visualize / Lens / TSVB / Dashboard) | 后续阶段 |
| 10-12 | 告警、上报与自动化(Alerting / Reporting / Task Manager) | 后续阶段 |
| 13-15 | 平台、安全与扩展(Spaces & RBAC / 插件体系 / 性能模型) | 后续阶段 |
| 16-17 | 演进、生态与对比(Kibana vs Grafana / 从纯前端到 Serverless) | 后续阶段 |
《深入 Elasticsearch》系列是本系列的后端基座,Kibana 的每个查询都落到 ES 上,涉及倒排索引、聚合、Query DSL 的地方会交叉引用该系列。
参考资料
- Kibana 官方文档:https://www.elastic.co/guide/en/kibana/current/(Saved Objects、Data View、Dev Tools 各章为本篇事实基线)
- Kibana Saved Objects 文档:https://www.elastic.co/guide/en/kibana/current/managing-saved-objects.html(type / attributes / references 与迁移框架)
- Kibana 源码仓库:https://github.com/elastic/kibana(New Platform 的 setup/start 生命周期、saved_objects 服务实现)
- Elasticsearch 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/(后端基座)
- 仓库内《深入 Elasticsearch》系列:作为后端机制的交叉引用来源
- Grafana 官方文档:https://grafana.com/docs/(用于第 16 篇对比)


