mcpField
O
observability-k8s-investigation

observability-k8s-investigation

github.com/elastic云与 DevOps6023.1k 次安装今天更新
代码仓库

关于 observability-k8s-investigation

observability-k8s-investigation 是用于排查 Kubernetes 问题的技能,面向需要分析集群遥测数据的运维人员。它关联 OTel 指标、事件、日志和 APM 信号,协助定位工作负载、节点及控制平面层面的原因。

主要功能

  1. 01关联 Kubernetes 多层遥测信号
  2. 02分析容器资源指标与重启
  3. 03检查 Kubernetes 事件和对象状态
  4. 04结合应用日志及 APM 数据
  5. 05基于证据评估根因与不确定性

适用场景

  1. 01调查 Pod 频繁重启或 OOMKilled
  2. 02排查 CPU 限制导致的探针超时
  3. 03结合事件与日志分析调度或驱逐问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elastic/agent-skills --skill observability-k8s-investigation

安装后在 Claude Code 中输入/observability-k8s-investigation确认已加载。

附带文件references/failure-modes.mdreferences/query-recipes.md

详细介绍

Kubernetes 问题调查

使用通过 EDOT(Elastic Distribution of OpenTelemetry)和 kube-stack 收集器采集的 OTel 遥测数据诊断 Kubernetes 问题。关联集群状态、Pod 运行时指标、K8s 事件、应用日志和 APM,从工作负载、节点和控制平面各层识别根因。

环境配置

此技能通过 elastic CLI 执行 Elasticsearch 操作。如果未安装 elastic CLI,请告知用户需要它的原因。不要猜测凭据、直接调用 HTTP API 或尝试其他变通方法。

此技能以 HTTP 简写形式引用操作(例如,GET /、GET /_cat/indices、GET /{index}/_mapping、 GET /{index}/_settings/index.mode、POST /_query)。本文档末尾的 操作 表将每种简写映射到对应的 elastic CLI 命令——始终使用 CLI,不要直接调用 HTTP API。

无法访问集群时的分析

上述 CLI 检查只限制_查询集群_,不限制分析。如果用户已在问题中提供证据(指标值、计数、状态原因、日志行、告警负载、配置),请基于这些证据进行推理并给出结论。

如果确实需要用户未提供的数据,仍需说明要检查什么以及如何检查——指出能够明确问题的具体查询、索引和字段——然后再请求配置 CLI。指出要检查什么,即使无法访问集群也有帮助;只请求配置则没有帮助。

此技能及 references/query-recipes.md 中的所有 ES|QL 查询都通过 POST /_query 执行。告警状态通过 GET kbn:/api/alerting/rules/_find 读取。字段存在性检查使用 GET /<index>/_mapping 或 GET /_field_caps。操作 表将这些操作映射到对应的 elastic CLI 命令。

范围

范围内: 使用 OTel 接收器命名空间的索引(metrics-kubeletstatsreceiver.otel-*、 metrics-k8sclusterreceiver.otel-*、logs-k8seventsreceiver.otel-*、logs-k8sobjectsreceiver.otel-*)和 OTel 语义约定(k8s.pod.name、k8s.namespace.name、k8s.container.restarts)。

范围外:

  • 旧版 Elastic Agent Kubernetes 集成(metrics-kubernetes.*、logs-kubernetes.*、kubernetes.* 字段)。 已弃用——不要针对这些路径编写查询。
  • APM 层分析(服务 SLO 违约、事务错误率、上游依赖运行状况)。这是不同领域——确认或排除 K8s 根因后,应转交给 observability-sre-triage 技能;该技能负责 SLO 状态和消耗速率、活动告警规则、吞吐量、延迟、错误率、依赖运行状况和日志归集。如果工作负载最终并非托管在 Kubernetes 上,也应使用该技能。
  • 集群配置、容量规划、成本优化。这是不同领域。

指南

这些指南适用于每次调查。如有疑问,撰写综合结论前请重新阅读。

没有证据不等于证据不存在。切勿根据空结果臆造结论。 如果日志查询返回 0 行,可能是没有收集日志,或 Pod 最近没有日志行——这 并不 意味着“依赖项不可用”或任何其他特定故障模式。请报告 no_logs_available,并据此调整其余信号的权重。

依赖项数据为空 ≠ 上游健康。 未进行 APM 插桩的服务(负载生成器、工作器)不会发出目标指标。请报告 insufficient_dependency_data,而不是“上游正常”。

共现症状不是原因。 两个服务同时降级通常是因为它们共享同一个上游,而非彼此存在因果关系。只有在 (a) 一个服务的降级明确早于另一个服务,且 (b) 差异较大(错误率 >5×,延迟 >3×)时,才归因于因果关系。

OOMKilled 默认不等于内存泄漏。 限制可能只是低于工作负载工作集所需的大小。通过内存曲线的形态区分:内存单调增长直至达到限制,每次重启后重置;负载与上一周持平,且近期没有部署——这是内存泄漏的特征,应以高置信度得出结论。仅在曲线形态不明确(有尖峰、呈昼夜规律或与负载相关)时,才参考 7 天内同一时段的基线;这不是每次发现 OOMKilled 的先决条件。

因错误终止 ≠ 默认是应用程序缺陷。 请先检查 k8s.container.cpu_limit_utilization。在此类问题中,最常见的误诊是 CFS 节流导致存活探针超时。

CPU 平均值会掩盖节流。 Pod 的平均 cpu_limit_utilization 即使看起来健康(40–60%),在 p99 时也可能遭遇严重节流。Linux 以 100ms 为周期执行 CPU 限制;突发型工作负载会在周期中途达到配额并停滞。请查看最大值和 p95,不要只看平均值。

重启次数是布尔值,不是计数器。 k8s.container.restarts 直接从 K8s API 获取,kubelet 可能随时清除该值,因此绝对值不可靠。请将其视为 == 0(近期没有重启)与 > 0(近期正在重启);不要据此推断退避时序或“线性还是指数”模式。请改为通过 K8s 的 Killing / BackOff 事件确认重启模式。

与其凭空营造信心,不如报告不确定性。 如果证据含糊不清,综合结论应明确说明。提出相互竞争的假设也是有效结论。

同样,不要凭空营造不确定性。 上述规则针对的是证据含糊,而非语气。关键指标已出现且有佐证时,应以高置信度明确下结论。对明确的发现含糊其辞、将置信度降至“中等”,与过度声称同样是缺陷。

给出综合结论后即停止。 置信度只需在 HYPOTHESIS 行中说明一次,不要在每条要点中重复。除非查询结果改变了结论,否则不要叙述运行过哪些查询,也不要向读者复述告警。请以 RECOMMENDED NEXT STEPS 或 DOWNSTREAM IMPACT 结尾;切勿以“需要我继续查看吗?”之类的提议收尾。后续工作应放在建议列表中,并以建议的形式表述。

索引和字段

查看位置
信号索引模式用途
Pod/容器运行时metrics-kubeletstatsreceiver.otel-*CPU、内存、网络、文件系统。利用率比率。
集群状态metrics-k8sclusterreceiver.otel-*重启、阶段、上次终止原因、HPA、配额、节点状态
K8s 事件logs-k8seventsreceiver.otel-*Killing、BackOff、FailedScheduling、Evicted、镜像拉取事件
K8s 对象快照logs-k8sobjectsreceiver.otel-*随时间变化的 Deployment/service/configmap 状态
应用日志logs-*.otel-*body.text、severity_text,按 k8s.pod.name 筛选
APMtraces-*.otel-*、metrics-service_*.otel-default通过 service.name + K8s 资源属性进行关联
ML 异常.ml-anomalies-*内存增长、重启率、限流任务(如果已配置)
关键字段

扁平 OTel 路径可用于 ES|QL。为提高可读性,优先使用扁平形式;嵌套的 resource.attributes.* 形式仅适用于原始日志文档。

字段索引含义
k8s.pod.nameall k8sPod 名称
k8s.namespace.name仅限 metricsNamespace。已映射,但在 k8seventsreceiver 上为 null
attributes.k8s.namespace.namek8seventsreceiver事件中的 Namespace — 在此处按此形式筛选
k8s.container.nameall k8sPod 中的容器
k8s.deployment.namek8sclusterreceiver + others上级 Deployment
k8s.pod.phasek8sclusterreceiverPending=1/Running=2/Succeeded=3/Failed=4/Unknown=5
k8s.container.restartsk8sclusterreceiver容器重启总次数
k8s.container.status.last_terminated_reasonk8sclusterreceiverOOMKilled、Error、Completed、ContainerCannotRun
k8s.pod.status_reasonk8sclusterreceiverPod 级别原因(Evicted、NodeLost)
k8s.container.memory_limit_utilizationkubeletstatsreceiver0.0–1.0+(发生 OOM 前可能短暂超过 1)
k8s.container.cpu_limit_utilizationkubeletstatsreceiver0.0–N(CFS 限流期间经常 >1)
k8s.pod.memory_limit_utilizationkubeletstatsreceiver整个 Pod 的聚合值;使用前请参阅下方说明
k8s.pod.cpu_limit_utilizationkubeletstatsreceiver整个 Pod 的聚合值;使用前请参阅下方说明
k8s.pod.memory.usage / .working_setkubeletstatsreceiver字节
k8s.node.condition_memory_pressurek8sclusterreceiver1 = 有压力,0 = 正常
k8s.node.condition_readyk8sclusterreceiver0 = NotReady
k8s.hpa.current_replicas / .desired_replicask8sclusterreceiverHPA 状态
attributes.k8s.event.reasonk8seventsreceiver事件原因(按此字段筛选)
body.textk8seventsreceiver / logs事件消息 / 日志消息
k8s.object.namek8seventsreceiverinvolvedObject 名称(日志属性,使用扁平形式)
容器级与 Pod 级限额利用率

请在容器级别读取限额利用率。k8s.container.cpu_limit_utilization 和 k8s.container.memory_limit_utilization 是默认字段;Pod 级字段是另一种测量值,并非同义字段。

接收器会在同一数据流的不同文档上输出这两组字段:Pod 级字段出现在不包含 k8s.container.name 的文档上,容器级字段则只出现在包含该字段的文档上。因此,STATS ... BY k8s.container.name 对所有 Pod 级字段都会返回 null,反之亦然。在一个运行中的 9.6.0 集群上测量一小时:42,240 个不包含容器名称的文档中,有 360 个包含 k8s.pod.cpu_limit_utilization,没有文档包含容器级字段;18,240 个包含容器名称的文档中,有 900 个包含容器级字段,没有文档包含 Pod 级字段。

字段可用性也有所不同。每个声明了限额的容器都会输出容器级利用率,而 Pod 级聚合要求 Pod 中每个容器都声明限额。在两个运行中的集群上测量三小时,没有 Pod 在缺少容器级字段的情况下包含 Pod 级字段;有 27 个 Pod 包含容器级字段,但缺少 Pod 级字段——这些 Pod 全是多容器 Pod,且只有部分容器声明了限额。针对注入了 sidecar 的 Pod 进行 Pod 级限流检查时,会静默返回 null。

集群仅容器级两级都有都没有仅 Pod 级
forge-factory187440
k8s-demo96400

仅当问题确实涉及整个 Pod——即相对于其所有容器限额总和的总消耗——并且确认字段已填充后,才使用 Pod 级字段。observability-sre-triage 也遵循同一规则,因此两个技能针对同一 Pod 会返回相同答案。

字段可用性

上述几个字段在标准 kube-stack 收集器中默认关闭,需要显式配置。使用 GET /<index>/_mapping 或 GET /_field_caps 确认字段是否存在;如果不存在,请按说明使用备用方案,并在综合说明中注明替代情况。

字段可能缺失的原因替代方案
k8s.container.status.last_terminated_reasonk8sclusterreceiver 中的可选指标;受 metrics_collected.metadata 配置控制。根据 logs-k8seventsreceiver.otel-* 中的 K8s Killing / OOMKilling 事件以及应用日志中的退出代码推断。
k8s.pod.status_reason同上——k8sclusterreceiver 中的可选指标。根据事件推断:Evicted、NodeLost、Preempted。
k8s.container.cpu_limit_utilization / memory_limit_utilization仅当容器声明了相应限制,且启用了 kubeletstatsreceiver 指标时才会生成。k8s.pod.cpu.node.utilization / k8s.pod.memory.node.utilization 表示消耗占节点容量的比例,无论是否声明限制都会生成;或者将绝对值 container.cpu.usage / container.memory.usage 与基线进行趋势比较。这两种替代方案都位于 Pod 级文档中,因此请按 k8s.pod.name 分组,而非按 k8s.container.name 分组。
k8s.pod.cpu_limit_utilization / memory_limit_utilization要求 Pod 中的每个容器都声明限制,因此在大多数多容器 Pod 中都不存在。使用容器级字段,它们的可用范围严格来说更广。
k8s.node.condition_memory_pressure受 k8sclusterreceiver 的 node_conditions_to_report 控制(默认不包含此项)。将 k8s.node.memory.usage 与 k8s.node.allocatable_memory 进行比较,或查找节点上的 Evicted 事件。
如果使用了回退方案,请在综合分析中注明(例如,(via memory.usage; limit_utilization not collected)),以便读者知道该信号是间接的。

ES|QL 注意事项

编写查询前,请了解以下内容。这些情况都会悄无声息地产生错误答案,而不是明确报错。

VALUES() 在只有一个不同值时返回标量,有多个不同值时返回数组。 假设结果始终是数组的模板(例如,| first),遇到标量时会提取字符串的第一个字符。请使用 MV_FIRST(VALUES(...)),或同时处理这两种情况。

VALUES() 的版本新于此技能的最低基准版本。 在 Serverless 上它已正式发布;但在 Stack 上,它从 8.14.0 起处于预览阶段,到 9.4.0 才正式发布,且在 8.14 之前完全不可用。使用前请检查 GET /:build_flavor: "serverless" 表示该功能可用;否则请查看 version.number。如果该功能不可用,请将字段移入 BY 子句,而不是对其进行聚合——每个不同值对应一行,携带的信息相同:

| STATS restarts = MAX(k8s.container.restarts), phase = MAX(k8s.pod.phase)
    BY term_reason = k8s.container.status.last_terminated_reason
| SORT restarts DESC
| LIMIT 10

PERCENTILE 不适用于 OTel histogram 类型(截至 8.15)。对于 APM 时长百分位数,请对 aggregate_metric_double 汇总字段使用 AVG(AVG(transaction.duration.summary) 会用总和除以 value_count)。如需真实百分位数,请回退到 Kibana Query DSL。

COUNT(agg_metric_double) 返回的是 value_count(事件数),而非文档数。 SUM(field) 返回总和分量;AVG(field) 返回总和除以 value_count。不要将 SUM(transaction.duration.summary) 用作事件数的替代指标——它返回的是总时长。

K8s 指标在 ES|QL 中使用扁平的 OTel 字段路径。 使用 k8s.pod.name,而不是 resource.attributes.k8s.pod.name。嵌套形式用于原始日志文档。

故障模式分类

各模式的分类术语——包括跨工作负载、节点、控制平面、自动扩缩和网络层的关键指标与佐证检查,以及两种模式都符合时的处理方法——见references/failure-modes.md。分类前请先阅读。

信号解读

内存
  • 在 30–60 min 内持续上升 → 内存泄漏。检查对应语言的 GC 指标:JVM 使用 jvm.gc.duration,Go 使用 process.runtime.go.gc.pause_ns,Node 使用 v8js_gc_duration。在存活集稳定的情况下,GC 频率或暂停时间上升是典型的内存泄漏特征。
  • 随昼夜变化或负载相关的峰值 → 由负载驱动,并非内存泄漏。考虑调整 HPA 或提高限制。
  • 达到 1.0 后重启 → 已确认 OOMKilled。应用日志中的退出代码 137(SIGKILL)与此相符。
CPU
  • 持续出现 cpu_limit_utilization > 1.0 → CFS 限流。节点有空闲 CPU;Pod 受到配额限制。
  • 限流的症状(并非限流指标本身):存活探针超时、p99 延迟达到 p50 的 4–16×、上游队列出现背压,以及原因字段为 Error 的容器终止。
  • 平均值看起来可能正常,但 p95 可能受到限流。不要只相信平均值。
重启模式
  • 最近 restarts > 0 → 工作负载近期发生过重启。不要根据计数值判断程度(请参见 重启计数是布尔值);请通过 logs-k8seventsreceiver.otel-* 中 K8s Killing / BackOff 事件的时间戳确认重启模式。
  • 重启与内存压力(memory_limit_utilization → 1.0)相关 → OOMKilled 路径。
  • 没有内存或 CPU 压力却发生重启 → 探针配置错误、应用缺陷或启动依赖失败。请提取 Unhealthy 和 Killing 事件。
终止原因
  • OOMKilled → 内存问题。
  • Error → 非零退出。检查应用日志;如果日志为空或内容很少,请先检查 CPU 限流,再归因于应用逻辑。
  • Completed → 已运行完成。对于 Job/CronJob/初始化容器而言属正常情况;其他情况下则异常。
  • ContainerCannotRun → 运行时、镜像或执行问题。检查镜像拉取事件。

调查流程

调查不是一份检查清单。以下各节描述的是一条_典型_路径——根据发现的情况进行精简、跳过或重新审视。 一旦有足够证据达到已知置信度,就立即结束。收益递减后仍继续追查信号,这是一种失败,而不是严谨。

确定方向

确定目标:k8s.pod.name、k8s.namespace.name,以及可选的 k8s.deployment.name 和 service.name。如果未指定时间范围,Pod 级调查默认查看最近 1 小时,事件关联默认查看最近 2 小时,持续中或尚未解决的事故默认查看最近 6 小时。

如果告警负载已经说明故障模式(例如,告警专门针对 OOMKilled 触发),请记录这一点并跳过分类;转而进行确认和基线比较。

描述特征

了解工作负载近期行为的概况:重启次数、终止原因、阶段、利用率。通常一两条查询就足够。

FROM metrics-k8sclusterreceiver.otel-*
| WHERE k8s.pod.name == "<pod>" AND k8s.namespace.name == "<ns>"
  AND @timestamp > NOW() - 1 hour
| STATS restarts = MAX(k8s.container.restarts),
        term_reasons = VALUES(k8s.container.status.last_terminated_reason),
        phase = MAX(k8s.pod.phase)

VALUES() 需要 Serverless 或 Stack 8.14+(GA 9.4)。在较旧的 Stack 集群上,请使用 ES|QL 注意事项中的 BY 子句改写,而不是从查询中删去终止原因。

FROM metrics-kubeletstatsreceiver.otel-*
| WHERE k8s.pod.name == "<pod>" AND @timestamp > NOW() - 15 minutes
| STATS mem_pct = ROUND(MAX(k8s.container.memory_limit_utilization) * 100, 1),
        cpu_pct = ROUND(MAX(k8s.container.cpu_limit_utilization) * 100, 1)
    BY k8s.container.name

按容器分组:注入了 sidecar 的 Pod 包含多个容器,只有声明了限制的容器才会报告利用率。如果每一列都返回 null,则表示没有声明限制——请按字段可用性中的说明进行后续处理,不要将 null 解读为空闲。

分类

使用references/failure-modes.md中的分类法。关键判定信号应当匹配;“Investigate”列会告诉你需要寻找哪些佐证。

如果两种模式都符合,请同时记录,并优先处理关键判定信号更强的一种。你可以在佐证过程中修正判断。

佐证

提取分类结果预期能找到的证据。常见来源:

该命名空间和时间范围内的 K8s 事件:

FROM logs-k8seventsreceiver.otel-*
| WHERE attributes.k8s.namespace.name == "<ns>"
  AND @timestamp > NOW() - 2 hours
  AND attributes.k8s.event.reason IN (
    "BackOff", "Killing", "Unhealthy", "Failed",
    "FailedScheduling", "Evicted", "SuccessfulRescale",
    "Pulling", "Pulled", "Started", "Created"
  )
| SORT @timestamp DESC
| KEEP @timestamp, attributes.k8s.event.reason, body.text, k8s.object.name
| LIMIT 30

在此接收器中,命名空间是日志属性,而不是资源属性。 请筛选 attributes.k8s.namespace.name,而不是 扁平字段 k8s.namespace.name。此数据流中映射了扁平形式,因此使用它的查询可以解析并执行,但会在无报错的情况下返回零行——在一个 Stack 9.4.4 集群上,扁平字段在 832 条事件中有 0 条填充值,而 attributes. 形式在所有事件中都携带命名空间,因此扁平筛选器丢弃了 300 条匹配的 BackOff、Killing 和 Unhealthy 事件。扁平的 k8s.* 路径在 metrics-kubeletstatsreceiver.otel-* 和 metrics-k8sclusterreceiver.otel-* 上确实有效,因为命名空间是资源属性;事件接收器是例外。在相信事件查询结果为空之前,请对比 COUNT(attributes.k8s.namespace.name) 和 COUNT(*)。

应用日志(如果可用)——查看终止时间戳之前最近的 200 行。如果没有日志,请标记 no_logs_available;不要臆造日志模式。

APM(如果 Pod 运行的是经过插桩的服务)——从 Pod 资源属性中解析 service.name,用于后续关联。SLO、延迟和错误率分析本身属于 APM 层工作,不在本技能范围内。

基线比较——对于基于利用率的发现,将当前值与 7 天前同一时段的值进行比较。只有相对于该工作负载的正常水平而言,“内存高”才有意义。

检查上游原因(有条件)

仅在症状模式表明有必要时才追查。阈值:上游错误率超过基线 5 倍,或延迟超过基线 3 倍,并且目标服务的症状出现之前就已开始退化。共同出现的症状不足以证明因果关系。

如果 metrics-service_destination.1m.otel-default 中没有该服务的数据行,请报告 insufficient_dependency_data,而不是“上游运行正常”。

检查近期变更(条件性)

过去 2 小时内的 SuccessfulCreate / Pulled 事件通常与部署相关。logs-k8sobjectsreceiver.otel-* 会显示 configmap/secret/deployment 规范的变更。症状出现前 15 分钟内发生的变更具有很强的相关性, 但仍然只是相关性——请确认它确实可以合理解释你已判定的模式。

综合并停止

一旦证据足以支撑一个具有已知置信度的假设,就立即进行综合。无需完成所有前置章节——出现以下任一情况时,调查即告终止:

  • 你得出了有佐证的高置信度假设;或
  • 你得出了低/中置信度假设,且进一步查询不太可能改变判断(例如,日志不可用、未检测 APM,或未发现近期变更)。

综合

默认结构:

HYPOTHESIS (confidence: high | medium | low)
<One paragraph: service, symptom, most likely cause. Name the failure mode from the taxonomy.>

EVIDENCE
- <Finding from characterization, with the concrete metric or value.>
- <Finding from events / logs / APM.>
- <Finding from baseline comparison, dependency check, or change correlation if pursued.>

CONFIDENCE NOTE
<Only if not 'high'. What specific evidence is missing or ambiguous.>

RECOMMENDED NEXT STEPS
1. <Most actionable — typically a config check or metric to observe.>
2. <Secondary.>

DOWNSTREAM IMPACT
<Services depending on this workload, or 'No downstream dependencies identified.'>

篇幅。 整个综合部分为 250–400 个词。HYPOTHESIS 用两到三句话。EVIDENCE 包含三到五条单行项目,每条引用一个具体值,而不是重新解释该值。RECOMMENDED NEXT STEPS 包含两到三条单行项目——只列出你实际会优先采取的措施,而不是所有可能的措施。DOWNSTREAM IMPACT 用一到两句话说明。证据充分的告警可以轻松控制在这个篇幅内;篇幅长不代表全面,而且值班人员在事件处理中快速浏览时不会看到首屏以外的内容。

当有两个假设尚未排除时: 将 HYPOTHESIS 替换为 COMPETING HYPOTHESES;列出两种假设,说明你更倾向哪一种及其原因,并列出可用于区分它们的证据。

未发现事故时(症状已解决,或告警似乎是误报):请直接说明。 ALERT FIRED BUT SYSTEM APPEARS HEALTHY 是有效的输出。列出你检查过的内容,以及未发现的情况。

置信度校准

从 高 开始,根据缺失信息降低置信度:

  • 降至 中:主要信号明确,但缺少佐证(没有日志、没有 APM、无法与基线比较)。或者:两种模式都符合,但你无法区分。
  • 降至 低:只有单一信号支持该假设、信号相互矛盾,或该模式需要你无法获取的证据。

如果没有应用程序日志数据,而假设又依赖于应用程序行为,绝不要给出 高 置信度。缺少证据不能佐证假设。

查询配方

针对重启次数最多的 Pod、CPU 限流、节点内存压力、准入拒绝和告警触发路径的现成查询,位于 references/query-recipes.md。

示例

“为什么我的 Pod 一直处于 CrashLoopBackOff 状态?”

先进行特征分析:获取重启次数、终止原因、内存和 CPU 利用率。

  • 如果 last_terminated_reason == "OOMKilled" 且内存利用率达到 1.0 → 内存路径。通过 7 天基线进行佐证:数日内持续上升 = 泄漏;波动剧烈 = 负载驱动。如果已知语言,检查 GC 指标。
  • 如果 last_terminated_reason == "Error" 且 cpu_limit_utilization > 1.0 → CPU 限流路径。通过存活探针配置(initialDelaySeconds、timeoutSeconds)和 K8s Unhealthy 事件进行佐证。
  • 如果 last_terminated_reason == "Error" 且 CPU 正常 → 应用逻辑路径。提取终止前的近期日志。
  • 如果 last_terminated_reason == "ContainerCannotRun" → 镜像/执行路径。检查 K8s 事件中是否有 Failed 拉取事件。

以适当的置信度进行综合。如果在 Error 路径中无法获取日志,请将置信度降至中,并说明原因。

“我的发布卡住了吗?”

权威信号:k8s.deployment.available < k8s.deployment.desired 持续超过 10 分钟。

诊断约束因素:

  • 检查新 ReplicaSet 上的 K8s 事件:FailedCreate → 准入拒绝(配额、Webhook、PSP)。FailedScheduling → 没有 合适的节点。
  • 检查新 Pod 的利用率:内存利用率全部为 0% → 从未启动(镜像拉取失败);CPU 利用率高而内存利用率低 → 启动缓慢, 触发就绪探针。
  • 检查 HPA 状态:负载下 current_replicas < desired_replicas 且数值稳定 → 未就绪 Pod 抑制扩容。
“告警已触发,但一切看起来都正常”

这种情况可能发生,值得明确说明。请检查:

  • 症状是否已消失?将当前利用率/重启率与告警触发点进行比较。
  • 告警是否由瞬时峰值触发,且峰值已回落?
  • 告警配置是否合适(例如,评估窗口过短)?

输出:ALERT FIRED BUT SYSTEM APPEARS HEALTHY,并说明已检查的内容。如果这种情况反复出现,建议调整告警配置。

相关内容

  • 工作流:K8s CrashLoopBackOff Investigation——由告警触发的自动化版本,执行上述 Pod 级排查流程。 运行确定性 ESQL 并进行分支处理;此技能提供工作流所缺少的解读层。
  • **Forge 基因库:**16 种 K8s 故障场景(OOMKill 级联、CPU 限流、探针配置错误、节点 NotReady、 准入 Webhook 阻止等),用于验证此技能的覆盖范围。

运维

HTTP API(简写)elastic CLI 命令
GET /elastic es info
POST /_queryelastic es esql query --format tsv --query '<esql>'
GET /<index>/_mappingelastic es indices get-mapping --index '<index>'
GET /_field_capselastic es field-caps --index '<index>' --fields '<fields>'
GET kbn:/api/alerting/rules/_findelastic kb alerting get-alerting-rules-find --filter '<filter>'

评论

支持 Markdown