使用 ES|QL

edit
REST API
关于使用ES|QL查询API的信息。
Using ES|QL in Kibana
在 Kibana 中使用 ES|QL 查询和聚合您的数据,创建可视化,并设置警报。
Using ES|QL in Elastic Security
在 Elastic Security 中使用 ES|QL 调查时间线中的事件,创建检测规则,并使用 Elastic AI 助手构建 ES|QL 查询。
Using ES|QL to query multiple indices
使用 ES|QL 查询多个索引并解决字段类型不匹配问题。
Using ES|QL across clusters
使用 ES|QL 跨多个集群进行查询。
Task management
使用任务管理 API来列出和取消 ES|QL 查询。

ES|QL REST API

edit

概述

edit

The ES|QL query API 接受一个ES|QL查询字符串在query参数中,运行它并返回结果。例如:

POST /_query?format=txt
{
  "query": "FROM library | KEEP author, name, page_count, release_date | SORT page_count DESC | LIMIT 5"
}

返回结果:

     author      |        name        |  page_count   | release_date
-----------------+--------------------+---------------+------------------------
Peter F. Hamilton|Pandora's Star      |768            |2004-03-02T00:00:00.000Z
Vernor Vinge     |A Fire Upon the Deep|613            |1992-06-01T00:00:00.000Z
Frank Herbert    |Dune                |604            |1965-06-01T00:00:00.000Z
Alastair Reynolds|Revelation Space    |585            |2000-03-15T00:00:00.000Z
James S.A. Corey |Leviathan Wakes     |561            |2011-06-02T00:00:00.000Z

Kibana 控制台

edit

如果你正在使用Kibana Console(强烈推荐),在创建查询时利用三重引号"""。这不仅会自动转义查询字符串中的双引号("),还支持多行请求:

POST /_query?format=txt
{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """
}

响应格式

edit

ES|QL 可以返回以下人类可读和二进制格式的数据。 您可以通过在 URL 中指定 format 参数或通过设置 AcceptContent-Type HTTP 头来设置格式。

URL参数优先于HTTP头。如果两者都未指定,则响应将以与请求相同的格式返回。

格式

HTTP 头

描述

人类可读

csv

文本/csv

逗号分隔值

json

application/json

JSON(JavaScript 对象表示法)人类可读的格式

tsv

text/tab-separated-values

制表符分隔值

txt

text/plain

类似命令行的表示

yaml

application/yaml

YAML(YAML 不是标记语言)人类可读的格式

二进制

cbor

application/cbor

简洁二进制对象表示法

微笑

application/smile

Smile 二进制数据格式类似于CBOR

箭头

application/vnd.apache.arrow.stream

实验性的。 Apache Arrow 数据框,IPC 流格式

The csv 格式接受一个格式化 URL 查询属性 delimiter,它指示应使用哪个字符来分隔 CSV 值。它默认使用逗号 (,),并且不能使用以下值:双引号 (")、回车 (\r) 和换行 (\n)。制表符 (\t) 也不能使用。请改用 tsv 格式。

使用 Elasticsearch 查询 DSL 进行过滤

edit

filter 参数中指定一个 Query DSL 查询,以过滤 ES|QL 查询所运行的文档集。

POST /_query?format=txt
{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """,
  "filter": {
    "range": {
      "page_count": {
        "gte": 100,
        "lte": 200
      }
    }
  }
}

返回结果:

    author     |                name                |  page_count   | release_date
---------------+------------------------------------+---------------+------------------------
Douglas Adams  |The Hitchhiker's Guide to the Galaxy|180            |1979-10-12T00:00:00.000Z

列式结果

edit

默认情况下,ES|QL 返回的结果为行格式。例如,FROM 将每个文档作为一行返回。对于 jsonyamlcborsmile 格式,ES|QL 可以以列式方式返回结果,其中一行表示结果中某一列的所有值。

POST /_query?format=json
{
  "query": """
    FROM library
    | KEEP author, name, page_count, release_date
    | SORT page_count DESC
    | LIMIT 5
  """,
  "columnar": true
}

返回结果:

{
  "took": 28,
  "columns": [
    {"name": "author", "type": "text"},
    {"name": "name", "type": "text"},
    {"name": "page_count", "type": "integer"},
    {"name": "release_date", "type": "date"}
  ],
  "values": [
    ["Peter F. Hamilton", "Vernor Vinge", "Frank Herbert", "Alastair Reynolds", "James S.A. Corey"],
    ["Pandora's Star", "A Fire Upon the Deep", "Dune", "Revelation Space", "Leviathan Wakes"],
    [768, 613, 604, 585, 561],
    ["2004-03-02T00:00:00.000Z", "1992-06-01T00:00:00.000Z", "1965-06-01T00:00:00.000Z", "2000-03-15T00:00:00.000Z", "2011-06-02T00:00:00.000Z"]
  ]
}

返回本地化结果

edit

在请求体中使用locale参数,以根据地区的惯例返回格式化的结果(特别是日期)。如果未指定locale,则默认为en-US(英语)。请参考JDK支持的地区

语法:locale 参数接受语言标签,格式为(不区分大小写)xyxy-XY

例如,返回法语中的月份名称:

POST /_query
{
  "locale": "fr-FR",
  "query": """
          ROW birth_date_string = "2023-01-15T00:00:00.000Z"
          | EVAL birth_date = date_parse(birth_date_string)
          | EVAL month_of_birth = DATE_FORMAT("MMMM",birth_date)
          | LIMIT 5
   """
}

传递参数到查询

edit

值,例如用于条件,可以通过将值集成到查询字符串本身中,以“内联”方式传递给查询:

POST /_query
{
  "query": """
    FROM library
    | EVAL year = DATE_EXTRACT("year", release_date)
    | WHERE page_count > 300 AND author == "Frank Herbert"
    | STATS count = COUNT(*) by year
    | WHERE count > 0
    | LIMIT 5
  """
}

为了避免任何黑客攻击或代码注入的尝试,请将值提取到一个单独的参数列表中。在查询字符串中为每个参数使用问号占位符(?):

POST /_query
{
  "query": """
    FROM library
    | EVAL year = DATE_EXTRACT("year", release_date)
    | WHERE page_count > ? AND author == ?
    | STATS count = COUNT(*) by year
    | WHERE count > ?
    | LIMIT 5
  """,
  "params": [300, "Frank Herbert", 0]
}

参数可以是命名参数或位置参数。

命名参数使用问号占位符(?)后跟一个字符串。

POST /_query
{
  "query": """
    FROM library
    | EVAL year = DATE_EXTRACT("year", release_date)
    | WHERE page_count > ?page_count AND author == ?author
    | STATS count = COUNT(*) by year
    | WHERE count > ?count
    | LIMIT 5
  """,
  "params": [{"page_count" : 300}, {"author" : "Frank Herbert"}, {"count" : 0}]
}

位置参数使用问号占位符(?)后跟一个整数。

POST /_query
{
  "query": """
    FROM library
    | EVAL year = DATE_EXTRACT("year", release_date)
    | WHERE page_count > ?1 AND author == ?2
    | STATS count = COUNT(*) by year
    | WHERE count > ?3
    | LIMIT 5
  """,
  "params": [300, "Frank Herbert", 0]
}

运行异步 ES|QL 查询

edit

The ES|QL async query API 允许您异步执行查询请求,监控其进度,并在结果可用时检索结果。

执行ES|QL查询通常非常快,然而在大数据集或冻结数据上进行查询可能需要一些时间。为了避免长时间等待,请运行异步ES|QL查询。

通过异步查询 API 发起的查询可能会返回结果,也可能不会。wait_for_completion_timeout 属性决定了等待结果的时间。如果在此时限内结果不可用,则会返回一个查询 ID,稍后可以使用该 ID 来检索结果。例如:

POST /_query/async
{
  "query": """
    FROM library
    | EVAL year = DATE_TRUNC(1 YEARS, release_date)
    | STATS MAX(page_count) BY year
    | SORT year
    | LIMIT 5
  """,
  "wait_for_completion_timeout": "2s"
}

如果在给定的超时时间内(在此情况下为2秒)结果不可用,则不会返回结果,而是返回一个包含以下内容的响应:

  • 一个查询ID
  • 一个is_running值为true,表示查询正在进行中

查询继续在后台运行,不会阻塞其他请求。

{
  "id": "FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=",
  "is_running": true
}

要检查异步查询的进度,请使用带有查询ID的ES|QL async query get API。在wait_for_completion_timeout参数中指定您希望等待完整结果的时间。

GET /_query/async/FmNJRUZ1YWZCU3dHY1BIOUhaenVSRkEaaXFlZ3h4c1RTWFNocDdnY2FSaERnUTozNDE=?wait_for_completion_timeout=30s

如果响应的 is_running 值为 false,则查询已完成,并且返回结果,以及查询的 took 时间。

{
  "is_running": false,
  "took": 48,
  "columns": ...
}

使用 ES|QL async query delete APIkeep_alive 周期结束之前删除异步查询。如果查询仍在运行,Elasticsearch 将取消它。

DELETE /_query/async/FmdMX2pIang3UWhLRU5QS0lqdlppYncaMUpYQ05oSkpTc3kwZ21EdC1tbFJXQToxOTI=

在 Kibana 中使用 ES|QL

edit

您可以在 Kibana 中使用 ES|QL 来查询和聚合您的数据,创建可视化图表,并设置警报。

本指南向您展示如何在 Kibana 中使用 ES|QL。要跟随查询操作,请通过点击 Kibana 主页上的 尝试示例数据,选择 其他示例数据集,然后在 示例 Web 日志 卡片上点击 添加数据 来加载 "Sample web logs" 示例数据集。

启用或禁用 ES|QL

edit

ES|QL 在 Kibana 中默认启用。可以通过 高级设置 中的 enableESQL 设置来禁用它。

这将隐藏各种应用程序中的ES|QL用户界面。 然而,用户将能够访问现有的ES|QL工件,如保存的搜索和可视化。

开始使用 ES|QL

edit

要在 Discover 中开始使用 ES|QL,请打开主菜单并选择 Discover。接下来,从数据视图菜单中选择 语言: ES|QL

esql data view menu

查询栏

edit

切换到ES|QL模式后,查询栏显示一个示例查询。例如:

from kibana_sample_data_logs | limit 10

每个查询都从一个源命令开始。在这个查询中,源命令是FROMFROM从数据流、索引或别名中检索数据。在这个例子中,数据是从kibana_sample_data_logs中检索的。

一个源命令可以跟随一个或多个处理命令。在这个查询中,处理命令是LIMITLIMIT限制了检索的行数。

点击帮助图标(Static)以打开所有命令和函数的内置参考文档。

为了更容易编写查询,自动完成功能提供了可能的命令和函数的建议:

esql kibana auto complete

ES|QL 关键字不区分大小写。以下查询与前一个查询相同:

FROM kibana_sample_data_logs | LIMIT 10

展开查询栏

edit

为了提高可读性,您可以将每个处理命令放在新的一行。以下查询与前一个查询相同:

FROM kibana_sample_data_logs
| LIMIT 10

为了更方便地编写多行查询,点击双头箭头按钮(esql icon expand query bar)以展开查询栏:

esql expanded query bar

要返回到紧凑查询栏,请点击最小化编辑器按钮 (esql icon minimize query bar).

警告

edit

查询可能会导致警告,例如当查询不支持的字段类型时。当这种情况发生时,查询栏中会显示一个警告符号。要查看详细的警告信息,请展开查询栏,然后点击警告

查询历史

edit

您可以在查询栏中重复使用您最近的ES|QL查询。 在查询栏中点击显示最近查询

esql discover show recent query

然后您可以浏览您最近的查询:

esql discover query history

结果表

edit

对于示例查询,结果表显示了10行。省略LIMIT命令,结果表默认最多显示1000行。使用LIMIT,您可以将限制增加到最多10,000行。

10,000 行限制仅适用于查询检索并在 Discover 中显示的行数。任何查询或聚合都在完整数据集上运行。

每行显示示例查询的两列:一列包含@timestamp字段,另一列包含完整文档。要显示文档中的特定字段,请使用KEEP命令:

FROM kibana_sample_data_logs
| KEEP @timestamp, bytes, geo.dest

要显示所有字段为单独的列,请使用 KEEP *

FROM kibana_sample_data_logs
| KEEP *

Discover 中列的最大数量为 50。如果查询返回的列数超过 50 列,Discover 只会显示前 50 列。

排序

edit

要按某一列排序,请点击您想要排序的列名并选择排序顺序。请注意,这是在客户端进行的排序。它仅对查询检索到的行进行排序,这可能不是完整的数据集,因为存在(隐式的)限制。要排序完整的数据集,请使用SORT命令:

FROM kibana_sample_data_logs
| KEEP @timestamp, bytes, geo.dest
| SORT bytes DESC

时间过滤

edit

要在指定的时间范围内显示数据,请使用时间过滤器。只有当您查询的索引中有一个名为@timestamp的字段时,时间过滤器才会启用。

如果你的索引没有名为 @timestamp 的时间戳字段,你可以使用 WHERE 命令和 NOW 函数来限制时间范围。例如,如果时间戳字段名为 timestamp,要查询最近 15 分钟的数据:

FROM kibana_sample_data_logs
| WHERE timestamp > NOW() - 15minutes

分析和可视化数据

edit

在查询栏和结果表之间,Discover 显示了一个日期直方图可视化。如果你查询的索引不包含 @timestamp 字段,则不会显示直方图。

可视化会根据查询进行调整。查询的性质决定了可视化的类型。例如,这个查询聚合了每个目的国家的字节总数:

FROM kibana_sample_data_logs
| STATS total_bytes = SUM(bytes) BY geo.dest
| SORT total_bytes DESC
| LIMIT 3

生成的可视化结果是一个条形图,显示了前3个国家:

esql kibana bar chart

要更改可视化效果,例如更改可视化类型、轴和颜色,请点击铅笔按钮(esql icon edit visualization)。这将打开一个内联编辑器:

esql kibana in line editor

您可以通过点击保存按钮(esql icon save visualization)将可视化保存到新的或现有的仪表板中。保存到仪表板后,您将被带到仪表板页面。您可以继续对可视化进行更改。点击右上角的操作按钮(esql icon options)并选择编辑 ESQL 可视化以打开内联编辑器:

esql kibana edit on dashboard

向仪表板添加面板

edit

您可以使用ES|QL查询在仪表板上创建面板。 要在仪表板上添加面板,在仪表板下,点击添加面板按钮并选择ES|QL。

esql dashboard panel

通过点击面板过滤器按钮(面板标题上的面板过滤器按钮)来检查ES|QL查询:

esql dashboard panel query

您也可以从这里编辑ES|QL可视化。 点击右上角选项按钮(esql icon options)并 选择编辑ESQL可视化以打开内联编辑器。

esql dashboard panel edit visualization

创建一个充实策略

edit

ES|QL ENRICH 命令使您能够 丰富 您的查询数据集与另一个数据集的字段。在使用 ENRICH 之前,您需要 创建并执行一个丰富策略。如果存在策略,它将由自动完成建议。如果没有, 点击 点击创建 来创建一个。

esql kibana enrich autocomplete

接下来,您可以输入策略名称、策略类型、源索引,以及可选的查询:

esql kibana enrich step 1

点击 下一步 以选择匹配字段和丰富字段:

esql kibana enrich step 2

最后,点击创建并执行

现在,您可以在 ES|QL 查询中使用 enrich 策略:

FROM kibana_sample_data_logs
| STATS total_bytes = SUM(bytes) BY geo.dest
| SORT total_bytes DESC
| LIMIT 3
| ENRICH countries

创建一个告警规则

edit

您可以使用ES|QL查询来创建警报。从Discover中,点击警报并选择创建搜索阈值规则。这将打开一个面板,使您能够使用ES|QL查询创建规则。接下来,您可以测试查询,添加连接器,并保存规则。

esql kibana create rule

限制

edit
  • 当Discover处于ES|QL模式时,过滤数据的界面未启用。要过滤数据,请编写一个使用WHERE命令的查询。
  • Discover最多显示10,000行。此限制仅适用于查询检索并在Discover中显示的行数。查询和聚合在完整数据集上运行。
  • Discover最多显示50列。如果查询返回超过50列,Discover仅显示前50列。
  • 从Discover导出的CSV最多显示10,000行。此限制仅适用于查询检索并在Discover中显示的行数。查询和聚合在完整数据集上运行。
  • 一次查询许多索引而不使用任何过滤器可能会导致kibana出现错误,错误信息类似于[esql] > Unexpected error from Elasticsearch: The content length (536885793) is bigger than the maximum allowed string (536870888)。ES|QL的响应太长。使用DROPKEEP来限制返回的字段数量。

在 Elastic Security 中使用 ES|QL

edit

您可以在 Elastic Security 中使用 ES|QL 来调查时间线中的事件并创建检测规则。使用 Elastic AI 助手来构建 ES|QL 查询,或回答有关 ES|QL 查询语言的问题。

使用 ES|QL 调查时间线中的事件

edit

您可以在时间线中使用 ES|QL 来过滤、转换和分析存储在 Elasticsearch 中的事件数据。要开始使用 ES|QL,请打开 ES|QL 选项卡。要了解更多信息,请参阅 在时间线中调查事件

使用 ES|QL 创建检测规则

edit

使用 ES|QL 规则类型,通过 ES|QL 查询创建检测规则。ES|QL 规则类型支持聚合和非聚合查询。要了解更多信息,请参阅 创建 ES|QL 规则

Elastic AI 助手

edit

使用 Elastic AI 助手构建 ES|QL 查询,或回答有关 ES|QL 查询语言的问题。要了解更多信息,请参阅 AI 助手

为了使AI助手能够回答有关ES|QL的问题并编写ES|QL查询,您需要 启用知识库

使用 ES|QL 查询多个索引

edit

使用 ES|QL,您可以在多个索引、数据流或别名上执行单个查询。 为此,请使用通配符和日期算术。以下示例使用逗号分隔的列表和通配符:

FROM employees-00001,other-employees-*

使用格式 :查询远程集群上的数据流和索引

FROM cluster_one:employees-00001,cluster_two:other-employees-*

字段类型不匹配

edit

在查询多个索引、数据流或别名时,您可能会发现同一个字段被映射到多个不同的类型。 例如,考虑以下两个索引及其字段映射:

索引: events_ip

{
  "mappings": {
    "properties": {
      "@timestamp":     { "type": "date" },
      "client_ip":      { "type": "ip" },
      "event_duration": { "type": "long" },
      "message":        { "type": "keyword" }
    }
  }
}

索引: events_keyword

{
  "mappings": {
    "properties": {
      "@timestamp":     { "type": "date" },
      "client_ip":      { "type": "keyword" },
      "event_duration": { "type": "long" },
      "message":        { "type": "keyword" }
    }
  }
}

当你使用类似 FROM events_ip 的简单查询分别查询这些内容时,结果会以特定类型的列提供:

FROM events_ip
| SORT @timestamp DESC
@timestamp:date client_ip:ip event_duration:long message:keyword

2023-10-23T13:55:01.543Z

172.21.3.15

1756467

已连接到 10.1.0.1

2023年10月23日 13:53:55.832Z

172.21.3.15

5033755

连接错误

2023年10月23日 13:52:55.015Z

172.21.3.15

8268153

连接错误

注意client_ip列是如何被正确识别为ip类型的,并且所有值都被显示出来。 然而,如果查询从两个冲突的索引中获取数据,例如FROM events_*,则无法确定client_ip列的类型, 并且会报告为unsupported,所有值都返回为null

FROM events_*
| SORT @timestamp DESC
@timestamp:date client_ip:unsupported event_duration:long message:keyword

2023年10月23日 13:55:01.543Z

1756467

已连接到 10.1.0.1

2023年10月23日 13:53:55.832Z

5033755

连接错误

2023年10月23日 13:52:55.015Z

8268153

连接错误

2023-10-23T13:51:54.732Z

725448

连接错误

2023年10月23日 13:33:34.937Z

1232382

已断开

2023年10月23日 12:27:28.948Z

2764889

已连接到 10.1.0.2

2023年10月23日 12:15:03.360Z

3450233

已连接到 10.1.0.3

此外,如果查询直接引用这个不支持的字段,查询将失败:

FROM events_*
| SORT client_ip DESC
Cannot use field [client_ip] due to ambiguities being mapped as
[2] incompatible types:
    [ip] in [events_ip],
    [keyword] in [events_keyword]

联合类型

edit

此功能处于技术预览阶段,可能会在未来的版本中进行更改或移除。Elastic 将努力修复任何问题,但技术预览版中的功能不受官方 GA 功能支持 SLA 的约束。

ES|QL 有一种处理 字段类型不匹配 的方法。当同一个字段在多个索引中映射为多种类型时,该字段的类型被理解为索引映射中各种类型的 联合。如前面的示例所示,这种 联合类型 不能在结果中使用,也不能被查询引用——除了在 KEEPDROP 中使用,或者当它传递给接受 联合 中所有类型并将其转换为单一类型的类型转换函数时。ES|QL 提供了一套 类型转换函数 来实现这一点。

在上面的示例中,查询可以使用类似 EVAL client_ip = TO_IP(client_ip) 的命令来解析 ipkeyword 的并集为仅 ip。 您还可以使用类型转换语法 EVAL client_ip = client_ip::IP。 或者,查询可以使用 TO_STRING 将所有支持的类型转换为 KEYWORD

例如,返回带有null值的client_ip:unsupported查询可以通过使用TO_IP函数或等效的field::ip语法来改进。 这些更改也解决了错误消息。 只要对原始字段的唯一引用是将其传递给一个解决类型模糊的转换函数,就不会产生错误。

FROM events_*
| EVAL client_ip = TO_IP(client_ip)
| KEEP @timestamp, client_ip, event_duration, message
| SORT @timestamp DESC
@timestamp:date client_ip:ip event_duration:long message:keyword

2023-10-23T13:55:01.543Z

172.21.3.15

1756467

已连接到 10.1.0.1

2023年10月23日 13:53:55.832Z

172.21.3.15

5033755

连接错误

2023年10月23日 13:52:55.015Z

172.21.3.15

8268153

连接错误

2023-10-23T13:51:54.732Z

172.21.3.15

725448

连接错误

2023-10-23T13:33:34.937Z

172.21.0.5

1232382

已断开

2023-10-23T12:27:28.948Z

172.21.2.113

2764889

已连接到 10.1.0.2

2023年10月23日 12:15:03.360Z

172.21.2.162

3450233

已连接到 10.1.0.3

索引元数据

edit

了解每行数据来源的特定索引可能会有所帮助。 要获取此信息,请在FROM命令中使用METADATA选项。

FROM events_* METADATA _index
| EVAL client_ip = TO_IP(client_ip)
| KEEP _index, @timestamp, client_ip, event_duration, message
| SORT @timestamp DESC
_index:keyword @timestamp:date client_ip:ip event_duration:long message:keyword

事件_IP

2023年10月23日 13:55:01.543Z

172.21.3.15

1756467

已连接到 10.1.0.1

事件_IP

2023年10月23日 13:53:55.832Z

172.21.3.15

5033755

连接错误

事件_IP

2023年10月23日 13:52:55.015Z

172.21.3.15

8268153

连接错误

事件关键词

2023-10-23T13:51:54.732Z

172.21.3.15

725448

连接错误

事件关键词

2023-10-23T13:33:34.937Z

172.21.0.5

1232382

已断开

事件关键词

2023年10月23日 12:27:28.948Z

172.21.2.113

2764889

已连接到 10.1.0.2

事件关键词

2023年10月23日 12:15:03.360Z

172.21.2.162

3450233

已连接到 10.1.0.3

跨集群使用ES|QL

edit

ES|QL 的跨集群搜索处于技术预览阶段,可能会在未来的版本中进行更改或移除。Elastic 将努力修复任何问题,但技术预览阶段的功能不受官方 GA 功能支持 SLA 的约束。

对于在8.16或更高版本上使用ES|QL的跨集群搜索,远程集群也必须是在8.16或更高版本上。

使用 ES|QL,您可以在多个集群上执行单个查询。

先决条件

edit
  • 跨集群搜索需要远程集群。要在 Elasticsearch Service 上设置远程集群,请参阅 在 Elasticsearch Service 上配置远程集群。如果您在自己的硬件上运行 Elasticsearch,请参阅 远程集群

    要确保您的远程集群配置支持跨集群搜索,请参阅 支持的跨集群搜索配置

  • 为了实现完整的跨集群搜索功能,本地和远程集群必须在相同的 订阅级别
  • 本地协调节点必须具有 remote_cluster_client 节点角色。
  • 如果你使用嗅探模式,本地协调节点必须能够连接到远程集群的种子节点和网关节点。

    我们建议使用能够作为协调节点的网关节点。种子节点可以是这些网关节点的一个子集。

  • 如果你使用 代理模式,本地协调节点必须能够连接到配置的 proxy_address。该地址的代理必须能够将连接路由到远程集群的网关节点和协调节点。
  • 跨集群搜索需要在本地集群和远程集群上配置不同的安全权限。请参阅 为跨集群搜索配置权限远程集群

安全模型

edit

Elasticsearch 支持两种跨集群搜索(CCS)的安全模型:

要检查正在使用哪种安全模型来连接您的集群,请运行 GET _remote/info。 如果您使用的是API密钥认证方法,您将在响应中看到 "cluster_credentials" 键。

TLS证书认证
edit

TLS证书认证通过相互TLS保护远程集群。 当单个管理员完全控制两个集群时,这可能是首选模式。 我们通常建议两个集群中的角色及其权限应保持一致。

请参阅TLS证书认证以获取先决条件和详细的设置说明。

API密钥认证
edit

以下信息涉及在使用基于API密钥的安全模型的情况下跨集群使用ES|QL。您需要按照该页面上的步骤进行完整的设置说明。本页面仅包含与ES|QL相关的附加信息。

基于API密钥的跨集群搜索(CCS)提供了更细粒度的控制,用于管理集群之间的允许操作。 当你有不同的管理员管理不同的集群,并且希望更严格地控制谁可以访问哪些数据时,这种模式可能是首选。在此模式下,集群管理员必须明确地定义授予集群和用户的访问权限。

你需要:

在使用基于API密钥的安全模型时,使用ES|QL需要一些额外的权限,这些权限在使用传统的基于查询DSL的搜索时可能不需要。 以下示例API调用创建了一个角色,该角色在使用基于API密钥的安全模型时可以使用ES|QL查询远程索引。 最终的权限remote_cluster是允许远程丰富操作所必需的。

POST /_security/role/remote1
{
  "cluster": ["cross_cluster_search"], 
  "indices": [
    {
      "names" : [""], 
      "privileges": ["read"]
    }
  ],
  "remote_indices": [ 
    {
      "names": [ "logs-*" ],
      "privileges": [ "read","read_cross_cluster" ], 
      "clusters" : ["my_remote_cluster"] 
    }
  ],
   "remote_cluster": [ 
        {
            "privileges": [
                "monitor_enrich"
            ],
            "clusters": [
                "my_remote_cluster"
            ]
        }
    ]
}

本地集群需要cross_cluster_search集群权限。

通常,用户将有权限读取本地和远程索引。然而,对于仅限于搜索远程集群的角色,仍然需要对本地集群的权限。为了提供对本地集群的读取访问权限,但不允许读取本地集群中的任何索引,名称字段可以是一个空字符串。

允许对远程集群进行读访问的索引。配置的 跨集群API密钥也必须允许读取此索引。

在使用基于API密钥的安全模型跨集群使用ES|QL时,始终需要read_cross_cluster权限。

这些权限适用的远程集群。 这个远程集群必须配置一个跨集群API密钥 并且在查询远程索引之前连接到远程集群。 使用远程集群信息 API验证连接。

需要允许远程富集。没有这个,用户无法从远程集群的 .enrich 索引中读取数据。remote_cluster 安全权限在版本 8.15.0 中引入。

然后,您需要一个具有上述权限的用户或API密钥。以下示例API调用创建一个具有remote1角色的用户。

POST /_security/user/remote_user
{
  "password" : "<PASSWORD>",
  "roles" : [ "remote1" ]
}

请记住,本地集群发出的所有跨集群请求都受跨集群API密钥权限的限制,这些权限由远程集群的管理员控制。

在8.15.0之前的版本中创建的跨集群API密钥需要替换或更新,以添加使用ENRICH进行ES|QL所需的新权限。

远程集群设置

edit

一旦安全模型配置完成,您可以添加远程集群。

以下集群更新设置 API 请求添加了三个远程集群:cluster_onecluster_twocluster_three

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_one": {
          "seeds": [
            "35.238.149.1:9300"
          ],
          "skip_unavailable": true
        },
        "cluster_two": {
          "seeds": [
            "35.238.149.2:9300"
          ],
          "skip_unavailable": false
        },
        "cluster_three": {  
          "seeds": [
            "35.238.149.3:9300"
          ]
        }
      }
    }
  }
}

由于未在cluster_three上设置skip_unavailable,它使用默认值false。详情请参阅可选的远程集群部分。

跨多个集群查询

edit

FROM 命令中,使用格式 : 指定远程集群上的数据流和索引。例如,以下 ES|QL 请求查询名为 cluster_one 的单个远程集群上的 my-index-000001 索引:

FROM cluster_one:my-index-000001
| LIMIT 10

同样地,这个 ES|QL 请求从三个集群中查询 my-index-000001 索引:

  • 本地(查询)集群
  • 两个远程集群,cluster_onecluster_two
FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001
| LIMIT 10

同样,此 ES|QL 请求从所有远程集群(cluster_onecluster_twocluster_three)查询 my-index-000001 索引:

FROM *:my-index-000001
| LIMIT 10

跨集群元数据

edit

使用 "include_ccs_metadata": true 选项,用户可以请求 ES|QL 跨集群搜索响应包含每个集群上的搜索元数据(当响应格式为 JSON 时)。 这里我们展示了一个使用异步搜索端点的示例。当请求时,跨集群搜索元数据也存在于同步搜索端点响应中。

POST /_query/async?format=json
{
  "query": """
    FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index*
    | STATS COUNT(http.response.status_code) BY user.id
    | LIMIT 2
  """,
  "include_ccs_metadata": true
}

返回结果:

{
  "is_running": false,
  "took": 42,  
  "columns" : [
    {
      "name" : "COUNT(http.response.status_code)",
      "type" : "long"
    },
    {
      "name" : "user.id",
      "type" : "keyword"
    }
  ],
  "values" : [
    [4, "elkbee"],
    [1, "kimchy"]
  ],
  "_clusters": {  
    "total": 3,
    "successful": 3,
    "running": 0,
    "skipped": 0,
    "partial": 0,
    "failed": 0,
    "details": { 
      "(local)": { 
        "status": "successful",
        "indices": "blogs",
        "took": 41,  
        "_shards": { 
          "total": 13,
          "successful": 13,
          "skipped": 0,
          "failed": 0
        }
      },
      "cluster_one": {
        "status": "successful",
        "indices": "cluster_one:my-index-000001",
        "took": 38,
        "_shards": {
          "total": 4,
          "successful": 4,
          "skipped": 0,
          "failed": 0
        }
      },
      "cluster_two": {
        "status": "successful",
        "indices": "cluster_two:my-index*",
        "took": 40,
        "_shards": {
          "total": 18,
          "successful": 18,
          "skipped": 1,
          "failed": 0
        }
      }
    }
  }
}

整个搜索(跨所有集群)花费的时间,以毫秒为单位。

此部分的计数器显示所有可能的集群搜索状态以及当前处于该状态的集群搜索数量。集群可以具有以下状态之一:运行中成功(所有分片上的搜索都成功)、跳过(在标记为skip_unavailable=true的集群上搜索失败)或失败(在标记为skip_unavailable=false的集群上搜索失败)。

The _clusters/details 部分显示了每个集群上搜索的元数据。

如果你在跨集群搜索中包含了从你发送请求的本地集群中的索引,它将被标识为“(本地)”。

搜索在每个集群上花费的时间(以毫秒为单位)。这有助于确定哪些集群的响应时间比其他集群慢。

该集群搜索的分片详情,包括由于can-match阶段结果而被跳过的分片数量。当分片不可能包含任何匹配的数据时,它们会被跳过,因此不会包含在完整的ES|QL查询中。

跨集群元数据可以用来确定是否有数据从集群返回。例如,在下面的查询中,通配符表达式cluster-two没有解析到具体的索引(或索引集)。因此,该集群被标记为跳过,并且搜索的分片总数设置为零。

POST /_query/async?format=json
{
  "query": """
    FROM cluster_one:my-index*,cluster_two:logs*
    | STATS COUNT(http.response.status_code) BY user.id
    | LIMIT 2
  """,
  "include_ccs_metadata": true
}

返回结果:

{
  "is_running": false,
  "took": 55,
  "columns": [
     ... // not shown
  ],
  "values": [
     ... // not shown
  ],
  "_clusters": {
    "total": 2,
    "successful": 2,
    "running": 0,
    "skipped": 0,
    "partial": 0,
    "failed": 0,
    "details": {
      "cluster_one": {
        "status": "successful",
        "indices": "cluster_one:my-index*",
        "took": 38,
        "_shards": {
          "total": 4,
          "successful": 4,
          "skipped": 0,
          "failed": 0
        }
      },
      "cluster_two": {
        "status": "skipped", 
        "indices": "cluster_two:logs*",
        "took": 0,
        "_shards": {
          "total": 0, 
          "successful": 0,
          "skipped": 0,
          "failed": 0
        }
      }
    }
  }
}

此集群被标记为已跳过,因为该集群上没有匹配的索引。

表示没有分片被搜索(由于没有任何匹配的索引)。

跨集群丰富

edit

在集群间丰富ES|QL的操作与本地丰富类似。如果丰富策略及其丰富索引在所有集群中一致,只需像没有远程集群那样编写丰富命令。在这种默认模式下,ES|QL可以在本地集群或远程集群上执行丰富命令,旨在最小化计算或集群间数据传输。确保策略在本地集群和远程集群上存在且数据一致对于ES|QL生成一致的查询结果至关重要。

在版本8.15.0中引入了基于API密钥安全模型的跨集群ES|QL增强功能。 在8.15.0之前的版本中创建的跨集群API密钥需要替换或更新以使用新的必需权限。 请参阅API密钥认证部分中的示例。

在以下示例中,可以在本地集群或远程集群cluster_one上执行hosts策略。

FROM my-index-000001,cluster_one:my-index-000001
| ENRICH hosts ON ip
| LIMIT 10

仅针对远程集群的ES|QL查询也可以在本地集群上进行。这意味着下面的查询要求本地集群上也存在hosts丰富策略。

FROM cluster_one:my-index-000001,cluster_two:my-index-000001
| LIMIT 10
| ENRICH hosts ON ip
使用协调器模式进行丰富
edit

ES|QL 提供了 _coordinator 模式,以强制 ES|QL 在本地集群上执行 enrich 命令。当 enrich 策略在远程集群上不可用,或者在多个集群之间维护 enrich 索引的一致性具有挑战性时,应使用此模式。

FROM my-index-000001,cluster_one:my-index-000001
| ENRICH _coordinator:hosts ON ip
| SORT host_name
| LIMIT 10

使用_coordinator模式通常会增加集群间的数据传输和本地集群的工作负载。

使用远程模式进行丰富
edit

ES|QL 还提供了 _remote 模式,以强制 ES|QL 在每个远程集群上独立执行 enrich 命令,这些远程集群是目标索引所在的位置。 这种模式对于管理每个集群上的不同 enrich 数据非常有用,例如每个区域的主机详细信息,目标(主)索引包含来自这些主机的日志事件。

在下面的示例中,hosts 丰富策略需要在所有远程集群上存在:querying 集群(因为本地索引被包含在内),远程集群 cluster_onecluster_two

FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001
| ENRICH _remote:hosts ON ip
| SORT host_name
| LIMIT 10

stats 命令之后不能执行 _remote 的 enrich。以下示例将导致错误:

FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001
| STATS COUNT(*) BY ip
| ENRICH _remote:hosts ON ip
| SORT host_name
| LIMIT 10
多个丰富命令
edit

您可以在同一个查询中包含多个不同模式的丰富命令。ES|QL将尝试相应地执行它们。例如,此查询首先在任何集群上使用hosts策略进行丰富,然后在本地集群上使用vendors策略进行丰富。

FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001
| ENRICH hosts ON ip
| ENRICH _coordinator:vendors ON os
| LIMIT 10

一个 _remote 的 enrich 命令不能在一个 _coordinator 的 enrich 命令之后执行。以下示例将导致错误。

FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001
| ENRICH _coordinator:hosts ON ip
| ENRICH _remote:vendors ON os
| LIMIT 10

从ES|QL查询中排除集群或索引

edit

要排除整个集群,请在 FROM 命令中使用减号作为集群别名的前缀,例如:-my_cluster:*

FROM my-index-000001,cluster*:my-index-000001,-cluster_three:*
| LIMIT 10

要排除特定的远程索引,请在 FROM 命令中使用减号作为索引的前缀,例如 my_cluster:-my_index

FROM my-index-000001,cluster*:my-index-*,cluster_three:-my-index-000001
| LIMIT 10

可选的远程集群

edit

ES|QL 的跨集群搜索目前不遵循 skip_unavailable 设置。因此,如果请求中指定的远程集群不可用或失败,无论该设置如何,ES|QL 查询的跨集群搜索都将失败。

我们正在积极努力,以使ES|QL的跨集群搜索行为与其他跨集群搜索API保持一致。

升级期间的跨集群查询

edit

在本地集群进行滚动升级时,您仍然可以搜索远程集群。然而,本地协调节点的“升级自”和“升级至”版本必须与远程集群的网关节点兼容。

在同一集群中运行多个版本的Elasticsearch超过升级期间是不支持的。

有关升级的更多信息,请参阅 升级 Elasticsearch

ES|QL 任务管理

edit

您可以使用任务管理 API列出正在运行的 ES|QL 查询:

GET /_tasks?pretty&detailed&group_by=parents&human&actions=*data/read/esql

返回的状态列表如下:

{
  "node" : "2j8UKw1bRO283PMwDugNNg",
  "id" : 5326,
  "type" : "transport",
  "action" : "indices:data/read/esql",
  "description" : "FROM test | STATS MAX(d) by a, b",  
  "start_time" : "2023-07-31T15:46:32.328Z",
  "start_time_in_millis" : 1690818392328,
  "running_time" : "41.7ms",                           
  "running_time_in_nanos" : 41770830,
  "cancellable" : true,
  "cancelled" : false,
  "headers" : { }
}

用户提交的查询。

查询已运行的时间。

您可以使用此功能来查找长时间运行的查询,并在需要时使用任务取消API取消它们:

POST _tasks/2j8UKw1bRO283PMwDugNNg:5326/_cancel

停止查询可能需要几秒钟的时间。