Добавление удаленных кластеров с аутентификацией по API-ключам
Авторизация с помощью ключа API позволяет локальному кластеру аутентифицироваться с удаленным кластером через ключ API межкластерного доступа. Ключ API должен быть создан администратором удаленного кластера. Локальный кластер настроен на предоставление этого ключа API при каждом запросе к удаленному кластеру. Удаленный кластер проверяет ключ API и предоставляет доступ, основываясь на привилегиях ключа API.
Все межкластерные запросы с локального кластера ограничены привилегиями ключа API, независимо от локальных пользователей, связанных с этими запросами. Например, если ключ API разрешает только чтение доступа к my-index на удаленном кластере, даже суперпользователь с локального кластера ограничен этим ограничением. Данный механизм позволяет администратору удаленного кластера полностью контролировать, кто может получить доступ к каким данным при межкластерном поиске и/или межкластерной репликации. Администратор удаленного кластера уверен, что доступ невозможен за пределами того, что явно назначено ключу API.
На стороне локального кластера не каждый локальный пользователь нуждается в доступе ко всем данным, разрешенным ключом API. Администратор локального кластера может дополнительно настроить дополнительные ограничения доступа для локальных пользователей, чтобы каждый пользователь получал доступ только к необходимым удаленным данным. Обратите внимание, что можно только уменьшить разрешения, предоставленные ключом API, для отдельных локальных пользователей. Невозможно увеличить разрешения, выходящие за рамки разрешений, предоставленных ключом API.
В этой модели межкластерные операции используют специальный порт сервера (интерфейс удаленного кластера) для связи между кластерами. Удаленный кластер должен разрешить этот порт для подключения локальных кластеров. Для максимальной безопасности настройте Transport Layer Security (TLS) для этого порта (как описано в Установление доверия с удаленным кластером).
Локальный кластер должен доверять удаленному кластеру на интерфейсе удаленного кластера. Это означает, что локальный кластер доверяет центру сертификации (CA) удаленного кластера, который подписывает сертификат сервера, используемый интерфейсом удаленного кластера. При установлении соединения все узлы локального кластера, участвующие в межкластерном взаимодействии, проверяют сертификаты узлов с другой стороны, на основе настроек доверия TLS.
Для добавления удаленного кластера с помощью аутентификации по ключу API:
Если возникнут проблемы, обратитесь к разделу Устранение неполадок.
Предварительные условия
- Функции безопасности Elasticsearch должны быть включены в обоих кластерах на каждом узле. Безопасность включена по умолчанию. Если она отключена, установите
xpack.security.enabledнаtrueвelasticsearch.yml. Обратитесь к общим настройкам безопасности. - Узлы локального и удаленного кластеров должны быть версии 8.10 или выше.
- Локальный и удаленный кластеры должны иметь соответствующую лицензию. Дополнительную информацию см. в https://www.elastic.co/subscriptions.
Установление доверия с удаленным кластером
Если удаленный кластер является частью развертывания Elasticsearch Service, у него по умолчанию есть действительный сертификат. Поэтому вы можете пропустить шаги, связанные с сертификатами, в этих инструкциях.
На удаленном кластере
-
Включите сервер удаленного кластера на каждом узле удаленного кластера. В
elasticsearch.yml:- Установите
remote_cluster_server.enabledнаtrue. - Настройте адрес привязки и публикации для трафика сервера удаленного кластера, например, используя
remote_cluster.host. Без настройки адреса, трафик удаленного кластера может быть привязан к локальному интерфейсу, и удаленные кластеры, работающие на других машинах, не смогут подключиться. - Дополнительно настройте порт удаленного сервера, используя
remote_cluster.port(по умолчанию9443).
- Установите
-
Далее, сгенерируйте центр сертификации (CA) и пару сертификат/ключ сервера. На одном из узлов удаленного кластера, в директории, где установлен Elasticsearch:
-
Создайте CA, если у вас его еще нет:
./bin/elasticsearch-certutil ca --pem --out=cross-cluster-ca.zip --pass CA_PASSWORD
Замените
CA_PASSWORDна желаемый пароль для CA. Вы можете удалить опцию--passи ее аргумент, если вы не развертываете на производстве. -
Разархивируйте сгенерированный файл
cross-cluster-ca.zip. Этот сжатый файл содержит следующее содержимое:/ca |_ ca.crt |_ ca.key
-
Сгенерируйте пару сертификата и закрытого ключа для узлов удаленного кластера:
./bin/elasticsearch-certutil cert --out=cross-cluster.p12 --pass=CERT_PASSWORD --ca-cert=ca/ca.crt --ca-key=ca/ca.key --ca-pass=CA_PASSWORD --dns=example.com --ip=127.0.0.1
- Замените
CA_PASSWORDна пароль CA из предыдущего шага. - Замените
CERT_PASSWORDна желаемый пароль для сгенерированного закрытого ключа. - Используйте опцию
--dnsдля указания соответствующего имени DNS для сертификата. Вы можете указать его несколько раз для нескольких DNS. - Используйте опцию
--ipдля указания соответствующего IP-адреса для сертификата. Вы можете указать его несколько раз для нескольких IP-адресов.
- Замените
-
Если удаленный кластер имеет несколько узлов, вы можете либо:
- создать один универсальный сертификат для всех узлов;
- или, создать отдельные сертификаты для каждого узла, либо вручную, либо в пакетном режиме с использованием бесшумного режима.
-
-
На каждом узле удаленного кластера:
- Скопируйте файл
cross-cluster.p12из предыдущего шага в директориюconfig. Если вы не создавали универсальный сертификат, убедитесь, что вы копируете правильный узел-специфичный файл p12. -
Добавьте следующую конфигурацию в
elasticsearch.yml:xpack.security.remote_cluster_server.ssl.enabled: true xpack.security.remote_cluster_server.ssl.keystore.path: cross-cluster.p12
-
Добавьте пароль хранилища SSL в хранилище ключей Elasticsearch:
./bin/elasticsearch-keystore add xpack.security.remote_cluster_server.ssl.keystore.secure_password
При запросе введите
CERT_PASSWORDиз предыдущего шага.
- Скопируйте файл
- Перезапустите удаленный кластер.
- На удаленном кластере сгенерируйте ключ API межкластерного доступа, предоставляющий доступ к индексам, которые вы хотите использовать для межкластерного поиска или межкластерной репликации. Вы можете использовать API для создания ключа API межкластерного доступа или Kibana.
- Скопируйте закодированный ключ (
encodedв ответе) в безопасное место. Вам понадобится он для подключения к удаленному кластеру позже.
На локальном кластере
-
На каждом узле локального кластера:
- Скопируйте файл
ca.crt, сгенерированный на удаленном кластере ранее, в директориюconfig, переименовав файлremote-cluster-ca.crt. -
Добавьте следующую конфигурацию в
elasticsearch.yml:xpack.security.remote_cluster_client.ssl.enabled: true xpack.security.remote_cluster_client.ssl.certificate_authorities: [ "remote-cluster-ca.crt" ]
-
Добавьте ключ API межкластерного доступа, созданный на удаленном кластере ранее, в хранилище ключей:
./bin/elasticsearch-keystore add cluster.remote.ALIAS.credentials
Замените
ALIASтем же именем, которое вы будете использовать для создания записи удаленного кластера позже. При запросе введите закодированный ключ API межкластерного доступа, созданный на удаленном кластере ранее.
- Скопируйте файл
- Перезапустите локальный кластер для загрузки изменений в хранилище ключей и настроек.
Примечание: Если вы настраиваете только ключ API межкластерного доступа, вы можете вызвать API перезагрузки настроек безопасности узлов вместо перезапуска кластера. Настройка настроек remote_cluster_client в elasticsearch.yml все равно требует перезапуска.
Подключение к удалённому кластеру
Для подключения к удалённым кластерам необходимо иметь привилегию manage кластера.
Локальный кластер использует интерфейс удалённого кластера для установления связи с удалёнными кластерами. Координирующие узлы в локальном кластере устанавливают долговременные TCP-соединения со специфическими узлами в удалённом кластере. Elasticsearch требует, чтобы эти соединения оставались открытыми, даже если они бездействуют в течение длительного времени.
Для добавления удалённого кластера из Stack Management в Kibana:
- Выберите Удалённые кластеры в боковом меню.
- Введите имя (псевдоним кластера) для удалённого кластера.
- Укажите URL-адрес конечной точки Elasticsearch или IP-адрес или имя хоста удалённого кластера, за которым следует порт удалённого кластера (по умолчанию
9443). Например,cluster.es.eastus2.staging.azure.foundit.no:9443или192.168.1.1:9443.
В качестве альтернативы, используйте API для обновления настроек кластера для добавления удалённого кластера. Вы также можете использовать этот API для динамической конфигурации удалённых кластеров для каждого узла в локальном кластере. Для конфигурации удалённых кластеров на отдельных узлах локального кластера определите статические настройки в elasticsearch.yml для каждого узла.
Следующий запрос добавляет удалённый кластер с псевдонимом cluster_one. Этот псевдоним кластера является уникальным идентификатором, представляющим подключение к удалённому кластеру и используется для различения локальных и удалённых индексов.
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:{remote-interface-default-port}"
]
}
}
}
},
)
print(resp) const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
cluster_one: {
seeds: ["127.0.0.1:{remote-interface-default-port}"],
},
},
},
},
});
console.log(response); PUT /_cluster/settings
{
"persistent" : {
"cluster" : {
"remote" : {
"cluster_one" : {
"seeds" : [
"127.0.0.1:9443"
]
}
}
}
}
} | Псевдоним кластера этого удалённого кластера — | |
| Указывает имя хоста и порт удалённого кластера узла-семена в удалённом кластере. |
Вы можете использовать API информации об удалённом кластере, чтобы проверить, успешно ли локальный кластер подключён к удалённому кластеру:
resp = client.cluster.remote_info() print(resp)
response = client.cluster.remote_info puts response
const response = await client.cluster.remoteInfo(); console.log(response);
GET /_remote/info
Ответ API показывает, что локальный кластер подключён к удалённому кластеру с псевдонимом кластера cluster_one:
{
"cluster_one" : {
"seeds" : [
"127.0.0.1:9443"
],
"connected" : true,
"num_nodes_connected" : 1,
"max_connections_per_cluster" : 3,
"initial_connect_timeout" : "30s",
"skip_unavailable" : true,
"cluster_credentials": "::es_redacted::",
"mode" : "sniff"
}
} | Количество узлов в удалённом кластере, к которому подключён локальный кластер. | |
| Указывает, нужно ли пропустить удалённый кластер, если выполняется поиск через межкластерный поиск, но доступные узлы отсутствуют. | |
| Если присутствует, указывает, что удалённый кластер подключился с помощью аутентификации по API-ключам. |
Динамическая конфигурация удалённых кластеров
Используйте API для обновления настроек кластера, чтобы динамически настроить удалённые параметры на каждом узле кластера. Следующий запрос добавляет три удалённых кластера: cluster_one, cluster_two и cluster_three.
Параметр seeds указывает имя хоста и порт удалённого кластера (по умолчанию 9443) узла-семени в удалённом кластере.
Параметр mode определяет конфигурированный режим подключения, который по умолчанию равен sniff. Поскольку cluster_one не указывает mode, используется значение по умолчанию. И cluster_two, и cluster_three явно используют разные режимы.
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:{remote-interface-default-port}"
]
},
"cluster_two": {
"mode": "sniff",
"seeds": [
"127.0.0.1:{remote-interface-default-port-plus1}"
],
"transport.compress": True,
"skip_unavailable": True
},
"cluster_three": {
"mode": "proxy",
"proxy_address": "127.0.0.1:{remote-interface-default-port-plus2}"
}
}
}
},
)
print(resp) const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
cluster_one: {
seeds: ["127.0.0.1:{remote-interface-default-port}"],
},
cluster_two: {
mode: "sniff",
seeds: ["127.0.0.1:{remote-interface-default-port-plus1}"],
"transport.compress": true,
skip_unavailable: true,
},
cluster_three: {
mode: "proxy",
proxy_address: "127.0.0.1:{remote-interface-default-port-plus2}",
},
},
},
},
});
console.log(response); PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9443"
]
},
"cluster_two": {
"mode": "sniff",
"seeds": [
"127.0.0.1:9444"
],
"transport.compress": true,
"skip_unavailable": true
},
"cluster_three": {
"mode": "proxy",
"proxy_address": "127.0.0.1:9445"
}
}
}
}
} Вы можете динамически обновить настройки удалённого кластера после первоначальной конфигурации. Следующий запрос обновляет настройки сжатия для cluster_two и настройки сжатия и расписания ping для cluster_three.
При изменении настроек сжатия или расписания ping все существующие соединения узлов должны закрыться и перезапуститься, что может привести к сбоям в полёте запросов.
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"cluster_two": {
"transport.compress": False
},
"cluster_three": {
"transport.compress": True,
"transport.ping_schedule": "60s"
}
}
}
},
)
print(resp) response = client.cluster.put_settings(
body: {
persistent: {
cluster: {
remote: {
cluster_two: {
'transport.compress' => false
},
cluster_three: {
'transport.compress' => true,
'transport.ping_schedule' => '60s'
}
}
}
}
}
)
puts response const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
cluster_two: {
"transport.compress": false,
},
cluster_three: {
"transport.compress": true,
"transport.ping_schedule": "60s",
},
},
},
},
});
console.log(response); PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_two": {
"transport.compress": false
},
"cluster_three": {
"transport.compress": true,
"transport.ping_schedule": "60s"
}
}
}
}
} Вы можете удалить удалённый кластер из настроек кластера, передав значения null для каждой настройки удалённого кластера. Следующий запрос удаляет cluster_two из настроек кластера, оставив cluster_one и cluster_three неизменными:
resp = client.cluster.put_settings(
persistent={
"cluster": {
"remote": {
"cluster_two": {
"mode": None,
"seeds": None,
"skip_unavailable": None,
"transport.compress": None
}
}
}
},
)
print(resp) response = client.cluster.put_settings(
body: {
persistent: {
cluster: {
remote: {
cluster_two: {
mode: nil,
seeds: nil,
skip_unavailable: nil,
'transport.compress' => nil
}
}
}
}
}
)
puts response const response = await client.cluster.putSettings({
persistent: {
cluster: {
remote: {
cluster_two: {
mode: null,
seeds: null,
skip_unavailable: null,
"transport.compress": null,
},
},
},
},
});
console.log(response); PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_two": {
"mode": null,
"seeds": null,
"skip_unavailable": null,
"transport.compress": null
}
}
}
}
} Статическая конфигурация удалённых кластеров
Если вы указываете настройки в elasticsearch.yml, только узлы с этими настройками смогут подключиться к удалённому кластеру и обрабатывать запросы к удалённому кластеру.
Настройки удалённого кластера, указанные с помощью API для обновления настроек кластера, имеют приоритет над настройками, которые вы указываете в elasticsearch.yml для отдельных узлов.
В следующем примере cluster_one, cluster_two и cluster_three — это произвольные псевдонимы кластера, представляющие подключение к каждому кластеру. Эти имена впоследствии используются для различения локальных и удалённых индексов.
cluster:
remote:
cluster_one:
seeds: 127.0.0.1:9443
cluster_two:
mode: sniff
seeds: 127.0.0.1:9444
transport.compress: true
skip_unavailable: true
cluster_three:
mode: proxy
proxy_address: 127.0.0.1:9445 | Сжатие явно включено для запросов к | |
| Отключённые удалённые кластеры являются необязательными для | |
| Адрес прокси-конечной точки, используемой для подключения к |
Настройка ролей и пользователей
Для использования удаленного кластера для кросс-кластерной репликации или кросс-кластерного поиска необходимо создать роли пользователей с привилегиями доступа к удаленным индексам или привилегиями доступа к удаленному кластеру на локальном кластере.
Вы можете управлять пользователями и ролями из Stack Management в Kibana, выбрав Безопасность > Роли в боковом навигационном меню. Также можно использовать API для управления ролями для динамического добавления, обновления, удаления и получения ролей.
В следующих примерах используется API для создания или обновления ролей. Для использования этого API необходимо иметь, как минимум, привилегию manage_security кластера.
Ключ API кросс-кластерного доступа, используемый локальным кластером для подключения к удаленному кластеру, должен иметь достаточные привилегии для покрытия всех привилегий доступа к удаленным индексам, необходимых отдельным пользователям.
Настройка привилегий для кросс-кластерной репликации
Предполагая, что удаленный кластер подключен под именем my_remote_cluster, следующий запрос создаёт роль под названием remote-replication на локальном кластере, которая позволяет выполнять репликацию удалённого индекса leader-index:
resp = client.security.put_role(
name="remote-replication",
cluster=[
"manage_ccr"
],
remote_indices=[
{
"clusters": [
"my_remote_cluster"
],
"names": [
"leader-index"
],
"privileges": [
"cross_cluster_replication"
]
}
],
)
print(resp) const response = await client.security.putRole({
name: "remote-replication",
cluster: ["manage_ccr"],
remote_indices: [
{
clusters: ["my_remote_cluster"],
names: ["leader-index"],
privileges: ["cross_cluster_replication"],
},
],
});
console.log(response); POST /_security/role/remote-replication
{
"cluster": [
"manage_ccr"
],
"remote_indices": [
{
"clusters": [ "my_remote_cluster" ],
"names": [
"leader-index"
],
"privileges": [
"cross_cluster_replication"
]
}
]
} После создания роли remote-replication на локальном кластере, используйте API для создания или обновления пользователей для создания пользователя на локальном кластере и назначения роли remote-replication. Например, следующий запрос назначает роль remote-replication пользователю с именем cross-cluster-user:
resp = client.security.put_user(
username="cross-cluster-user",
password="l0ng-r4nd0m-p@ssw0rd",
roles=[
"remote-replication"
],
)
print(resp) const response = await client.security.putUser({
username: "cross-cluster-user",
password: "l0ng-r4nd0m-p@ssw0rd",
roles: ["remote-replication"],
});
console.log(response); POST /_security/user/cross-cluster-user
{
"password" : "l0ng-r4nd0m-p@ssw0rd",
"roles" : [ "remote-replication" ]
} Обратите внимание, что вам необходимо создать этого пользователя только на локальном кластере.
Настройка привилегий для кросс-кластерного поиска
Предполагая, что удалённый кластер подключён под именем my_remote_cluster, следующий запрос создаёт роль remote-search на локальном кластере, которая позволяет выполнять поиск в удалённом индексе target-index:
resp = client.security.put_role(
name="remote-search",
remote_indices=[
{
"clusters": [
"my_remote_cluster"
],
"names": [
"target-index"
],
"privileges": [
"read",
"read_cross_cluster",
"view_index_metadata"
]
}
],
)
print(resp) const response = await client.security.putRole({
name: "remote-search",
remote_indices: [
{
clusters: ["my_remote_cluster"],
names: ["target-index"],
privileges: ["read", "read_cross_cluster", "view_index_metadata"],
},
],
});
console.log(response); POST /_security/role/remote-search
{
"remote_indices": [
{
"clusters": [ "my_remote_cluster" ],
"names": [
"target-index"
],
"privileges": [
"read",
"read_cross_cluster",
"view_index_metadata"
]
}
]
} После создания роли remote-search, используйте API для создания или обновления пользователей для создания пользователя на локальном кластере и назначения роли remote-search. Например, следующий запрос назначает роль remote-search пользователю с именем cross-search-user:
resp = client.security.put_user(
username="cross-search-user",
password="l0ng-r4nd0m-p@ssw0rd",
roles=[
"remote-search"
],
)
print(resp) const response = await client.security.putUser({
username: "cross-search-user",
password: "l0ng-r4nd0m-p@ssw0rd",
roles: ["remote-search"],
});
console.log(response); POST /_security/user/cross-search-user
{
"password" : "l0ng-r4nd0m-p@ssw0rd",
"roles" : [ "remote-search" ]
} Обратите внимание, что вам необходимо создать этого пользователя только на локальном кластере.
© 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/remote-clusters-api-key.html