OpenSearch 异常检测

OpenSearch 异常检测

在 OpenSearch 中,异常指时间序列数据中不寻常的行为变化。异常能够揭示有价值的信息。例如,IT 基础设施的内存使用指标出现异常,可能是系统故障的早期信号。

仅靠可视化和仪表板等传统方式,可能难以发现异常。虽然可以按固定阈值配置告警,但这需要领域知识,而且未必适合自然增长或存在季节性趋势的数据。

异常检测使用随机切割森林(Random Cut Forest,RCF)算法,近乎实时地自动发现 OpenSearch 数据中的异常。RCF 是无监督机器学习算法,它对输入数据流建立概要模型,为每个数据点计算异常等级和置信度,用来区分异常与正常波动。算法详见 Robust Random Cut Forest Based Anomaly Detection on Streams。

可以搭配告警插件,在发现异常时收到通知。

在 OpenSearch Dashboards 中开始使用异常检测

依次打开 OpenSearch Dashboards > OpenSearch Plugins > Anomaly Detection。

第一步:定义检测器

检测器是一个独立的异常检测任务。可以定义多个检测器,让它们同时运行、分别分析不同来源的数据。按以下步骤定义检测器:

  1. 在 Anomaly detection 页面选择 Create detector。

  2. 在 Define detector 页面填写名称和简短说明。名称必须唯一,并能清楚说明检测器用途。

  3. 在 Select data 面板的 Index 下拉列表中选择一个或多个数据源,可以是索引、索引模式或别名。

检测器支持远程索引,访问格式为 cluster-name:index-name,详见跨集群搜索。从 OpenSearch Dashboards 2.17 起,也可以直接选择集群和索引。启用 Security 插件时,请参阅异常检测安全文档中的远程索引细粒度访问控制。

在 OpenSearch Dashboards 中创建跨集群检测器,需要以下权限:indices:data/read/field_caps、indices:admin/resolve/index 和 cluster:monitor/remote/info。

  1. 可选:选择 Add data filter,设置 Field、Operator 和 Value 来筛选数据。也可以选择 Use query DSL,输入 JSON 格式的布尔查询。此处的查询 DSL 只支持布尔查询。

示例:使用查询 DSL 筛选数据

下面的查询检索 urlPath.keyword 字段匹配任意指定值的文档:

 {
    "bool": {
       "should": [
             {
                "term": {
                   "urlPath.keyword": "/domain/{id}/short"
                }
             },
             {
                "term": {
                   "urlPath.keyword": "/sub_dir/{id}/short"
                }
             },
             {
                "term": {
                   "urlPath.keyword": "/abcd/123/{id}/xyz"
                }
             }
       ]
    }
 }
  1. 在 Timestamp 面板的 Timestamp field 下拉列表中选择时间戳字段。

  2. 可选:若要将异常检测结果存入自定义索引,选择 Enable custom results index 并输入名称,例如 abc。插件创建由 opensearch-ad-plugin-result- 和该名称组成的别名,例如 opensearch-ad-plugin-result-abc。别名指向带有日期和序号的实际索引,例如 opensearch-ad-plugin-result-abc-history-2024.06.12-000002,结果保存在该索引中。

可以用 - 分隔命名空间,管理自定义结果索引的权限。例如结果索引为 opensearch-ad-plugin-result-financial-us-group1 时,可以按 opensearch-ad-plugin-result-financial-us-* 创建角色,在 financial 部门下细分 us 组的权限。

权限

启用 Security 插件的细粒度访问控制后,默认结果索引成为系统索引,无法通过标准 Index 或 Search API 访问,只能通过异常检测 RESTful API 或仪表板读取。因此启用该插件时,不能基于默认结果索引构建自定义仪表板;可以改用自定义结果索引。

如果指定的自定义索引不存在,异常检测插件会在创建检测器并启动实时或历史分析时创建它。

如果自定义索引已经存在,插件会核对映射是否符合异常结果所需结构。此时应确保映射符合 anomaly-results.json 的定义。使用自定义结果索引需要以下权限:

  • indices:admin/create:创建和滚动更新自定义索引。
  • indices:admin/aliases:创建和管理索引别名。
  • indices:data/write/index:将单实体检测器的结果写入索引。
  • indices:data/read/search:搜索自定义结果索引,在异常检测界面显示结果。
  • indices:data/write/delete:检测器可能产生大量结果,需要删除旧数据以节省磁盘空间。
  • indices:data/write/bulk*:插件通过 Bulk API 写入结果。

展平嵌套字段

自定义结果索引的嵌套字段会给聚合和可视化带来困难。Enable flattened custom result index 可以展平这些字段。启用后,插件创建一个名称包含自定义结果索引名和检测器名的独立索引。例如检测器 Test 使用索引 abc 时,别名为 opensearch-ad-plugin-result-abc-flattened-test 的独立索引保存展平后的结果。

插件还会创建包含脚本处理器的摄取管道,将它绑定到独立索引,并使用 Painless 脚本展平自定义结果索引中的所有嵌套字段。详见 Painless 脚本语言。

对运行中的检测器关闭此选项,会移除其展平摄取管道;该管道也不再是结果索引的默认管道。使用展平结果选项时,请注意:

  • 插件根据自定义结果索引和检测器名称构造索引名。检测器名称可以修改,因此可能发生名称冲突;冲突时插件复用该索引名。
  • 异常检测仪表板会从所有自定义结果索引查询所有检测器的结果,索引过多可能影响性能。
  • 可以使用索引状态管理滚动更新旧结果索引,也可以手动删除或归档旧索引。建议多个检测器复用同一个自定义结果索引。

当自定义结果索引满足下表任一条件时,插件将别名滚动切换到新索引。

参数 含义 类型 单位 示例 必填
result_index_min_size 滚动更新所需的主分片总大小下限,不含副本。例如阈值为 100 GiB,索引包含 5 个主分片和 5 个副本分片,每片 20 GiB 时,会执行滚动更新。 integer MB 51200 否
result_index_min_age 从创建时间到当前时间计算的索引最小年龄,达到后滚动更新。 integer day 7 否
result_index_ttl 删除已滚动更新索引所需的最小年龄。 integer day 60 否

完成检测器设置后,选择 Next 配置模型。

第二步:配置模型

向检测器添加特征。特征是字段的聚合结果或 Painless 脚本。检测器可以跨一个或多个特征发现异常。

每个特征都必须选择聚合方法:average()、count()、sum()、min() 或 max()。方法决定检测器依据什么判断异常。例如 min() 关注特征最小值的异常,average() 则关注平均值的异常。

也可以使用自定义 JSON 聚合查询作为聚合方法。编写方法见 Query DSL。

每个特征还可以设置异常判定方向。默认情况下,实际值异常高于或低于预期值都会被判为异常;也可以只关注高于预期值的峰值,或低于预期值的下降。例如为 cpu_utilization 创建检测器时,可以只记录突增,以减少告警疲劳。

使用阈值规则抑制异常

在 Feature selection 面板中,可以使用绝对值或相对百分比,指定实际值与预期值之间可接受的差异。这能减少细微波动导致的误报,让你关注显著偏差。

若要抑制与预期值偏差小于 30% 的异常,可以设置以下规则:

  • 实际值高于预期值不超过 30% 时,忽略异常。
  • 实际值低于预期值不超过 30% 时,忽略异常。

下图展示了名为 LogVolume 的特征,可在此设置相对偏差百分比:

原文界面配图

如果希望日志量与预期值至少相差 10,000 才视为异常,可以设置以下绝对阈值:

  • 实际值高于预期值不超过 10,000 时,忽略异常。
  • 实际值低于预期值不超过 10,000 时,忽略异常。

下图展示了 LogVolume 特征的绝对阈值设置面板:

原文界面配图

未设置自定义抑制规则时,系统默认忽略每个已启用特征与预期值偏差小于 20% 的异常。

多特征模型会关联所有特征中的异常。由于维度灾难,它相比单特征模型更难识别较小的异常。增加特征可能降低模型的精确率和召回率,较高的数据噪声比例还会放大这种影响。建议反复测试不同特征数量上限,找出适合的特征集合。检测器默认最多包含 5 个特征,可用 plugins.anomaly_detection.max_anomaly_features 调整。

根据聚合方法配置模型

按聚合方法配置模型的步骤如下:

  1. 在 Detectors 页面选择检测器。
  2. 在详情页打开 Actions 菜单,选择 Edit model configuration。
  3. 在编辑页面选择 Add another feature。
  4. 填写 Feature name,勾选 Enable feature。
  5. 在 Find anomalies based on 中选择 Field value。
  6. 在 Aggregation method 中选择聚合方法。
  7. 在 Field 中选择字段。
  8. 选择 Save changes。

根据 JSON 聚合查询配置模型

按 JSON 聚合查询配置模型的步骤如下:

  1. 在 Edit model configuration 页面选择 Add another feature。
  2. 填写 Feature name,勾选 Enable feature。
  3. 在 Find anomalies based on 中选择 Custom expression,打开 JSON 编辑器。
  4. 输入 JSON 聚合查询。
  5. 选择 Save changes。

可接受的 JSON 查询语法见 OpenSearch Query DSL。

为高基数数据设置分类字段

可以按 keyword 或 IP 类型字段分类异常。启用 Categorical fields 后,可按 IP 地址、产品 ID、国家代码等维度切分源时间序列,细看各实体中的异常,以便定位和调试问题。

选择 Enable categorical fields,再选择字段。检测器创建后不能更改分类字段。

分类字段支持的唯一实体数量有限。可用以下公式估算集群建议支持的实体总数:

(data nodes * heap size * anomaly detection maximum memory percentage) / (entity model size of a detector)

使用 Profile Detector API 获取实体模型大小。最大内存百分比可由 plugins.anomaly_detection.model_max_size_percent 调整。

例如集群有 3 个数据节点,每个节点 JVM 堆为 8 GB,默认分配 10% 内存;每个实体模型大小为 1 MB。原文用以下公式估算唯一实体数量:

(8096 MB * 0.1 / 1 MB ) * 3 = 2429

如果实际唯一实体数超过估算值(原文示例为 2,429),检测器仍会尝试为额外实体建模,优先考虑出现频率较高且近期出现的实体。原文公式将 8 GB 写成 8096 MB;容量规划时应按实际堆字节数和单位重新计算。

这个公式只是起点,应使用有代表性的负载测试。更多信息见 Improving Anomaly Detection: One million entities in one minute。

运行设置

OpenSearch Dashboards 的 Suggest parameters 会分析近期历史,推荐合理的默认值。也可以自行调整以下参数。

检测器间隔

指定聚合桶大小,例如 10 分钟。应按实际数据特征设置:

  • 间隔较长:平滑噪声、降低计算成本,但检测更迟。
  • 间隔较短:更快发现变化,但资源用量增加,也可能引入噪声。

间隔应足够大,使数据缺失较少。模型通过 shingling 将连续相邻的桶组合起来,缺桶会降低数据质量并影响窗口形成。

运行频率(可选)

指定任务查询、评分和写入结果的频率。较短值更新更实时但成本更高;较长值降低负载但更新较慢。运行周期必须是检测间隔的整数倍,默认等于检测间隔。

不确定时可以留空,任务会使用检测间隔。

运行周期大于检测间隔的常见场景:

  1. 批量处理短时间桶以提高效率。 对不要求极快告警的高频、大流量日志,包含复杂连接或高基数特征的负载,以及合规要求每晚生成不可修改的每日异常记录供审核的场景,每 1~2 分钟运行可能浪费资源。可以降低执行频率,一次处理多个短间隔。例如每 6 小时运行一次,可一次处理约 360 个一分钟桶。应按告警延迟和成本目标选择 30 分钟、1 小时、3 小时、6 小时或 12 小时等周期。
  • 好处:减少调度开销,提高资源利用率,尤其适用于任务多或集群繁忙的情况。
  • 代价:检测延迟增加,一分钟桶中的异常可能要到批处理运行时才报告。
  • 适合:成本和负载控制、合规与审计。
  1. 适应低频或批量日志摄取。 日志可能不定期到达或批量到达,例如每天从 S3 导入一次,或 IoT 设备集中上传。每分钟运行大多只得到空结果。将周期调到接近数据到达周期(例如一天),更容易查到新数据。对于时间戳不规则、量少的零散日志,中间结果可能损害准确性,因为 RCF 是有状态模型,假定时间戳严格递增。降低频率相当于等待完整数据,而非反复查询空索引。
  • 好处:减少无意义查询和 CPU 开销,提高效率及结果准确性;日志批次到达后再评估,减少中间误报风险。
  • 代价:异常评估更不频繁。
  • 适合:批处理任务、零散日志摄取。
窗口延迟(可选)

若数据采集需要额外处理时间,可以设置 Window delay,告诉检测器数据进入 OpenSearch 存在延迟。

工作方式:

窗口延迟会平移检测区间,补偿摄取延迟。例如: – 检测器间隔:10 分钟。 – 数据摄取延迟:1 分钟。 – 检测器执行时间:下午 2:00。

没有窗口延迟时,检测器查询 1:50~2:00,却只能获得 9 分钟的数据,缺少 1:59~2:00。将窗口延迟设为 1 分钟,会把区间移动到 1:49~1:59,从而读取完整的 10 分钟数据。

建议: – 将窗口延迟设为预期摄取延迟的上限,避免缺数据。 – 权衡准确性与时效性;延迟过长会妨碍实时异常检测。

历史数据(可选)

指定训练初始冷启动模型使用的历史数据点数量,最多 10,000 个。在此上限以内,增加历史数据有助于提高初始模型准确性。

如何选择运行频率和窗口延迟

两者都能应对摄取延迟,但适合不同的数据到达模式:

  • 窗口延迟:更适合持续少量到达的流式数据。
  • 运行频率:更适合周期性集中到达的批量数据。

场景示例:

  • 示例 A:每分钟到达数据,但始终晚一天——使用窗口延迟。
    • 模式:Day-1 00:01, 00:02, ..., 23:59 的数据,在 Day-2 相同分钟逐步到达。
    • 配置:interval = 1 min、window_delay = 1 day、frequency = 1 min。
    • 效果:Day-2 00:01 的运行处理 Day-1 00:01,Day-2 00:02 处理 Day-1 00:02,依此类推,直到 Day-2 23:59 处理前一天对应分钟。
    • 原因:每分钟的数据都有可预测的 24 小时延迟。一天的窗口延迟保证按预定时间戳处理,同时保持增量负载。
  • 示例 B:第一天全部数据在第二天零点到达——使用每日运行周期。
    • 模式:Day-1 没有数据进入;Day-2 00:00 一次收到覆盖 1,440 分钟的数据。
    • 配置:interval = 1 min、frequency = 1 day,一次处理全天。可再设 1~5 分钟的 window_delay,补偿索引或刷新延迟。
    • 最佳情况:检测器在 00:00 左右启动,Day-2 00:00 的运行在数据到达后就处理第一天全部数据。
    • 最差情况:若检测器在 23:59 左右启动,要等到 Day-2 23:59 才执行,额外等待约 24 小时。
    • 一般规律:对于午夜到达的数据,额外等待时间取决于检测器每天的启动时刻。
    • 原因:全天数据同时可用,一天处理一次远比逐分钟运行高效。

下图比较一天摄取延迟的两种处理方式:上方是第一天的数据摄取,中间连续条带是第二天使用 window_delay = 1 day 的处理,下方竖条是 frequency = 1 day 的单次运行。每日运行可能紧随第一天结束,也可能再晚将近一天,取决于初次启动时刻;之后每天大致在这一时刻执行。

原文界面配图

设置 shingle 大小

在 Advanced settings 中,可以设置检测窗口包含的数据流聚合间隔数。应结合实际数据选择最佳值。选择 Show,在 intervals 中输入大小。

shingle 大小必须为 1~128,默认 8。只有至少包含两个特征时才使用 1。小于 8 可能提高召回率,同时也可能增加误报;大于 8 可能有助于忽略信号噪声。

设置缺失值填补选项

在 Advanced settings 中,可以选择如何处理数据流中的缺失值:

  • Ignore Missing Data(默认):不考虑缺失点,继续现有数据流。
  • Fill with Custom Values:为每个特征指定替代缺失点的值,实现针对性填补。
  • Fill with Zeros:用零替代缺失值,适合数据缺失本身代表重要事件的情况,例如事件计数降为零。
  • Use Previous Values:沿用最后观测值,维持时间序列连续性;这会把缺失视为非异常,延续之前趋势。

这些选项有助于提高召回率。例如监测事件计数部分下降或完全消失时,用零填补有助于检测显著的数据缺失。

大量数据缺失时应谨慎填补,因为缺口过多会损害准确性。输入数据质量至关重要,低质量数据会导致模型表现不佳。发生填补时置信度也会降低。可以通过异常结果索引中的 feature_imputed 字段判断特征值是否经过填补,详见异常结果映射。

预览异常样本

可以基于特征样本预览异常,再按需要调整设置。插件抽取少量样本,例如每 30 分钟一个数据点,并通过插值估算其余点,近似实际特征数据。检测器加载样本集后生成异常预览。

  1. 选择 Preview sample anomalies。如果没有结果,检查检测间隔,确认预览日期范围内实体具有至少 400 个数据点。
  2. 选择 Next。

第三步:设置检测任务

若要近乎实时地检测异常,选择 Start real-time detector automatically (recommended)。

若希望分析几周或几个月的历史窗口,选择 Run historical analysis detection,并指定至少覆盖 128 个检测间隔的日期范围。

历史分析有助于熟悉插件,也可用历史数据评估并微调检测器。

启用实时检测器前,可以用不同特征集合进行历史分析,检查精确率。

第四步:检查检测器设置

检查检测器和模型配置,确认有效后选择 Create detector。

如果出现验证错误,修改相应设置,再返回检测器页面。

第五步:观察结果

选择 Real-time results 或 Historical analysis 标签页。实时结果需要一定时间才会出现。例如检测间隔为 10 分钟时,检测器可能需要一小时初始化,以等待足够数据来生成异常结果。

较短间隔能让模型更快完成 shingle 过程并产生结果。可通过 profile detector 检查数据点是否足够。

如果初始化持续超过一天,请聚合现有数据,按检测间隔检查是否缺失数据点;缺失较多时,考虑增大检测间隔。

在异常折线图上点击并拖动,可以放大查看异常细节。

可以使用以下可视化分析异常:

  • Live anomalies:显示最近 60 个检测间隔的实时异常。例如间隔为 10 分钟时显示最近 600 分钟,每 30 秒刷新。
  • Anomaly overview(实时结果)或 Anomaly history(历史分析):展示异常等级及对应置信度,包括指定时间范围内的异常次数、平均异常等级、置信度和最后一次异常时间。
  • Average anomaly grade:0~1 之间的数值。0 表示不是异常,非零值表示相对严重程度。
  • Confidence:对报告的异常等级符合预期异常等级之概率的估计。模型观察更多数据、学习行为与趋势后,置信度会提高。置信度不同于模型准确性。
  • Last anomaly occurrence:最后一次异常发生的时间。

Anomaly overview 和 Anomaly history 下还有以下内容:

  • Feature breakdown:按聚合方法绘制特征,可调整日期时间范围。选择折线图上的一点,会显示 Feature output(原文描述为字段在索引中出现的次数)和 Expected value(特征输出的预测值)。没有异常时,输出值和预期值相等。

  • Anomaly occurrences:显示每次异常的 Start time、End time、Data confidence 和 Anomaly grade。在 Actions 列选择 View in Discover,可查看相关日志;日志包含开始时间前和结束时间后各 10 分钟的缓冲区间。

选择异常折线图上的一点,还会显示 Feature Contribution,即特征对异常的贡献百分比。

设置分类字段后,还会出现 Heat map 热力图,关联异常实体的结果。未选择异常实体时图表为空。选择后可查看异常时段(anomaly_grade > 0)的异常和特征折线图。

如果设置了多个分类字段,可以选择字段子集进行筛选和排序,从而查看与另一字段共享同一值的某字段排名靠前的值。

例如分类字段为 ip 和 endpoint 时,在 View by 中选择 endpoint,再选一个单元格,即可把前 20 个 ip 值叠加到图表中。插件默认选择排名第一的 ip,最多同时查看 5 条独立时间序列。

第六步:设置告警

在 Real-time results 下选择 Set up alerts,配置监视器,在检测到异常时通知你。创建监视器和通知的方法见配置异常告警。

停止或删除检测器时,也应删除与它关联的监视器。

查看和更新检测器配置

选择 Detector configuration 标签页查看全部配置。

  1. 要修改配置,或微调时间间隔以减少误报,在 Detector configuration 中选择 Edit。必须先停止实时和历史分析;确认停止后再继续。
  2. 要启用或禁用特征,在 Features 中选择 Edit,调整后选择 Save and start detector。

管理检测器

要启动、停止或删除检测器,打开 Detectors 页面。

  1. 选择检测器名称。
  2. 选择 Actions,再选择 Start real-time detectors、Stop real-time detectors 或 Delete detectors。

原文:Anomaly detection,OpenSearch 官方文档。版权归原作者及 OpenSearch 项目相关权利人所有。

文档仓库使用 Apache License 2.0。本页为中文翻译,并标注了原文计算示例差异。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容