用于 Kubernetes 监测的常用 ES|QL 查询

作者:来自 Elastic Jeffrey Rengifo

用于 Elasticsearch 的可复制粘贴 ES|QL 查询,将内存压力和错误峰值转化为五分钟诊断。

这篇文章包含九个用于在 Elasticsearch 中诊断 Kubernetes 问题的 ES|QL 查询。它们涵盖了崩溃循环的 pod、OOM kill 之前的内存压力、饱和的节点以及按命名空间划分的错误峰值。每个查询都针对使用 Elastic Distributio
ns of OpenTelemetry (EDOT)
收集的 Kubernetes 数据运行,并且几乎无需编辑即可粘贴到 Discover 中。找到所需的查询后,可以将其中任何一个转换为仪表板面板或告警。直接跳转到与你当前看到的问题匹配的查询,或者完整阅读整组查询,以了解你的集群情况。

运行这些 Kubernetes ES|QL 查询前需要什么

要跟随本文中的查询,你需要:

  • Elasticsearch 9.2 或更高版本。

  • 在你的集群中运行 EDOT Collectors,并将数据发送到 Elasticsearch,同时启用 kubeletstatsk8s_clusterfilelog 接收器。

为什么使用 ES|QL 进行 Kubernetes 监测

Elasticsearch ES|QL 是一种管道式查询语言,它允许你从数据源开始,然后每行添加一个操作:过滤、计算、聚合、排序。这种结构非常适合调查工作,因为当你逐步缩小问题范围时,可以一步一步细化查询。

何时使用 ES|QL TS 命令处理 Kubernetes 指标

TS 命令理解时间序列。这一点很重要,因为大多数 Kubernetes 指标都是随时间采样的计数器或测量值。对指标使用 TS 可以避免常见错误:在多个 pod 之间求和累计计数器,从而得到没有意义的数字。

这些 Kubernetes 查询依赖的 EDOT 接收器

下面的查询假设 EDOT Collectors 正在你的集群中运行,并将数据发送到 Elasticsearch。典型配置使用:

  • kubeletstats 接收器,用于 pod、容器和节点资源指标。

  • k8s_cluster 接收器,用于对象状态,例如 pod 阶段和容器重启。

  • filelog 接收器,结合 k8sattributes 处理器,用于容器日志。

资源 attributes 遵循 OpenTelemetry 语义约定。pod、命名空间和节点标识符显示为 k8s.pod.namek8s.namespace.namek8s.node.name 。指标名称由生成它们的接收器定义,而不是由 semantic conventions 规范本身定义:k8s.pod.phase 来自 k8s_cluster 接收器,而 k8s.container.memory_limit_utilization 等利用率指标来自 kubeletstats。EDOT 在 Elasticsearch 中原生保留所有这些名称。你实际拥有的字段取决于启用的接收器,因此请将这些查询视为模板,并在缺少某个指标时调整字段名称。

探索集群

从全局开始。在调查具体症状之前,先了解你的数据中的集群情况会有所帮助。

此查询统计过去一小时内每个命名空间中报告指标的 pod 数量。

sql 复制代码
`

1.  FROM metrics-*
2.  | WHERE @timestamp >= NOW() - 1 hour
3.  | STATS pod_count = COUNT_DISTINCT(k8s.pod.name) BY k8s.namespace.name
4.  | SORT pod_count DESC

`AI写代码

COUNT_DISTINCT 将每个 pod 的多个指标样本合并为每个命名空间的单个计数。结果是一个快速清单:哪些命名空间比较繁忙,以及你预期正在运行的内容是否缺失。

查找 pod 重启和崩溃循环

重启通常是出现问题的第一个信号。k8s.container.restarts 指标是一个测量值,用于报告每个容器当前的重启次数。

此查询显示过去 24 小时内重启次数最多的容器。

markdown 复制代码
`

1.  FROM metrics-*
2.  | WHERE @timestamp >= NOW() - 24 hours AND k8s.container.restarts IS NOT NULL
3.  | STATS restarts = MAX(k8s.container.restarts)
4.      BY k8s.namespace.name, k8s.pod.name, k8s.container.name
5.  | WHERE restarts > 0
6.  | SORT restarts DESC
7.  | LIMIT 20

`AI写代码

MAX 获取时间窗口内看到的最高重启次数,这反映了测量值的最新值。具有较高且不断增加的重启次数的容器,是崩溃循环的典型信号。获得 pod 名称后,你可以直接使用下面的查询转到它的日志。

发现未运行的 pod

重启次数说明 pod 已经恢复。pod 阶段说明它当前是否健康。k8s.pod.phase 指标将阶段编码为数字:

阶段
1 Pending(等待中)
2 Running(运行中)
3 Succeeded(成功)
4 Failed(失败)
5 Unknown(未知)

此查询使用 TS 读取每个 pod 的最新阶段,并保留所有不是 Running 的 pod。

ini 复制代码
`

1.  TS metrics-*
2.  | WHERE TRANGE(15m)
3.  | STATS phase = MAX(LAST_OVER_TIME(k8s.pod.phase))
4.      BY k8s.namespace.name, k8s.pod.name
5.  | WHERE phase != 2
6.  | EVAL phase_name = CASE(
7.      phase == 1, "Pending",
8.      phase == 3, "Succeeded",
9.      phase == 4, "Failed",
10.      phase == 5, "Unknown",
11.      "Other")
12.  | SORT phase_name

`AI写代码![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

LAST_OVER_TIME 选择每个 pod 时间序列中的最新样本,因此你比较的是当前状态,而不是平均值。卡在 Pending 状态的 pod 通常表示调度问题,例如节点上 CPU 或内存不足。处于 FailedUnknown 状态的 pod 值得立即查看。

在 OOM kill 之前发现内存压力

内存不足终止(out-of-memory kill)是 Kubernetes 中最常见的故障之一,并且预防它比事后调试更容易。当你在 kubeletstats 接收器中启用限制元数据时,EDOT 会将 k8s.container.memory_limit_utilization 报告为容器内存限制的 0 到 1 之间的比例。

此查询查找过去一小时内运行接近其限制的容器。

markdown 复制代码
`

1.  TS metrics-*
2.  | WHERE TRANGE(1h)
3.  | STATS peak_mem_pct = MAX(MAX_OVER_TIME(k8s.container.memory_limit_utilization))
4.      BY k8s.namespace.name, k8s.pod.name, k8s.container.name
5.  | EVAL peak_mem_pct = ROUND(peak_mem_pct * 100, 1)
6.  | WHERE peak_mem_pct > 85
7.  | SORT peak_mem_pct DESC

`AI写代码

MAX_OVER_TIME 查找每个容器时间序列中的峰值,而外层的 MAX 保留每个容器的该峰值。一个反复达到 95% 或更高的容器,很可能是下一次 OOM kill 的候选对象。将此查询与上面的重启查询结合使用:同时具有不断增加的重启次数和高内存利用率的容器,很可能曾经被 OOM kill。

跟踪 CPU 使用情况和节点压力

CPU 问题通常表现为节流和响应时间变慢,而不是崩溃。k8s.pod.cpu.node.utilization 指标将每个 pod 的 CPU 使用量报告为节点总容量的一部分。

此查询按五分钟时间段统计过去一小时内 CPU 最繁忙的 pod。

scss 复制代码
`

1.  TS metrics-*
2.    | WHERE TRANGE(1h)
3.    | STATS avg_cpu = AVG(AVG_OVER_TIME(k8s.pod.cpu.node.utilization))
4.        BY k8s.pod.name, TBUCKET(5m)
5.    | SORT avg_cpu DESC

`AI写代码

AVG_OVER_TIME 对每个 pod 时间序列中时间桶内的样本取平均值,而外层 AVG 合并共享相同 pod 名称的时间序列。TBUCKET(5m) 每五分钟生成一个数据点,可以干净地呈现为时间序列图表。

要检查节点本身是否达到饱和状态,可以直接查询节点利用率。

scss 复制代码
`

1.  TS metrics-*
2.    | WHERE TRANGE(1h)
3.    | STATS cpu = AVG(AVG_OVER_TIME(k8s.node.cpu.usage)),
4.            mem = AVG(LAST_OVER_TIME(k8s.node.memory.usage))
5.        BY k8s.node.name, TBUCKET(5m)
6.    | SORT cpu DESC

`AI写代码

一个接近满负载 CPU 的节点,可以同时解释多个命名空间中的 pod 被节流的情况。当你只查看单个 pod 时,这很容易被误认为是应用程序问题。

调查容器日志

当指标将你指向某个 pod 后,日志可以解释它正在执行的操作。EDOT 将日志消息存储在 body.text 中,将级别存储在 severity_text 中,同时保留与指标相同的 k8s.* 字段。

此查询按过去一小时内的错误数量对命名空间和 pod 进行排名。

sql 复制代码
`

1.  FROM logs-*
2.  | WHERE @timestamp >= NOW() - 1 hour
3.    AND severity_text IN ("ERROR", "FATAL")
4.  | STATS errors = COUNT(*)
5.      BY k8s.namespace.name, k8s.pod.name
6.  | SORT errors DESC
7.  | LIMIT 20

`AI写代码

按 pod 进行计数可以告诉你错误是集中在一个工作负载中,还是分布在整个集群中。单个产生大量日志的 pod 和整个集群范围的峰值,需要采取完全不同的响应方式。

要查看特定 pod 记录的日志,请按 pod 名称进行过滤,并搜索消息文本。

sql 复制代码
`

1.  FROM logs-*
2.  | WHERE @timestamp >= NOW() - 1 hour
3.    AND k8s.pod.name == "checkout-<your-hash>"
4.    AND body.text LIKE "*timeout*"
5.  | KEEP @timestamp, severity_text, body.text
6.  | SORT @timestamp DESC
7.  | LIMIT 50

`AI写代码

LIKE "*timeout*" 对消息执行简单的通配符匹配。如果需要使用全文相关性搜索而不是通配符,请将其替换为 MATCH(body.text, "timeout")(www.elastic.co/docs/refere... "MATCH(body.text, "timeout")")。

使用 ES|QL 查询链调查 Kubernetes 事件

实际的 Kubernetes 调查通常会将多个 ES|QL 查询串联起来,而不是单独运行一个查询。

一个有用的循环如下:

  1. 按 pod 统计错误数量,找到产生大量错误的工作负载。

  2. 检查该 pod 的重启次数和内存利用率,查看它是否正在崩溃或资源不足。

  3. 阅读它最近的日志,找到具体故障。

因为每个查询都使用相同的 k8s.namespace.namek8s.pod.name 字段,所以你可以直接将一个查询中的 pod 名称带到下一个查询中。同样的字段让你可以构建一个单独的仪表板,其中指标面板和日志面板可以在你点击浏览命名空间时一起进行过滤。

将查询转换为告警和仪表板

本文中的任何产生聚合值的 ES|QL 查询都可以支持告警,而不仅仅用于临时调查。

例如,重启查询在只保留超过阈值的容器并基于非空结果触发时,就可以变成一个告警。

sql 复制代码
`

1.  FROM metrics-*
2.  | WHERE @timestamp >= NOW() - 15 minutes AND k8s.container.restarts IS NOT NULL
3.  | STATS restarts = MAX(k8s.container.restarts)
4.      BY k8s.namespace.name, k8s.pod.name, k8s.container.name
5.  | WHERE restarts >= 5

`AI写代码

将其连接到 Elasticsearch query rule,你就可以在容器在十五分钟内重启五次时立即收到通知,而不是等用户发现问题后才知道。同样的模式也适用于内存利用率、节点饱和度和错误数量。

使用 ES|QL 构建 Kubernetes 监测工具集

ES|QL 为所有 Kubernetes 信号提供了一种统一语言,从对象状态到资源指标,再到容器日志。先从探索查询开始了解你的集群结构,然后在下一次事件发生时保留重启、阶段、内存、CPU 和日志查询以便快速使用。当你需要使用 MAX_OVER_TIMETBUCKET 等时间序列函数,在每个 pod 或容器时间序列中正确聚合时,使用 TS 。对于统计不同值数量或对测量值执行简单 MAX ,使用 FROM 即可。

接下来,你可以根据自己的接收器调整字段名称,将最有用的查询保存为仪表板面板,并将关键查询提升为告警。

要深入了解,请查看 ES|QL referenceTS 命令文档EDOT Kubernetes guide

原文:Kubernetes monitoring with ES|QL: crash loops and memory --- Elastic Observability Labs

相关推荐
本旺11 小时前
Elasticsearch 前缀匹配性能优化实战,附4种方式即执行计划判别
大数据·elasticsearch·性能优化
Elastic 中国社区官方博客16 小时前
Elastic 在 Everest Group 企业搜索产品 PEAK Matrix® 评估 2026 中被评为领导者
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
Java小白笔记18 小时前
Codex Skills 分类整理
大数据·人工智能·elasticsearch·搜索引擎·ai·ai编程·ai写作
Elastic 中国社区官方博客20 小时前
谁来评判评判者?在 Elasticsearch Workflows 中使用 LLM-as-a-Judge
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
Elastic 中国社区官方博客1 天前
使用 Elasticsearch 作为 Grafana 的直接替代 Prometheus 后端
大数据·数据库·sql·elasticsearch·搜索引擎·grafana·prometheus
阿里云大数据AI技术2 天前
AI Search × ES Agent Builder 最佳实践:企业智能助手落地指南
人工智能·elasticsearch
利威尔·3 天前
常用git命令
大数据·elasticsearch·搜索引擎
至乐活着3 天前
ELK日志系统从零搭建到实战:Nginx日志采集与可视化全攻略
nginx·elk·elasticsearch·docker·日志系统
say_fall3 天前
【Git 精品详解】企业规范:企业级开发模型、Git Flow、发版流程规范、Code Owner 制度、事故应急回滚
大数据·linux·服务器·git·学习·elasticsearch