加载中

排查 Kibana 任务管理器故障

Kibana 实例不组成集群。相反,Kibana 实例通过将状态同步到 Elasticsearch(保存在 kibana 功能状态下)来管理其状态。这就是为什么当 Elasticsearch 或 Kibana 特定的底层索引不可用时,Kibana 会变得不可用。同步状态的一部分包含 Kibana 的任务管理器 (Task Manager)

任务管理器被 Kibana 中的广泛服务所使用,例如警报 (Alerting)、操作 (Actions)、报告 (Reporting)和遥测 (Telemetry)。这些服务中的意外行为可能与任务管理器中的问题有关,你可以从 Kibana 服务器状态中进行检查。

本页介绍如何排查任务管理器的健康状况并解决可能遇到的常见问题。如果本页未描述你的问题,请检查 elastic/Kibana GitHub 仓库中的未解决问题,或者在联系 Elastic 支持寻求帮助时分享 Kibana 诊断信息

以下步骤演示了典型的排查流程。它假设 Task Manager Health 已在本地保存为 task_manager_health.json,并使用第三方工具 JQ 作为 JSON 处理器。它不要求 taskManager 插件在 Kibana 服务器状态下被标记为不健康。

  1. 检查总体状态。
cat kibana_task_manager_health.json | jq -rc '{ overall: .status }'
		
  1. 检查各子部分的状态。
cat kibana_task_manager_health.json | jq -r '{ capacity:. stats.capacity_estimation.status, config: .stats.configuration.status, runtime: .stats.runtime.status, workload: .stats.workload.status }'
		

可能的健康状态包括 OKWarningError

  1. 子部分可能显示为健康,但任务管理器仍然报告高 load(负载)或 drift(漂移)。
cat kibana_task_manager_health.json | jq '.stats.runtime.value|{drift, load}'
		

对于大多数性能问题,子部分会通过其状态指示明确的健康问题。你可以从其自身的子数据中确认子部分状态的汇总

部分 描述
配置 本节总结了任务管理器的当前配置。这包括随时间变化的动态配置,例如 poll_intervalmax_workers,当系统负载变化时,这些配置可能会发生变化。
工作负载 本节总结了整个集群的工作负载,包括系统中的任务、其类型和当前状态。
运行时 本节跟踪任务管理器的执行性能,包括任务 drift(漂移)、工作线程 load(负载),以及按类型细分的执行统计信息(包括持续时间和执行结果)。
容量估计 本节提供对其容量充足性的粗略估计。这些是基于历史数据的估计,不应用作预测。在遵循任务管理器扩缩容指南时,请使用这些估计值。
重要提示

某些任务(例如连接器任务)即使在任务失败时也可能会错误地将其状态报告为成功。运行时和工作负载块会返回有关成功和失败的数据,但并未考虑这一点。

为了更好地了解操作失败,请参考事件日志索引以获取有关失败和成功的更准确上下文。

以下指南通过解读来自健康监视端点的输出,来帮助你识别 drift(漂移)的根本原因。

通过分析输出的不同部分,你可以评估解释部署中漂移的不同假设。

检索 Kibana 实例任务管理器的最新受监视健康统计信息

$ curl -X GET api/task_manager/_health
		

API 返回以下内容

{
  "id": "15415ecf-cdb0-4fef-950a-f824bd277fe4",
  "timestamp": "2021-02-16T11:38:10.077Z",
  "status": "OK",
  "last_update": "2021-02-16T11:38:09.934Z",
  "stats": {
    "configuration": {
      "timestamp": "2021-02-16T11:29:05.055Z",
      "value": {
        "request_capacity": 1000,
        "monitored_aggregated_stats_refresh_rate": 60000,
        "monitored_stats_running_average_window": 50,
        "monitored_task_execution_thresholds": {
          "default": {
            "error_threshold": 90,
            "warn_threshold": 80
          },
          "custom": {}
        },
        "poll_interval": 3000,
        "max_workers": 10
      },
      "status": "OK"
    },
    "runtime": {
      "timestamp": "2021-02-16T11:38:09.934Z",
      "value": {
        "polling": {
          "last_successful_poll": "2021-02-16T11:38:09.934Z",
          "last_polling_delay": "2021-02-16T11:29:05.053Z",
          "duration": {
            "p50": 13,
            "p90": 128,
            "p95": 143,
            "p99": 168
          },
          "claim_conflicts": {
            "p50": 0,
            "p90": 0,
            "p95": 0,
            "p99": 0
          },
          "claim_mismatches": {
            "p50": 0,
            "p90": 0,
            "p95": 0,
            "p99": 0
          },
          "result_frequency_percent_as_number": {
            "Failed": 0,
            "NoAvailableWorkers": 0,
            "NoTasksClaimed": 80,
            "RanOutOfCapacity": 0,
            "RunningAtCapacity": 0,
            "PoolFilled": 20
          }
        },
        "drift": {
          "p50": 99,
          "p90": 1245,
          "p95": 1845,
          "p99": 2878
        },
        "load": {
          "p50": 0,
          "p90": 0,
          "p95": 10,
          "p99": 20
        },
        "execution": {
          "duration": {
            "alerting:.index-threshold": {
              "p50": 95,
              "p90": 1725,
              "p95": 2761,
              "p99": 2761
            },
            "alerting:xpack.uptime.alerts.monitorStatus": {
              "p50": 149,
              "p90": 1071,
              "p95": 1171,
              "p99": 1171
            },
            "actions:.index": {
              "p50": 166,
              "p90": 166,
              "p95": 166,
              "p99": 166
            }
          },
          "persistence": {
            "recurring": 88,
            "non_recurring": 4,
          },
          "result_frequency_percent_as_number": {
            "alerting:.index-threshold": {
              "Success": 100,
              "RetryScheduled": 0,
              "Failed": 0,
              "status": "OK"
            },
            "alerting:xpack.uptime.alerts.monitorStatus": {
              "Success": 100,
              "RetryScheduled": 0,
              "Failed": 0,
              "status": "OK"
            },
            "actions:.index": {
              "Success": 10,
              "RetryScheduled": 0,
              "Failed": 90,
              "status": "error"
            }
          }
        }
      },
      "status": "OK"
    },
    "workload": {
      "timestamp": "2021-02-16T11:38:05.826Z",
      "value": {
        "count": 26,
        "task_types": {
          "alerting:.index-threshold": {
            "count": 2,
            "status": {
              "idle": 2
            }
          },
          "actions:.index": {
            "count": 14,
            "status": {
              "idle": 2,
              "running": 2,
              "failed": 10
            }
          },
          "alerting:xpack.uptime.alerts.monitorStatus": {
            "count": 10,
            "status": {
              "idle": 10
            }
          },
        },
        "schedule": [
          ["10s", 2],
          ["1m", 2],
          ["60s", 2],
          ["5m", 2],
          ["60m", 4],
          ["3600s", 1],
          ["720m", 1]
        ],
        "non_recurring": 18,
        "owner_ids": 0,
        "overdue": 10,
        "overdue_non_recurring": 10,
        "estimated_schedule_density": [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 3, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0],
        "capacity_requirements": {
          "per_minute": 6,
          "per_hour": 28,
          "per_day": 2
        }
      },
      "status": "OK"
    },
    "capacity_estimation": {
      "timestamp": "2021-02-16T11:38:06.826Z",
      "value": {
        "observed": {
          "observed_kibana_instances": 1,
          "max_throughput_per_minute_per_kibana": 200,
          "max_throughput_per_minute": 200,
          "minutes_to_drain_overdue": 1,
          "avg_recurring_required_throughput_per_minute": 28,
          "avg_recurring_required_throughput_per_minute_per_kibana": 28,
          "avg_required_throughput_per_minute": 28,
          "avg_required_throughput_per_minute_per_kibana": 28
        },
        "proposed": {
          "min_required_kibana": 1,
          "provisioned_kibana": 1,
          "avg_recurring_required_throughput_per_minute_per_kibana": 28,
          "avg_required_throughput_per_minute_per_kibana": 28
        }
      }
      "status": "OK"
    }
  }
}
		

假设 (Theory):Kibana 配置为以降低的速率轮询任务。

诊断 (Diagnosis):评估健康统计信息时,你可以在 stats.configuration.value 下看到以下输出

{
  "request_capacity": 1000,
  "monitored_aggregated_stats_refresh_rate": 60000,
  "monitored_stats_running_average_window": 50,
  "monitored_task_execution_thresholds": {
    "default": {
      "error_threshold": 90,
      "warn_threshold": 80
    },
    "custom": {}
  },
  "poll_interval": 3000,
  "max_workers": 10
}
		
  1. poll_interval 设置为默认值 3000 毫秒
  2. max_workers 设置为默认值 10 个工作线程

你可以从该输出推断出,Kibana 实例每 3 秒轮询一次工作,并且可以运行 10 个并发任务。

现在假设 stats.configuration.value 下的输出如下

{
  "request_capacity": 1000,
  "monitored_aggregated_stats_refresh_rate": 60000,
  "monitored_stats_running_average_window": 50,
  "monitored_task_execution_thresholds": {
    "default": {
      "error_threshold": 90,
      "warn_threshold": 80
    },
    "custom": {}
  },
  "poll_interval": 60000,
  "max_workers": 1
}
		
  1. poll_interval 设置为 60000 毫秒,远高于默认值
  2. max_workers 设置为 1 个工作线程,远低于默认值

你可以从该输出推断出,Kibana 实例每分钟只轮询一次工作,并且一次只获取一个任务。这种吞吐量不太可能支持关键任务服务(如警报或报告),并且任务通常会延迟运行。

这种配置可能有以下两个原因

  • 这些设置是手动配置的,可以通过重新配置这些设置来解决。有关详细信息,请参阅任务管理器设置

  • Kibana 为了应对 Elasticsearch 集群上的过高负载而降低了自己的吞吐量。

    任务管理器配备了响应式自愈机制,以应对 Elasticsearch 中与负载相关的错误增加。此机制将增加 poll_interval 设置(降低其查询 Elasticsearch 的速率),并减少 max_workers(减少对 Elasticsearch 执行的操作量)。一旦错误率降低,这些设置将再次逐步调高,恢复到配置的设置。

    可以通过在 Kibana 服务器日志中搜索如下消息来识别此场景

    Max workers configuration is temporarily reduced after Elasticsearch returned 25 "too many request" error(s).
    		

    需要对 Elasticsearch 集群遇到的高错误率进行更深入的调查。

假设 (Theory):Kibana 轮询的频率没有达到应有的水平

诊断 (Diagnosis):评估健康统计信息时,你会在 stats.runtime.value.polling 下看到以下输出

{
  "last_successful_poll": "2021-02-16T11:38:09.934Z",
  "last_polling_delay": "2021-02-14T11:29:05.053Z",
  "duration": {
    "p50": 13,
    "p90": 128,
    "p95": 143,
    "p99": 168
  },
  "claim_conflicts": {
    "p50": 0,
    "p90": 0,
    "p95": 0,
    "p99": 2
  },
  "claim_mismatches": {
    "p50": 0,
    "p90": 0,
    "p95": 0,
    "p99": 0
  },
  "result_frequency_percent_as_number": {
    "Failed": 0,
    "NoAvailableWorkers": 0,
    "NoTasksClaimed": 80,
    "RanOutOfCapacity": 0,
    "RunningAtCapacity": 0,
    "PoolFilled": 20
  }
}
		
  1. 确保最后一次成功的轮询周期在过去不久(不超过 poll_interval 的几倍)完成。
  2. 确保轮询周期的持续时间通常低于 100ms。可能存在更长的持续时间,但这并非预期情况。
  3. 确保集群中的 Kibana 实例没有遇到高频率的版本冲突。
  4. 确保大多数轮询周期产生积极的结果,例如 RunningAtCapacityPoolFilled

你可以从该输出推断出 Kibana 实例正在定期轮询。此评估基于以下内容

  • last_successful_poll 与根目录下的 timestamp(值为 2021-02-16T11:38:10.077Z)进行比较,从中可以看到上一次轮询周期发生在健康监视 API 公开监视统计信息之前的 1 秒。

  • last_polling_delay 与根目录下的 timestamp(值为 2021-02-16T11:38:10.077Z)进行比较,从中可以看到上一次轮询周期延迟发生在 2 天前,这表明 Kibana 实例不常发生冲突。

  • durationp50 显示,至少 50% 的轮询周期最多需要 13 毫秒即可完成。

  • 评估 result_frequency_percent_as_number

    • 80% 的轮询周期在未认领任何任务的情况下完成(表明没有任何逾期任务)。
    • 20% 的轮询周期完成时,任务管理器认领了随后执行的任务。
    • 没有任何轮询周期最终占满所有可用工作线程,因为 RunningAtCapacity 的频率为 0%,这表明任务管理器中有足够的容量来处理工作负载。

所有这些统计信息都作为移动平均线进行跟踪,这意味着它们提供的是一段时间内的快照(默认情况下 Kibana 最多跟踪 50 个周期),而不是完整的历史记录。

假设 stats.runtime.value.polling.result_frequency_percent_as_number 下的输出如下

{
  "Failed": 30,
  "NoAvailableWorkers": 20,
  "NoTasksClaimed": 10,
  "RanOutOfCapacity": 10,
  "RunningAtCapacity": 10,
  "PoolFilled": 20
}
		
  1. 30% 的轮询周期失败,这是一个很高的比率。
  2. 20% 的轮询周期被跳过,因为任务管理器没有剩余容量来运行任务。
  3. 10% 的轮询周期导致任务管理器认领的任务数超出了其运行能力。
  4. 10% 的轮询周期导致任务管理器认领的任务数恰好等于其运行能力。

你可以从该输出推断出任务管理器不健康,因为失败率很高,并且任务管理器正在获取它无力运行的任务。分析 Kibana 服务器日志应该能揭示导致高错误率和容量问题的根本原因。

高达 20% 的 NoAvailableWorkers 率表明有许多任务的运行持续时间超过了 poll_interval。有关分析长任务执行持续时间的详细信息,请参阅运行时间过长的任务假设。

假设 (Theory):Kibana 的轮询频率达到了应有的水平,但仍不足以跟上工作负载

诊断 (Diagnosis):评估健康统计信息时,你可以在 stats.runtime.value 下看到 driftload 的以下输出

{
  "drift": {
    "p50": 99,
    "p90": 1245,
    "p95": 1845,
    "p99": 2878
  },
  "load": {
    "p50": 0,
    "p90": 0,
    "p95": 10,
    "p99": 20
  },
}
		
  1. drift 表明至少 95% 的任务在其预定时间的 2 秒内运行。
  2. load 表明任务管理器至少 90% 的时间处于空闲状态,且使用不超过 20% 的可用工作线程。

你可以从这些统计信息推断出此 Kibana 具有充足的容量,你可能遇到的任何延迟都不太可能通过扩大吞吐量来解决。

假设 driftload 的输出如下

{
  "drift": {
    "p50": 2999,
    "p90": 3845,
    "p95": 3845.75,
    "p99": 4078
  },
  "load": {
    "p50": 80,
    "p90": 100,
    "p95": 100,
    "p99": 100
  }
}
		
  1. drift 表明所有任务都在其预定时间之后 3 到 4 秒运行。
  2. load 表明至少有一半的时间任务管理器以 80% 的负载运行。

你可以从这些统计信息推断出此 Kibana 正在使用其大部分容量,但大多数时候似乎能跟上工作。此评估基于以下内容

  • loadp90 为 100%,p50 也高达 80%。这意味着几乎没有腾挪的空间,工作量的激增可能会导致任务管理器超出其容量。
  • 任务在其预定时间后不久运行,这是意料之中的。3000 毫秒的 poll_interval 通常会出现介于 03000 毫秒之间的持续漂移。2999p50 drift 表明仍有改进空间,你可以从更高的吞吐量中获益。

有关通过调整扩缩容策略来实现更高吞吐量的详细信息,请参阅扩缩容指南

假设 (Theory):任务运行时间过长,超出了其调度时间

诊断 (Diagnosis)吞吐量不足以处理预定工作负载的假设分析了一个假设场景,其中漂移和负载都异常高。

假设另一种场景,其中 drift 高但 load 不高,例如以下场景

{
    "drift": {
        "p50": 9799,
        "p90": 83845,
        "p95": 90328,
        "p99": 123845
    },
    "load": {
        "p50": 40,
        "p90": 75,
        "p95": 80,
        "p99": 100
    }
}
		
  1. drift 表明大多数(如果不是全部)任务运行延迟至少 32 秒。
  2. load 表明在大多数情况下,你有运行更多并发任务的容量。

在上述场景中,任务运行得太晚,但你有足够的容量来运行更多并发任务。高容量允许 Kibana 同时运行多个不同的任务。如果在下一次计划运行到期时任务已经在运行,Kibana 将避免第二次运行它,而是等待第一次执行完成。

如果任务执行所需的时间长于其调度节奏,则该任务将始终超时并经历高漂移。例如,假设一个任务计划每 3 秒执行一次,但需要 6 秒才能完成。它将持续遭遇至少 3 秒的漂移。

在此假设场景中评估健康统计信息时,你会在 stats.runtime.value.execution.duration 下看到以下输出

{
  "alerting:.index-threshold": {
    "p50": 95,
    "p90": 1725,
    "p95": 2761,
    "p99": 2761
  },
  "alerting:.es-query": {
    "p50": 7149,
    "p90": 40071,
    "p95": 45282,
    "p99": 121845
  },
  "actions:.index": {
    "p50": 166,
    "p90": 166,
    "p95": 166,
    "p99": 166
  }
}
		
  1. 支持索引阈值警报的 50% 的任务在不到 100 毫秒内完成。
  2. 支持 Elasticsearch 查询警报的 50% 的任务在 7 秒内完成,但至少有 10% 的任务耗时超过 40 秒。

你可以从这些统计信息推断出,任务管理器经历的高漂移很可能是由于 Elasticsearch 查询警报运行时间过长导致的。

解决此问题取决于上下文,并且因情况而异。在前面的例子中,可以通过修改这些警报中的查询以使其更快,或者提高 Elasticsearch 吞吐量以加速现有查询来解决。

假设 (Theory):任务需要多次尝试才能成功

诊断 (Diagnosis):高错误率可能会导致任务看起来运行延迟,而实际上它按时运行,但遭遇了高失败率。

评估前面的健康统计信息时,你会在 stats.runtime.value.execution.result_frequency_percent_as_number 下看到以下输出

{
  "alerting:.index-threshold": {
    "Success": 100,
    "RetryScheduled": 0,
    "Failed": 0,
    "status": "OK"
  },
  "alerting:xpack.uptime.alerts.monitorStatus": {
    "Success": 100,
    "RetryScheduled": 0,
    "Failed": 0,
    "status": "OK"
  },
  "actions:.index": {
    "Success": 8,
    "RetryScheduled": 0,
    "Failed": 92,
    "status": "error"
  }
}
		
  1. 支持索引阈值警报的 100% 的任务成功完成。
  2. 支持 ES 索引操作的 92% 的任务未能完成。
  3. 支持 ES 索引操作的任务已超过默认的 monitored_task_execution_thresholds error(错误)配置。

你可以从这些统计信息推断出,支持 ES 索引 Kibana 操作的大多数 actions:.index 任务都失败了。解决该问题需要深入调查记录了确切错误的 Kibana 服务器日志,并解决这些特定的错误。

假设 (Theory):非循环任务的激增正在消耗可用容量的高比例

诊断 (Diagnosis):任务管理器使用临时非循环任务在多个 Kibana 实例之间进行负载均衡操作。

评估前面的健康统计信息时,你会在 stats.runtime.value.execution.persistence 下看到以下输出

{
  "recurring": 88,
  "non_recurring": 12,
},
		
  1. 88% 的执行任务是循环任务
  2. 12% 的执行任务是非循环任务

你可以从这些统计信息推断出,88% 的执行是由循环任务组成的。你可以使用 execution.persistence 统计信息来评估消耗容量的比率,但仅凭这些,你不应对可用容量的充足性做出假设。

为了评估容量,你应该将这些统计信息与 stats.runtime.value 下的 load 进行对比评估

{
    "load": {
        "p50": 40,
        "p90": 40,
        "p95": 60,
        "p99": 80
    }
}
		

你可以从这些统计信息推断出,任务管理器耗尽容量是非常罕见的,因此容量可能足以处理非循环任务的数量。

假设你有另一种场景,你在 stats.runtime.value.execution.persistence 下看到以下输出

{
  "recurring": 60,
  "non_recurring": 40,
},
		
  1. 60% 的执行任务是循环任务
  2. 40% 的执行任务是非循环任务

你可以从这些统计信息推断出,尽管大多数执行都是循环任务,但相当大比例的执行(40%)是非循环任务。

评估 stats.runtime.value 下的 load,你会看到以下内容

{
    "load": {
        "p50": 70,
        "p90": 100,
        "p95": 100,
        "p99": 100
    }
}
		

你可以从这些统计信息推断出,此 Kibana 实例耗尽容量是相当常见的。鉴于非循环任务的高比率,可以合理地评估认为 Kibana 集群中处理任务数量的容量不足。

请记住,这些统计信息仅提供特定时间点的概览,即使最近几分钟内容量一直不足,在其他使用较少非循环任务的时间里可能并非如此。我们建议随着时间推移跟踪这些统计信息,并在对基础设施进行重大更改之前识别这些任务的来源。

预测部署支持任务管理器可能需要的所需吞吐量是很困难的,因为功能可以按各种计划节奏调度不可预测数量的任务。

健康监视提供的统计信息使监视现有吞吐量的充足性变得更加容易。通过评估工作负载,可以估计所需的吞吐量,这在遵循任务管理器扩缩容指南时会用到。

评估前一个例子中的健康统计信息时,你会在 stats.workload.value 下看到以下输出

{
  "count": 26,
  "task_types": {
    "alerting:.index-threshold": {
      "count": 2,
      "status": {
        "idle": 2
      }
    },
    "actions:.index": {
      "count": 14,
      "status": {
        "idle": 2,
        "running": 2,
        "failed": 10
      }
    },
    "alerting:xpack.uptime.alerts.monitorStatus": {
      "count": 10,
      "status": {
        "idle": 10
      }
    },
  },
  "non_recurring": 0,
  "owner_ids": 1,
  "schedule": [
    ["10s", 2],
    ["1m", 2],
    ["90s", 2],
    ["5m", 8]
  ],
  "overdue_non_recurring": 0,
  "overdue": 0,
  "estimated_schedule_density": [
    0, 1, 0, 0, 0, 1, 0, 1, 0, 1,
    0, 0, 0, 1, 0, 0, 1, 1, 1, 0,
    0, 3, 0, 0, 0, 1, 0, 1, 0, 1,
    0, 0, 0, 1, 0, 0, 1, 1, 1, 0
  ],
  "capacity_requirements": {
    "per_minute": 14,
    "per_hour": 240,
    "per_day": 0
  }
}
		
  1. 系统中有 26 个任务,包括常规任务、循环任务和失败任务。
  2. 有 2 个 idle(空闲)索引阈值警报任务,这意味着它们计划在未来的某个时间点运行。
  3. 在支持 ES 索引操作的 14 个任务中,10 个失败,2 个正在运行。
  4. 队列中没有非循环任务。
  5. 有一个任务管理器正在积极执行任务。可能还有其他空闲的任务管理器,但它们目前没有积极执行任务。
  6. 所有已调度循环任务的直方图显示,有 2 个任务计划每 10 秒运行一次,2 个任务计划每分钟运行一次,依此类推。
  7. 没有逾期的非循环任务。非循环任务通常安排立即执行,因此逾期的非循环任务通常是系统拥堵的征兆。
  8. 没有逾期任务,这意味着所有本应在此之前运行的任务都已运行。
  9. 此直方图显示了计划在接下来的 20 个轮询周期内运行的任务。该直方图代表整个部署,而不仅仅是这个 Kibana 实例。
  10. 处理系统中循环任务所需的容量。这些是存储桶,而不是聚合总数,我们建议评估容量估计部分,而不是自己评估这些存储桶。

workload(工作负载)部分总结了整个集群的工作负载,列出了系统中的任务、其类型、调度和当前状态。

你可以从这些统计信息推断出默认部署应该足够了。此评估基于以下内容

  • 估计的调度密度较低。
  • 相对于默认容量,系统中的任务并不多。

假设 stats.workload.value 的输出看起来像这样

{
  "count": 2191,
  "task_types": {
    "alerting:.index-threshold": {
      "count": 202,
      "status": {
        "idle": 183,
        "claiming": 2,
        "running": 19
      }
    },
    "alerting:.es-query": {
      "count": 225,
      "status": {
        "idle": 225,
      }
    },
    "actions:.index": {
      "count": 89,
      "status": {
        "idle": 24,
        "running": 2,
        "failed": 63
      }
    },
    "alerting:xpack.uptime.alerts.monitorStatus": {
      "count": 87,
      "status": {
        "idle": 74,
        "running": 13
      }
    },
  },
  "non_recurring": 0,
  "owner_ids": 1,
  "schedule": [
    ["10s", 38],
    ["1m", 101],
    ["90s", 55],
    ["5m", 89],
    ["20m", 62],
    ["60m", 106],
    ["1d", 61]
  ],
  "overdue_non_recurring": 0,
  "overdue": 0,
  "estimated_schedule_density": [
    10, 1, 0, 10, 0, 20, 0, 1, 0, 1,
    9, 0, 3, 10, 0, 0, 10, 10, 7, 0,
    0, 31, 0, 12, 16, 31, 0, 10, 0, 10,
    3, 22, 0, 10, 0, 2, 10, 10, 1, 0
  ],
  "capacity_requirements": {
    "per_minute": 329,
    "per_hour": 4272,
    "per_day": 61
  }
}
		
  1. 系统中有 2,191 个任务。
  2. 已调度的任务分布在各种节奏中。
  3. 调度密度表明你预计会超过默认的 10 个并发任务。
  4. 有 329 个任务执行在每分钟的间隔内循环。
  5. 有 4,273 个任务执行在每小时的间隔内循环。
  6. 有 61 个任务执行在每天的间隔内循环。

你可以从该输出中推断出工作负载的几个重要属性

  • 你的系统中有许多任务,确保这些任务在其预定节奏下运行需要关注任务管理器的吞吐量。
  • 评估高频任务(循环节奏为几分钟或更短的任务),你必须支持大约每分钟 330 个任务执行的吞吐量(每 10 秒 38 个 + 每分钟 101 个)。
  • 评估中频任务(循环节奏为一小时或更短的任务),你必须支持每小时超过 4,272 个任务执行的额外吞吐量(每 90 秒 55 个 + 每 5 分钟 89 个 + 每 20 分钟 62 个 + 每小时 106 个)。你可以通过将这些任务计算为每分钟额外的 70 - 80 个任务来平均计算该小时所需的吞吐量。
  • 评估估计的调度密度,有些周期需要并发运行多达 31 个任务,而在这些周期旁边,还有空闲周期。你可以期望任务管理器在整个空闲周期内对这些任务进行负载均衡,但这可能不会留下太多容量来处理未来可能调度的、新任务的激增。

这些粗略计算为你提供了所需吞吐量的下限,即至少每分钟 410 个任务,以确保循环任务在其预定时间执行。此吞吐量既不计入可能已调度的非循环任务,也不计入未来可能调度的任务(循环或其他任务)。

鉴于这些推断出的属性,可以放心地假设具有默认设置的单个 Kibana 实例将无法提供所需的吞吐量。通过添加更多的 Kibana 实例进行水平扩展可能会提供所需的吞吐量。

有关扩展任务管理器的详细信息,请参阅扩缩容指南

任务管理器不断评估其运行时操作和工作负载。这使任务管理器能够对其容量的充足性做出粗略估计。

顾名思义,这些是基于历史数据的估计,不应用作预测。在对基础设施进行更改之前,应将这些估计与详细的健康监视统计信息一起评估。这些估计假设所有 Kibana 实例的配置完全相同。

我们建议在遵循任务管理器扩缩容指南时使用这些估计。

评估前一个例子中的健康统计信息时,你可以在 stats.capacity_estimation.value 下看到以下输出

{
  "observed": {
    "observed_kibana_instances": 1,
    "minutes_to_drain_overdue": 1,
    "max_throughput_per_minute_per_kibana": 200,
    "max_throughput_per_minute": 200,
    "avg_recurring_required_throughput_per_minute": 28,
    "avg_recurring_required_throughput_per_minute_per_kibana": 28,
    "avg_required_throughput_per_minute": 28,
    "avg_required_throughput_per_minute_per_kibana": 28
  },
  "proposed": {
    "min_required_kibana": 1,
    "provisioned_kibana": 1,
    "avg_recurring_required_throughput_per_minute_per_kibana": 28,
    "avg_required_throughput_per_minute_per_kibana": 28
  }
}
		
  1. 这些估计假设有一个 Kibana 实例正在积极执行任务。
  2. 根据过去的吞吐量,系统中的逾期任务可以在 1 分钟内执行完毕。
  3. 假设集群中的所有 Kibana 实例与此实例的配置相同,则最大可用吞吐量为每分钟 200 个任务。
  4. 平均而言,系统中的循环任务历来需要每分钟 28 个任务的吞吐量。
  5. 平均而言,无论它们是否为循环任务,系统中的任务历来需要每分钟 28 个任务的吞吐量。
  6. 一个 Kibana 实例应该足以运行当前的工作负载。
  7. 我们建议等待工作负载发生变化,然后再配置额外的 Kibana 实例。

capacity_estimation(容量估计)部分由两个子部分组成

  • observed(观察值)通过观察历史运行时和工作负载统计信息来估计当前容量
  • proposed(建议值)估计基线 Kibana 集群规模以及在此类部署策略下的预期吞吐量

你可以从这些估计推断出,当前的系统利用率不足,并且有足够的容量来处理比目前更多的任务。

假设另一种场景,你在 stats.capacity_estimation.value 下看到以下输出

{
  "observed": {
    "observed_kibana_instances": 2,
    "max_throughput_per_minute_per_kibana": 200,
    "max_throughput_per_minute": 400,
    "minutes_to_drain_overdue": 12,
    "avg_recurring_required_throughput_per_minute": 354,
    "avg_recurring_required_throughput_per_minute_per_kibana": 177,
    "avg_required_throughput_per_minute": 434,
    "avg_required_throughput_per_minute_per_kibana": 217
  },
  "proposed": {
    "min_required_kibana": 2,
    "provisioned_kibana": 3,
    "avg_recurring_required_throughput_per_minute_per_kibana": 118,
    "avg_required_throughput_per_minute_per_kibana": 145
  }
}
		
  1. 这些估计假设有两个 Kibana 实例正在积极执行任务。
  2. 目前系统中最大可用吞吐量为每分钟 400 个任务。
  3. 根据过去的吞吐量,系统中的逾期任务应该在 12 分钟内执行完毕。
  4. 平均而言,系统中的循环任务历来需要每分钟 354 个任务的吞吐量。
  5. 平均而言,每个 Kibana 实例利用其每分钟 177 个任务的容量来执行循环任务。
  6. 平均而言,系统中的任务历来需要每分钟 434 个任务的吞吐量。
  7. 系统估计至少需要两个 Kibana 实例来运行当前的循环工作负载。
  8. 系统建议配置三个 Kibana 实例来处理该工作负载。
  9. 一旦配置了第三个 Kibana 实例,每个实例用于执行循环任务所消耗的容量应从每分钟 177 个任务降至 118 个。
  10. 考虑到历史临时任务执行情况,我们估计一旦配置了第三个 Kibana 实例,每个 Kibana 实例所需的吞吐量将从每分钟 217 个任务降至 145 个。

通过这些估计进行评估,我们可以推断出系统的一些有趣属性

  • 这些估计是基于集群中有两个 Kibana 实例的假设生成的。此数字基于最近几分钟内积极执行任务的 Kibana 实例数量。如果 Kibana 实例保持空闲,有时此数字可能会波动,因此建议根据你对系统的了解来验证这些估计。
  • 似乎有太多的逾期任务,需要 12 分钟的执行时间才能追赶上积压的工作。这并未将在这 12 分钟内可能变逾期的任务计算在内。尽管这种拥堵可能是暂时的,但系统也可能一直处于资源不足的状态,并且可能永远无法完全清空积压工作。
  • 评估工作负载中的循环任务,系统平均需要每分钟 354 个任务的吞吐量才能准时执行任务,这低于估计的每分钟 400 个任务的最大吞吐量。然而,一旦我们将历史吞吐量考虑在内,我们估计所需的吞吐量为每分钟 434 个任务。这表明,从历史上看,大约 20% 的任务是临时非循环任务,其规模比循环任务更难预测。

你可以从这些估计推断出,当前系统中的容量不足,至少需要一个额外的 Kibana 实例才能跟上工作负载。

有关扩展任务管理器的详细信息,请参阅扩缩容指南

问题:

任务计划每 2 秒运行一次,但似乎运行延迟。

解决方案:

任务管理器按照 xpack.task_manager.poll_interval 设置指定的节奏轮询任务,该设置默认值为 3 秒。这意味着如果任务使用的调度时间小于此设置,则该任务可能会延迟运行。

你可以调整 xpack.task_manager.poll_interval 设置。但是,这会给集群中的 Kibana 和 Elasticsearch 实例增加一些负载,因为它们必须执行更多查询。

问题:

任务管理器中存在潜在问题的最常见症状是任务显得运行延迟。例如,循环任务可能会以不一致的节奏运行,或者在其预定时间很久之后运行。

解决方案:

默认情况下,Kibana 以每 3 秒 10 个任务的速率轮询任务。

如果许多任务计划同时运行,则待处理的任务会在 Elasticsearch 中排队。然后,每个 Kibana 实例以每 3 秒最多 10 个任务的速率轮询待处理任务。队列中的待处理任务可能会超过此容量,从而导致运行延迟。

这种类型的延迟被称为 drift(漂移)。漂移的根本原因取决于具体的使用情况,并且没有应对漂移的硬性规则。

例如

  • 如果漂移是由相对于集群中 Kibana 实例可用容量而言过多的并发任务引起的,你可以扩大集群的吞吐量。
  • 如果漂移是由超出其调度节奏的长时间运行任务引起的,你可以重新配置相关任务。

有关识别正确解决方案的分步说明,请参阅诊断漂移的根本原因

通常可以通过调整部署的扩缩容以更好地适应你的使用情况来解决 drift(漂移)。有关扩展任务管理器的详细信息,请参阅扩缩容指南

问题:

任务的 runAt 属性在过去。

解决方案:

在宣布它无可救药之前稍等片刻,因为任务管理器可能只是工作落后了。你应该查看 Kibana 日志,看看能找到哪些与任务管理器相关的内容。在健康的环境中,你应该会看到一行日志,表明 Kibana 启动时任务管理器已成功启动

server log [12:41:33.672] [info][plugins][taskManager][taskManager] TaskManager is identified by the Kibana UUID: 5b2de169-2785-441b-ae8c-186a1936b17d
		

如果你看到该消息且没有其他与任务管理器相关的错误,则很可能是任务管理器运行正常,只是还没有机会拾取该任务。另一方面,如果 runAt 严重逾期,则值得寻找其他与任务管理器或警报相关的错误,因为可能出了其他问题。值得查看 status(状态)字段,因为它可能已经失败(这可以解释为什么它没有被拾取),或者它可能正在运行(这意味着该任务可能是一个运行时间非常长的任务)。

问题:

任务未运行,并且服务器日志包含以下错误消息

[warning][plugins][taskManager] Task Manager cannot operate when inline scripts are disabled in Elasticsearch
		

解决方案:

内联脚本是任务管理器正常运行的硬性要求。要启用内联脚本,请查看 Elasticsearch 文档中关于配置允许的脚本类型设置的内容。

问题:

任务被标记为失败。

解决方案:

广义上讲,警报框架旨在通过在未来重新调度一次新的运行来优雅地处理任务失败的情况。如果未能发生这种情况,则意味着底层实现中出现了问题,这是意料之外的。理想情况下,你应该尝试查找与此规则及其任务相关的任何日志行,并使用这些日志行来帮助我们做进一步调查。

任务管理器会在某些情况下将日志行写入 Kibana 日志。以下是一些常见的日志行及其含义。

任务管理器已耗尽可用工作线程

server log [12:41:33.672] [info][plugins][taskManager][taskManager] [Task Ownership]: Task Manager has skipped Claiming Ownership of available tasks at it has ran out Available Workers.
server log [12:41:33.672] [warn][plugins][taskManager][taskManager] taskManager plugin is now degraded: Task Manager is unhealthy - Reason: setting HealthStatus.Error because of expired hot timestamps
		

此日志消息告诉我们,任务管理器无法跟上其需要完成的庞大工作量。这可能意味着规则没有按预期的频率运行(例如,不是每 5 分钟运行一次,而是每 7-8 分钟运行一次)。

默认情况下,任务管理器限制为 10 个任务,可以通过在 kibana.yml 文件中使用 xpack.task_manager.capacity 配置设置更高的数字来提高此限制。请务必记住,在任何给定时间运行更多的任务意味着对 Kibana 和 Elasticsearch 都会产生更大的负载;只有在增加环境中的负载具有合理性时,才更改此设置。

解决此问题的另一种方法可能是让工作线程以更高的速率运行,而不是添加更多工作线程,这可以使用 xpack.task_manager.poll_interval 进行配置。此值决定了任务管理器检查是否有更多工作要完成的频率,单位为毫秒(默认值为 3000,这意味着间隔为 3 秒)。

在更改这两个数字之前,强烈建议调查为什么任务管理器无法跟上进度 - 系统中是否存在异常大量的规则?规则是否经常失败,迫使任务管理器不断运行它们?Kibana 是否处于重负载下?可能会有各种各样的问题,切勿仅通过简单地更改这些配置来解决所有问题。

Task TaskType 尝试运行失败

server log [12:41:33.672] [info][plugins][taskManager][taskManager] Task TaskType "alerting:example.always-firing" failed in attempt to run: Unable to load resource ‘/api/something’
		

此日志消息告诉我们,当任务管理器运行我们的规则之一时,其任务出错并因此失败。在这种情况下,我们可以看出失败的规则类型为 alerting:example.always-firing,失败原因是 Unable to load resource ‘/api/something’ 。这是一个虚构的例子,但总体而言,如果你看到这种格式的消息,它会告诉你很多关于问题可能所在的信息。

例如,在这种情况下,我们希望看到来自警报框架本身的相应日志行,指出该规则失败。你应该在 Kibana 日志中查找类似于下方日志行的行(可能在任务管理器日志行之前不久)

Executing Rule "27559295-44e4-4983-aa1b-94fe043ab4f9" has resulted in Error: Unable to load resource ‘/api/something’
		

这将证实错误确实发生在规则本身(而不是任务管理器)中,并且它将帮助我们精确定位失败规则的具体 ID:27559295-44e4-4983-aa1b-94fe043ab4f9

我们现在可以使用该 ID,通过使用 HTTP 端点查找该规则的配置和当前状态,以了解有关该规则的更多信息,从而帮助调查可能导致该问题的原因。

© . This website operates independently and is not affiliated with or endorsed by Elasticsearch B.V. All brand names, logos, and trademarks are the property of their respective owners.