Использование ES|QL в кластерах
Поиск по кластерам для ES|QL находится в техническом предварительном просмотре и может быть изменён или удалён в будущих выпусках. Elastic будет работать над исправлением любых проблем, но функции в техническом предварительном просмотре не подпадают под SLA поддержки официальных функций GA.
С помощью ES|QL вы можете выполнить один запрос по нескольким кластерам.
Предварительные условия
-
Для поиска по кластерам требуется удалённые кластеры. Чтобы настроить удалённые кластеры в Elasticsearch Service, см. настройка удалённых кластеров в Elasticsearch Service. Если вы используете Elasticsearch на собственном оборудовании, см. Удалённые кластеры.
Чтобы убедиться, что конфигурация вашего удалённого кластера поддерживает поиск по кластерам, см. Поддерживаемые конфигурации поиска по кластерам.
- Для полной функциональности поиска по кластерам локальный и удалённый кластеры должны быть на одном уровне подписки.
- Локальный координирующий узел должен иметь роль узла
remote_cluster_client. -
Если вы используете режим sniffer, локальный координирующий узел должен иметь возможность подключения к узлам seed и gateway удалённого кластера.
Рекомендуется использовать gateway-узлы, способные работать в качестве координирующих узлов. Узлы seed могут быть подмножеством этих gateway-узлов.
- Если вы используете режим прокси, локальный координирующий узел должен иметь возможность подключения к настроенному
proxy_address. Прокси по этому адресу должен иметь возможность маршрутизации подключений к gateway- и координирующим узлам удалённого кластера. - Поиск по кластерам требует различных прав доступа в локальном и удалённом кластерах. См. Настройка прав для поиска по кластерам и Удалённые кластеры.
Модель безопасности
Elasticsearch поддерживает две модели безопасности для поиска по кластерам (CCS):
Чтобы проверить, какая модель безопасности используется для подключения ваших кластеров, выполните GET _remote/info. Если вы используете метод аутентификации с API-ключами, вы увидите ключ "cluster_credentials" в ответе.
TLS-аутентификация с сертификатами
TLS-аутентификация с сертификатами обеспечивает безопасность удалённых кластеров с взаимной TLS-аутентификацией. Это может быть предпочтительной моделью, когда один администратор имеет полный контроль над обоими кластерами. В общем, рекомендуется, чтобы роли и их права были идентичны в обоих кластерах.
См. TLS-аутентификацию с сертификатами для предварительных условий и подробных инструкций по настройке.
Аутентификация с API-ключами
Следующая информация относится к использованию ES|QL между кластерами с помощью модели безопасности на основе API-ключей. Вам нужно будет следовать инструкциям на этой странице для полных инструкций по настройке. Эта страница содержит только дополнительную информацию, специфичную для ES|QL.
Поиск по кластерам на основе API-ключей (CCS) обеспечивает более точный контроль над разрешенными действиями между кластерами. Это может быть предпочтительной моделью, когда у вас разные администраторы для разных кластеров и вы хотите иметь больший контроль над тем, кто может получить доступ к каким данным. В этой модели администраторы кластера должны явно определить доступ, предоставляемый кластерам и пользователям.
Вам нужно будет:
- Создать API-ключ на удаленном кластере с помощью API создания API-ключа для поиска по кластерам или с помощью пользовательского интерфейса API-ключей Kibana .
- Добавить API-ключ в хранилище ключей на локальном кластере в рамках шагов в настройке локального кластера. Все запросы по кластерам с локального кластера привязаны к правам API-ключа.
Использование ES|QL с моделью безопасности на основе API-ключа требует дополнительных разрешений, которые могут не потребоваться при использовании традиционного поиска на основе запроса DSL. Следующий пример API-вызова создаёт роль, которая может выполнять запросы к удалённым индексам с помощью ES|QL при использовании модели безопасности на основе API-ключей. Окончательное разрешение, remote_cluster, необходимо для разрешения удалённых операций обогащения.
resp = client.security.put_role(
name="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"
]
}
],
)
print(resp) const response = await client.security.putRole({
name: "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"],
},
],
});
console.log(response); 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"
]
}
]
} | Разрешение кластера | |
| Обычно пользователи имеют разрешения на чтение как локальных, так и удалённых индексов. Однако в случаях, когда роль предназначена ТОЛЬКО для поиска в удалённом кластере, разрешение | |
| Индексы, которым разрешен доступ к чтению в удалённом кластере. Настроенный API-ключ для поиска по кластерам также должен разрешить чтение этого индекса. | |
| Разрешение | |
| Удалённые кластеры, к которым применяются эти права. Этот удалённый кластер должен быть настроен с API-ключом для поиска по кластерам и подключён к удалённому кластеру, прежде чем можно будет выполнить запрос к удалённому индексу. Проверьте подключение с помощью API информации об удалённом кластере. | |
| Требуется для разрешения удалённого обогащения. Без этого пользователь не может читать из индексов |
Затем вам потребуется пользователь или API-ключ с разрешениями, созданными выше. Следующий пример API-вызова создаёт пользователя с ролью remote1.
resp = client.security.put_user(
username="remote_user",
password="<PASSWORD>",
roles=[
"remote1"
],
)
print(resp) const response = await client.security.putUser({
username: "remote_user",
password: "<PASSWORD>",
roles: ["remote1"],
});
console.log(response); POST /_security/user/remote_user
{
"password" : "<PASSWORD>",
"roles" : [ "remote1" ]
} Помните, что все запросы по кластерам с локального кластера ограничены правами API-ключа для поиска по кластерам, которые контролируются администратором удалённого кластера.
API-ключи для поиска по кластерам, созданные в версиях до 8.15.0, необходимо заменить или обновить, чтобы добавить новые разрешения, необходимые для ES|QL с обогащением (ENRICH).
Настройка удалённого кластера
После настройки модели безопасности вы можете добавить удалённые кластеры.
Следующий запрос API настроек кластера добавляет три удалённых кластера: cluster_one, cluster_two и cluster_three.
resp = client.cluster.put_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"
]
}
}
}
},
)
print(resp) response = client.cluster.put_settings(
body: {
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'
]
}
}
}
}
}
)
puts response const response = await client.cluster.putSettings({
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"],
},
},
},
},
});
console.log(response); 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"
]
}
}
}
}
} | Поскольку |
Запрос по нескольким кластерам
В команде FROM укажите потоки данных и индексы на удалённых кластерах в формате <remote_cluster_name>:<target>. Например, следующий запрос ES|QL выполняет запрос к индексу my-index-000001 на одном удалённом кластере с именем cluster_one:
FROM cluster_one:my-index-000001 | LIMIT 10
Аналогично, этот запрос ES|QL выполняет запрос к индексу my-index-000001 из трёх кластеров:
- Локальный ("запрашивающий") кластер
- Два удалённых кластера,
cluster_oneиcluster_two
FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001 | LIMIT 10
Также запрос ES|QL обращается к индексу my-index-000001 на всех удаленных кластерах (cluster_one, cluster_two и cluster_three):
FROM *:my-index-000001 | LIMIT 10
Метаданные между кластерами
Используя опцию "include_ccs_metadata": true, пользователи могут запросить, чтобы ответы ES|QL на межкластерный поиск включали метаданные о поиске на каждом кластере (когда формат ответа — JSON). Здесь показан пример с использованием асинхронного конечного пункта поиска. Метаданные межкластерного поиска также присутствуют в ответе синхронного конечного пункта поиска при запросе.
resp = client.esql.async_query(
format="json",
query="\n FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index*\n | STATS COUNT(http.response.status_code) BY user.id\n | LIMIT 2\n ",
include_ccs_metadata=True,
)
print(resp) const response = await client.transport.request({
method: "POST",
path: "/_query/async",
querystring: {
format: "json",
},
body: {
query:
"\n FROM my-index-000001,cluster_one:my-index-000001,cluster_two:my-index*\n | STATS COUNT(http.response.status_code) BY user.id\n | LIMIT 2\n ",
include_ccs_metadata: true,
},
});
console.log(response); 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
}
}
}
}
} | Сколько времени занял весь поиск (по всем кластерам) в миллисекундах. | |
| Этот раздел счётчиков отображает все возможные состояния поиска по кластерам и сколько поисков по кластерам в настоящее время находятся в этом состоянии. Кластеры могут иметь одно из следующих состояний: running, successful (поиски по всем фрагментам были успешными), skipped (поиск завершился неудачно на кластере, помеченном | |
| Раздел | |
| Если вы включили индексы локального кластера, к которому вы направили запрос, в свой межкластерный поиск, он идентифицируется как "(local)". | |
| Сколько времени (в миллисекундах) занял поиск на каждом кластере. Это может быть полезно для определения кластеров, которые имеют более медленные время отклика, чем другие. | |
| Подробности фрагмента для поиска на этом кластере, включая количество фрагментов, которые были пропущены из-за результатов фазы can-match. Фрагменты пропускаются, когда они не могут иметь каких-либо соответствующих данных и поэтому не включены в полный запрос ES|QL. |
Метаданные межкластерного поиска могут использоваться для определения, возвращались ли какие-либо данные с кластера. Например, в запросе ниже, выражение подстановки для cluster-two не разрешилось до конкретного индекса (или индексов). Поэтому кластер помечен как skipped, а общее количество обработанных фрагментов установлено в ноль.
resp = client.esql.async_query(
format="json",
query="\n FROM cluster_one:my-index*,cluster_two:logs*\n | STATS COUNT(http.response.status_code) BY user.id\n | LIMIT 2\n ",
include_ccs_metadata=True,
)
print(resp) const response = await client.transport.request({
method: "POST",
path: "/_query/async",
querystring: {
format: "json",
},
body: {
query:
"\n FROM cluster_one:my-index*,cluster_two:logs*\n | STATS COUNT(http.response.status_code) BY user.id\n | LIMIT 2\n ",
include_ccs_metadata: true,
},
});
console.log(response); 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
}
}
}
}
} | Этот кластер помечен как skipped, так как на этом кластере не было соответствующих индексов. | |
| Указывает, что фрагменты не обрабатывались (из-за отсутствия соответствующих индексов). |
Обогащение между кластерами
Обогащение в ES|QL между кластерами работает аналогично локальному обогащению. Если политика обогащения и её индексы обогащения одинаковы на всех кластерах, просто запишите команду обогащения так же, как и без удалённых кластеров. В этом режиме по умолчанию ES|QL может выполнить команду обогащения на локальном кластере или на удалённых кластерах, стремясь свести к минимуму вычисления или передачу данных между кластерами. Обеспечение существования политики с согласованными данными как на локальном, так и на удалённых кластерах имеет решающее значение для ES|QL для получения согласованного результата запроса.
Обогащение в ES|QL между кластерами с использованием модели безопасности на основе API-ключа было добавлено в версии 8.15.0. Ключи API межкластерного доступа, созданные в версиях до 8.15.0, необходимо заменить или обновить, чтобы использовать новые необходимые разрешения. Обратитесь к примеру в разделе авторизация с помощью API-ключа.
В следующем примере политика обогащения с hosts может быть выполнена на локальном кластере или на удалённом кластере cluster_one.
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
Обогащение в режиме координатора
ES|QL предоставляет режим обогащения _coordinator, чтобы принудительно заставить ES|QL выполнить команду обогащения на локальном кластере. Этот режим следует использовать, когда политика обогащения недоступна на удалённых кластерах или поддержание согласованности индексов обогащения между кластерами является сложной задачей.
FROM my-index-000001,cluster_one:my-index-000001 | ENRICH _coordinator:hosts ON ip | SORT host_name | LIMIT 10
Обогащение в режиме _coordinator обычно увеличивает передачу данных между кластерами и нагрузку на локальный кластер.
Обогащение в удалённом режиме
ES|QL также предоставляет режим обогащения _remote, чтобы принудительно заставить ES|QL выполнить команду обогащения независимо на каждом удалённом кластере, где находятся целевые индексы. Этот режим полезен для управления различными данными обогащения на каждом кластере, такими как подробная информация о хостах для каждого региона, где целевые (основные) индексы содержат события регистрации с этих хостов.
В примере ниже политика обогащения hosts должна существовать на всех удалённых кластерах: кластере querying (так как локальные индексы включены), удалённом кластере cluster_one и cluster_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
Обогащение _remote не может быть выполнено после команды stats. Следующий пример приведет к ошибке:
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
Несколько команд обогащения
Вы можете включить несколько команд обогащения в один запрос с различными режимами. 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 не может быть выполнена после команды обогащения _coordinator. Следующий пример приведёт к ошибке.
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
Чтобы исключить весь кластер, добавьте перед алиасом кластера знак минус в команде 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
Необязательные удалённые кластеры
Межкластерный поиск для ES|QL в настоящее время не учитывает настройку skip_unavailable. В результате, если удалённый кластер, указанный в запросе, недоступен или вышел из строя, межкластерный поиск для ES|QL-запросов завершится неудачно независимо от настройки.
Мы активно работаем над согласованием поведения межкластерного поиска для ES|QL с другими API межкластерного поиска.
Поиск между кластерами во время обновления
Вы по-прежнему можете искать на удалённом кластере во время выполнения поэтапного обновления на локальном кластере. Однако версия локального координирующего узла «с версии» и «до версии» должна быть совместима с версией узла шлюза удалённого кластера.
Запуск нескольких версий Elasticsearch в одном кластере за пределами периода обновления не поддерживается.
Дополнительную информацию об обновлениях см. на странице Обновление Elasticsearch.
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/esql-cross-clusters.html