远程集群

edit

您可以将本地集群连接到其他Elasticsearch集群,这些集群被称为远程集群。远程集群可以位于不同的数据中心或地理区域,并且包含可以通过跨集群复制进行复制或通过本地集群使用跨集群搜索进行搜索的索引或数据流。

跨集群复制

edit

通过跨集群复制,您可以将数据摄取到远程集群上的索引中。这个领导者索引会被复制到一个或多个只读的追随者索引到您的本地集群。使用跨集群复制创建多集群架构使您能够配置灾难恢复、将数据更接近您的用户,或建立一个集中式报告集群以在本地处理报告。

跨集群搜索

edit

跨集群搜索使您能够对一个或多个远程集群运行搜索请求。此功能为每个区域提供了所有集群的全局视图,允许您从本地集群发送搜索请求并从所有连接的远程集群返回结果。为了实现完整的跨集群搜索功能,本地和远程集群必须在相同的订阅级别

添加远程集群

edit

以下说明描述了如何从自管理集群创建远程连接。您还可以从Elasticsearch Service 部署或从Elastic Cloud Enterprise 部署设置跨集群搜索和跨集群复制。

要添加远程集群,您可以在 两种安全模型两种连接模式之间进行选择。两种安全模型都与任一连接模式兼容。

安全模型

edit
API key based security model
对于版本8.14或更高版本的集群,您可以使用API密钥进行身份验证和授权跨集群操作到远程集群。此模型为本地和远程集群的管理员提供了细粒度的访问控制。使用API密钥身份验证添加远程集群
Certificate based security model
使用相互TLS认证进行跨集群操作。用户认证在本地集群上执行,用户的角色名称被传递到远程集群。在这种模式下,本地集群上的超级用户获得对远程集群的完全读取访问权限,因此它仅适用于处于相同安全域的集群。使用TLS证书认证添加远程集群

连接模式

edit
Sniff mode

在嗅探模式下,使用您选择的名称注册一个集群别名,并使用cluster.remote..seeds设置指定一组种子节点的地址。当您使用嗅探模式注册远程集群时,Elasticsearch会从其中一个种子节点获取最多三个网关节点的地址。本地Elasticsearch集群中的每个remote_cluster_client节点随后会打开与网关节点的发布地址的多个TCP连接。因此,此模式要求网关节点的发布地址对本地集群中的节点是可访问的。

嗅探模式是默认的连接模式。有关配置嗅探模式的更多信息,请参阅嗅探模式远程集群设置

网关节点的选择取决于以下标准:

  • 版本: 远程节点必须与它们注册到的集群兼容。
  • 角色: 默认情况下,任何非主节点都可以充当网关节点。专用主节点永远不会被选为网关节点。
  • 属性: 您可以通过将cluster.remote.node.attr.gateway设置为true来定义集群的网关节点。然而,这些节点仍然必须满足上述两个要求。
Proxy mode

在代理模式下,集群别名会注册为您选择的名称,并使用 cluster.remote..proxy_address 设置指定一个TCP(第4层)反向代理的地址。您必须配置此代理以将连接路由到一个或多个远程集群节点。当您使用代理模式注册远程集群时,Elasticsearch会打开多个TCP连接到代理地址,并使用这些连接与远程集群通信。在代理模式下,Elasticsearch会忽略远程集群节点的发布地址,这意味着远程集群节点的发布地址不需要对本地集群可访问。

代理模式不是默认的连接模式,因此您必须设置 cluster.remote..mode: proxy 才能使用它。有关配置代理模式的更多信息,请参阅 代理模式远程集群设置

代理模式与嗅探模式具有相同的版本兼容性要求

使用 API 密钥认证添加远程集群

edit

API 密钥认证使本地集群能够通过 跨集群 API 密钥 与远程集群进行身份验证。API 密钥需要由远程集群的管理员创建。本地集群配置为在每次请求远程集群时提供此 API 密钥。远程集群验证 API 密钥并根据 API 密钥的权限授予访问权限。

本地集群的所有跨集群请求都受API密钥权限的限制,无论与请求关联的本地用户是谁。例如,如果API密钥仅允许对远程集群上的my-index进行读取访问,即使本地集群的管理员用户也会受到此限制。此机制使远程集群的管理员能够完全控制谁可以通过跨集群搜索和/或跨集群复制访问哪些数据。远程集群的管理员可以确信,任何访问都不会超出明确分配给API密钥的权限。

在本地集群端,并非每个本地用户都需要访问API密钥允许的每一条数据。本地集群的管理员可以进一步配置本地用户的额外权限约束,以便每个用户只能访问必要的远程数据。请注意,只能进一步减少API密钥允许的权限,无法增加权限超出API密钥允许的范围。

在这个模型中,跨集群操作使用一个专用的服务器端口(远程集群接口)进行集群之间的通信。远程集群必须启用此端口,以便本地集群能够连接。为此端口配置传输层安全性(TLS)以最大化安全性(如与远程集群建立信任中所述)。

本地集群必须在远程集群接口上信任远程集群。这意味着本地集群信任远程集群的证书颁发机构(CA),该机构签署了远程集群接口使用的服务器证书。在建立连接时,参与跨集群通信的本地集群的所有节点都会根据TLS信任配置验证另一侧节点的证书。

使用API密钥认证添加远程集群:

如果您遇到任何问题,请参考故障排除

先决条件

edit
  • Elasticsearch 安全功能需要在两个集群的每个节点上启用。安全功能默认启用。如果已禁用,请在 elasticsearch.yml 中将 xpack.security.enabled 设置为 true。请参阅 通用安全设置
  • 本地和远程集群的节点必须在版本 8.10 或更高版本上。
  • 本地和远程集群必须具有适当的许可证。有关更多信息,请参阅 https://www.elastic.co/subscriptions

与远程集群建立信任

edit

如果远程集群是 Elasticsearch Service 部署的一部分,它默认具有有效的证书。因此,您可以跳过这些说明中与证书相关的步骤。

在远程集群上

edit
  1. 在远程集群的每个节点上启用远程集群服务器。在 elasticsearch.yml中:

    1. remote_cluster_server.enabled设置为 true
    2. 配置远程集群服务器的绑定和发布地址,例如使用remote_cluster.host。如果不配置地址,远程集群流量可能会绑定到本地接口,其他机器上运行的远程集群将无法连接。
    3. 可选地,使用remote_cluster.port配置远程服务器端口(默认为9443)。
  2. 接下来,生成一个证书颁发机构(CA)和一个服务器证书/密钥对。 在远程集群的一个节点上,从已安装Elasticsearch的目录中:

    1. 创建一个CA,如果你还没有CA的话:

      ./bin/elasticsearch-certutil ca --pem --out=cross-cluster-ca.zip --pass CA_PASSWORD

      CA_PASSWORD 替换为您希望用于CA的密码。如果您不是部署到生产环境中,可以删除 --pass 选项及其参数。

    2. 解压生成的 cross-cluster-ca.zip 文件。这个压缩文件包含以下内容:

      /ca
      |_ ca.crt
      |_ ca.key
    3. 为远程集群中的节点生成证书和私钥对:

      ./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地址。
    4. 如果远程集群有多个节点,您可以:

      • 为所有节点创建一个通配符证书;
      • 或者,为每个节点手动或批量创建单独的证书,使用静默模式
  3. 在远程集群的每个节点上:

    1. cross-cluster.p12 文件从上一步复制到 config 目录。如果您没有创建通配符证书,请确保复制正确的节点特定p12文件。
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_server.ssl.enabled: true
      xpack.security.remote_cluster_server.ssl.keystore.path: cross-cluster.p12
    3. 将SSL密钥库密码添加到Elasticsearch密钥库中:

      ./bin/elasticsearch-keystore add xpack.security.remote_cluster_server.ssl.keystore.secure_password

      当提示时,输入前面步骤中的CERT_PASSWORD

  4. 重启远程集群。
  5. 在远程集群上,生成一个跨集群API密钥,该密钥提供对您希望用于跨集群搜索或跨集群复制的索引的访问权限。您可以使用创建跨集群API密钥APIKibana
  6. 将编码的密钥(响应中的encoded)复制到一个安全的位置。稍后您将需要它来连接到远程集群。

在本地集群上

edit
  1. 在本地集群的每个节点上:

    1. 将之前在远程集群上生成的 ca.crt 文件复制到 config 目录中,并将其重命名为 remote-cluster-ca.crt
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_client.ssl.enabled: true
      xpack.security.remote_cluster_client.ssl.certificate_authorities: [ "remote-cluster-ca.crt" ]
    3. 将之前在远程集群上创建的跨集群API密钥添加到密钥库中:

      ./bin/elasticsearch-keystore add cluster.remote.ALIAS.credentials

      ALIAS 替换为您稍后将用于创建远程集群条目的相同名称。当提示时,输入之前在远程集群上创建的编码跨集群 API 密钥。

  2. 重启本地集群以加载密钥库和设置的更改。

注意: 如果你只配置跨集群的API密钥,你可以调用节点重新加载安全设置 API,而不需要重启集群。 在elasticsearch.yml中配置remote_cluster_client设置仍然需要重启。

连接到远程集群

edit

您必须拥有 manage 集群权限才能连接远程集群。

本地集群使用远程集群接口与远程集群建立通信。本地集群中的协调节点与远程集群中的特定节点建立长连接TCP连接。Elasticsearch要求这些连接保持打开状态,即使连接在很长一段时间内处于空闲状态。

要在 Kibana 的 Stack Management 中添加远程集群:

  1. 从侧边导航中选择远程集群
  2. 输入远程集群的名称(集群别名)。
  3. 指定Elasticsearch端点URL,或远程集群的IP地址或主机名,后跟远程集群端口(默认为9443)。例如,cluster.es.eastus2.staging.azure.foundit.no:9443192.168.1.1:9443

或者,使用集群更新设置 API 来添加远程集群。您还可以使用此 API 为本地集群中的每个节点动态配置 远程集群。要在本地集群中的各个节点上配置远程集群,请在每个节点的 elasticsearch.yml 中定义静态设置。

以下请求添加了一个别名为 cluster_one 的远程集群。这个 集群别名 是一个唯一标识符,代表与远程集群的连接,并用于区分本地和远程索引。

PUT /_cluster/settings
{
  "persistent" : {
    "cluster" : {
      "remote" : {
        "cluster_one" : {    
          "seeds" : [
            "127.0.0.1:9443" 
          ]
        }
      }
    }
  }
}

这个远程集群的集群别名是 cluster_one

指定远程集群中种子节点的主机名和远程集群端口。

您可以使用远程集群信息API来验证本地集群是否成功连接到远程集群:

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密钥认证进行连接。

动态配置远程集群

edit

使用集群更新设置API来动态配置集群中每个节点的远程设置。以下请求添加了三个远程集群:cluster_onecluster_twocluster_three

参数 seeds 指定了远程集群中种子节点的 远程集群端口(默认值为 9443)和主机名。

mode 参数决定了配置的连接模式,默认为 sniff。由于 cluster_one 没有指定 mode,因此它使用默认模式。cluster_twocluster_three 则明确使用了不同的模式。

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的压缩设置,以及cluster_three的压缩和ping调度设置。

当压缩或ping调度设置更改时,所有现有的节点连接必须关闭并重新打开,这可能导致正在进行的请求失败。

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "transport.compress": false
        },
        "cluster_three": {
          "transport.compress": true,
          "transport.ping_schedule": "60s"
        }
      }
    }
  }
}

您可以通过为每个远程集群设置传递null值来从集群设置中删除远程集群。以下请求将移除cluster_two,而保留cluster_onecluster_three

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "mode": null,
          "seeds": null,
          "skip_unavailable": null,
          "transport.compress": null
        }
      }
    }
  }
}

静态配置远程集群

edit

如果您在 elasticsearch.yml 中指定了设置,只有具有这些设置的节点才能连接到远程集群并处理远程集群请求。

使用集群更新设置 API指定的远程集群设置优先于您在elasticsearch.yml中为单个节点指定的设置。

在下面的示例中,cluster_onecluster_twocluster_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 

压缩已明确启用,用于对 cluster_two 的请求。

断开连接的远程集群对于cluster_two是可选的。

用于连接到 cluster_three 的代理端点的地址。

配置角色和用户

edit

要使用远程集群进行跨集群复制或跨集群搜索,您需要在本地集群上创建具有远程索引权限的用户角色。

您可以通过在Kibana的Stack Management中选择侧边导航中的安全 > 角色来管理用户和角色。您还可以使用角色管理API来动态添加、更新、删除和检索角色。

以下示例使用创建或更新角色 API。您必须至少拥有manage_security集群权限才能使用此 API。

本地集群用于连接远程集群的跨集群API密钥必须具有足够的权限,以覆盖各个用户所需的所有远程索引权限。

配置跨集群复制的权限

edit

假设远程集群在本地集群中以名称 my_remote_cluster 连接, 以下请求在本地集群中创建一个名为 remote-replication 的角色, 该角色允许复制远程的 leader-index 索引:

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 的用户:

POST /_security/user/cross-cluster-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-replication" ]
}

请注意,您只需在本地集群上创建此用户。

配置跨集群搜索的权限

edit

假设远程集群在本地集群中以名称 my_remote_cluster 连接, 以下请求在本地集群上创建一个 remote-search 角色, 允许搜索远程的 target-index 索引:

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 的用户:

POST /_security/user/cross-search-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-search" ]
}

请注意,您只需要在本地集群上创建此用户。

使用TLS证书认证添加远程集群

edit

使用TLS证书认证添加远程集群:

如果您遇到任何问题,请参考故障排除

先决条件

edit
  1. Elasticsearch 安全功能需要在每个集群的每个节点上启用。 安全功能默认启用。如果已禁用,请在 elasticsearch.yml 中将 xpack.security.enabled 设置为 true。请参阅 通用安全设置
  2. 本地和远程集群的版本必须兼容。

    • 任何节点都可以与同一主要版本上的另一个节点通信。例如,7.0 可以与任何 7.x 节点通信。
    • 只有某个主要版本的最后一个次要版本上的节点才能与下一个主要版本上的节点通信。在 6.x 系列中,6.8 可以与任何 7.x 节点通信,而 6.7 只能与 7.0 通信。
    • 版本兼容性是对称的,这意味着如果 6.7 可以与 7.0 通信,7.0 也可以与 6.7 通信。下表展示了本地节点和远程节点之间的版本兼容性。

      版本兼容性表

      本地集群

      远程集群

      5.0–5.5

      5.6

      6.0–6.6

      6.7

      6.8

      7.0

      7.1–7.16

      7月17日

      8.0–9.0

      5.0–5.5

      是

      是

      否

      否

      否

      否

      否

      否

      否

      5.6

      是

      是

      是

      是

      是

      否

      否

      否

      否

      6.0–6.6

      否

      是

      是

      是

      是

      否

      否

      否

      否

      6.7

      否

      是

      是

      是

      是

      是

      否

      否

      否

      6.8

      否

      是

      是

      是

      是

      是

      是

      是

      否

      7.0

      否

      否

      <span class="image

与远程集群建立信任

edit

要在远程集群上安全地使用跨集群复制或跨集群搜索,请在所有连接的集群上启用安全性,并在每个节点上配置传输层安全性(TLS)。 在传输接口上配置TLS安全性是远程集群的最低要求。为了增加安全性,还可以在 HTTP接口上配置TLS。

所有连接的集群必须相互信任,并在传输接口上通过TLS进行相互认证。这意味着本地集群信任远程集群的证书颁发机构(CA),而远程集群信任本地集群的CA。在建立连接时,所有节点都会验证对方节点的证书。这种相互信任是安全连接远程集群所必需的,因为所有连接的节点实际上形成了一个单一的安全域。

用户认证在本地集群上进行,用户和用户的角色名称会被传递到远程集群。远程集群会根据其本地的角色定义来检查用户的角色名称,以确定用户可以访问哪些索引。

在使用跨集群复制或跨集群搜索与安全的Elasticsearch集群之前,完成以下配置任务:

  1. 在每个节点上配置传输层安全(TLS)以加密节点间流量,并使用本地集群中的节点对所有远程集群中的节点进行身份验证。请参阅为Elastic Stack设置基本安全以获取配置安全所需的步骤。

    此过程使用相同的CA为所有节点生成证书。或者,您可以将本地集群的证书添加为每个远程集群中的受信任CA。您还必须将远程集群的证书添加为本地集群中的受信任CA。使用相同的CA为所有节点生成证书简化了此任务。

连接到远程集群

edit

您必须拥有 manage 集群权限才能连接远程集群。

本地集群使用传输接口与远程集群建立通信。本地集群中的协调节点与远程集群中的特定节点建立长连接TCP连接。Elasticsearch要求这些连接保持打开状态,即使连接在较长时间内处于空闲状态。

要在 Kibana 的 Stack Management 中添加远程集群:

  1. 从侧边导航中选择远程集群
  2. 输入远程集群的名称(集群别名)。
  3. 指定Elasticsearch端点URL,或远程集群的IP地址或主机名,后跟传输端口(默认为 9300)。例如, cluster.es.eastus2.staging.azure.foundit.no:9300192.168.1.1:9300

或者,使用集群更新设置 API 来添加远程集群。您还可以使用此 API 为本地集群中的每个节点动态配置 远程集群。要在本地集群中的各个节点上配置远程集群,请在每个节点的 elasticsearch.yml 中定义静态设置。

以下请求添加了一个别名为 cluster_one 的远程集群。这个 集群别名 是一个唯一标识符,代表与远程集群的连接,并用于区分本地和远程索引。

PUT /_cluster/settings
{
  "persistent" : {
    "cluster" : {
      "remote" : {
        "cluster_one" : {    
          "seeds" : [
            "127.0.0.1:9300" 
          ]
        }
      }
    }
  }
}

这个远程集群的集群别名是 cluster_one

指定远程集群中种子节点的主机名和传输端口。

您可以使用远程集群信息API来验证本地集群是否成功连接到远程集群:

GET /_remote/info

API 响应表明本地集群已通过集群别名 cluster_one 连接到远程集群:

{
  "cluster_one" : {
    "seeds" : [
      "127.0.0.1:9300"
    ],
    "connected" : true,
    "num_nodes_connected" : 1,  
    "max_connections_per_cluster" : 3,
    "initial_connect_timeout" : "30s",
    "skip_unavailable" : true, 
    "mode" : "sniff"
  }
}

本地集群连接到的远程集群中的节点数量。

指示在通过跨集群搜索进行搜索时,如果没有可用节点,是否跳过远程集群。

动态配置远程集群

edit

使用集群更新设置API来动态配置集群中每个节点的远程设置。以下请求添加了三个远程集群:cluster_onecluster_twocluster_three

参数 seeds 指定了远程集群中种子节点的 传输端口(默认值为 9300)和主机名。

mode 参数决定了配置的连接模式,默认为 sniff。由于 cluster_one 没有指定 mode,因此它使用默认模式。cluster_twocluster_three 则明确使用了不同的模式。

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_one": {
          "seeds": [
            "127.0.0.1:9300"
          ]
        },
        "cluster_two": {
          "mode": "sniff",
          "seeds": [
            "127.0.0.1:9301"
          ],
          "transport.compress": true,
          "skip_unavailable": true
        },
        "cluster_three": {
          "mode": "proxy",
          "proxy_address": "127.0.0.1:9302"
        }
      }
    }
  }
}

您可以在初始配置后动态更新远程集群的设置。以下请求更新了cluster_two的压缩设置,以及cluster_three的压缩和ping调度设置。

当压缩或ping调度设置更改时,所有现有的节点连接必须关闭并重新打开,这可能导致正在进行的请求失败。

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "transport.compress": false
        },
        "cluster_three": {
          "transport.compress": true,
          "transport.ping_schedule": "60s"
        }
      }
    }
  }
}

您可以通过为每个远程集群设置传递null值来从集群设置中删除远程集群。以下请求将移除cluster_two,而保留cluster_onecluster_three

PUT _cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "cluster_two": {
          "mode": null,
          "seeds": null,
          "skip_unavailable": null,
          "transport.compress": null
        }
      }
    }
  }
}

静态配置远程集群

edit

如果您在 elasticsearch.yml 中指定了设置,只有具有这些设置的节点才能连接到远程集群并处理远程集群请求。

使用集群更新设置 API指定的远程集群设置优先于您在elasticsearch.yml中为单个节点指定的设置。

在下面的示例中,cluster_onecluster_twocluster_three 是表示每个集群连接的任意集群别名。这些名称随后用于区分本地和远程索引。

cluster:
    remote:
        cluster_one:
            seeds: 127.0.0.1:9300
        cluster_two:
            mode: sniff
            seeds: 127.0.0.1:9301
            transport.compress: true      
            skip_unavailable: true        
        cluster_three:
            mode: proxy
            proxy_address: 127.0.0.1:9302 

压缩已明确启用,用于对 cluster_two 的请求。

断开连接的远程集群对于cluster_two是可选的。

用于连接到 cluster_three 的代理端点的地址。

为远程集群配置角色和用户

edit

连接远程集群之后,您需要在本地和远程集群上创建用户角色并分配必要的权限。 这些角色是使用跨集群复制和跨集群搜索所必需的。

您必须在本地和远程集群上使用相同的角色名称。例如,以下跨集群复制配置在本地和远程集群上都使用了remote-replication角色名称。但是,您可以在每个集群上指定不同的角色定义。

您可以通过在Kibana的Stack Management中选择侧导航栏中的安全 > 角色来管理用户和角色。您还可以使用角色管理API来动态添加、更新、删除和检索角色。当您使用API在native领域中管理角色时,这些角色存储在Elasticsearch的内部索引中。

以下请求使用 创建或更新角色 API。您必须至少拥有 manage_security 集群权限才能使用此 API。

配置跨集群复制的权限

edit

跨集群复制用户在远程集群和本地集群上需要不同的集群和索引权限。使用以下请求在本地和远程集群上创建单独的角色,然后创建具有所需角色的用户。

远程集群
edit

在包含主索引的远程集群上,跨集群复制角色需要read_ccr集群权限,以及主索引上的monitorread权限。

如果请求使用API密钥进行身份验证,则API密钥需要在本地集群上具有上述权限,而不是远程集群。

如果请求是代表其他用户发出的,那么进行身份验证的用户必须在远程集群上具有run_as权限。

以下请求在远程集群上创建一个remote-replication角色:

POST /_security/role/remote-replication
{
  "cluster": [
    "read_ccr"
  ],
  "indices": [
    {
      "names": [
        "leader-index-name"
      ],
      "privileges": [
        "monitor",
        "read"
      ]
    }
  ]
}
本地集群
edit

在包含从属索引的本地集群上,remote-replication角色需要manage_ccr集群权限,以及在从属索引上的monitorreadwritemanage_follow_index权限。

以下请求在本地集群上创建一个远程复制角色:

POST /_security/role/remote-replication
{
  "cluster": [
    "manage_ccr"
  ],
  "indices": [
    {
      "names": [
        "follower-index-name"
      ],
      "privileges": [
        "monitor",
        "read",
        "write",
        "manage_follow_index"
      ]
    }
  ]
}

在每个集群上创建remote-replication角色后,使用创建或更新用户API在本地集群上创建一个用户并分配remote-replication角色。例如,以下请求将remote-replication角色分配给名为cross-cluster-user的用户:

POST /_security/user/cross-cluster-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-replication" ]
}

您只需要在本地集群上创建此用户。

然后,您可以配置跨集群复制,以在数据中心之间复制您的数据。

配置跨集群搜索的权限

edit

跨集群搜索用户在远程集群和本地集群上需要不同的集群和索引权限。以下请求在本地和远程集群上创建单独的角色,然后创建一个具有所需角色的用户。

远程集群
edit

在远程集群上,跨集群搜索角色需要目标索引的读取跨集群读取权限。

如果请求使用API密钥进行身份验证,则API密钥需要在本地集群上具有上述权限,而不是远程集群。

如果请求是代表其他用户发出的,那么进行身份验证的用户必须在远程集群上具有run_as权限。

以下请求在远程集群上创建一个remote-search角色:

POST /_security/role/remote-search
{
  "indices": [
    {
      "names": [
        "target-indices"
      ],
      "privileges": [
        "read",
        "read_cross_cluster"
      ]
    }
  ]
}
本地集群
edit

在本地集群上,即用于启动跨集群搜索的集群,用户只需要remote-search角色。该角色的权限可以为空。

以下请求在本地集群上创建一个remote-search角色:

POST /_security/role/remote-search
{}

在每个集群上创建了remote-search角色后,使用创建或更新用户API在本地集群上创建一个用户并分配remote-search角色。例如,以下请求将remote-search角色分配给名为cross-search-user的用户:

POST /_security/user/cross-search-user
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [ "remote-search" ]
}

您只需要在本地集群上创建此用户。

拥有 remote-search 角色的用户可以 跨集群搜索

配置跨集群搜索和Kibana的权限

edit

当使用 Kibana 跨多个集群进行搜索时,两步授权过程决定了用户是否可以访问远程集群上的数据流和索引:

  • 首先,本地集群确定用户是否有权访问远程集群。本地集群是Kibana连接到的集群。
  • 如果用户被授权,远程集群随后确定用户是否有权访问指定的数据流和索引。

要授予Kibana用户访问远程集群的权限,请为他们分配一个本地角色,该角色具有对远程集群上索引的读取权限。您可以在远程集群中指定数据流和索引为:

要授予用户对远程数据流和索引的读取访问权限,您必须在远程集群上创建一个匹配的角色,该角色授予具有适当数据流和索引访问权限的read_cross_cluster权限。

例如,您可能正在本地集群上主动索引Logstash数据,并定期将较旧的基于时间的索引导出到远程集群上的存档中。您希望在两个集群中进行搜索,因此必须在两个集群上启用Kibana用户。

本地集群
edit

在本地集群上,创建一个logstash-reader角色,授予对本地logstash-*索引的readview_index_metadata权限。

如果您将本地集群配置为Elasticsearch中的另一个远程集群,则本地集群上的logstash-reader角色也需要授予read_cross_cluster权限。

POST /_security/role/logstash-reader
{
  "indices": [
    {
      "names": [
        "logstash-*"
        ],
        "privileges": [
          "read",
          "view_index_metadata"
          ]
    }
  ]
}

为您的 Kibana 用户分配一个角色,该角色授予 访问 Kibana 的权限,以及您的 logstash_reader 角色。例如,以下请求创建了 cross-cluster-kibana 用户,并分配了 kibana-accesslogstash-reader 角色。

PUT /_security/user/cross-cluster-kibana
{
  "password" : "l0ng-r4nd0m-p@ssw0rd",
  "roles" : [
    "logstash-reader",
    "kibana-access"
    ]
}
远程集群
edit

在远程集群上,创建一个logstash-reader角色,授予read_cross_cluster权限以及logstash-*索引的readview_index_metadata权限。

POST /_security/role/logstash-reader
{
  "indices": [
    {
      "names": [
        "logstash-*"
        ],
        "privileges": [
          "read_cross_cluster",
          "read",
          "view_index_metadata"
          ]
    }
  ]
}

从证书迁移远程集群到API密钥认证

edit

基于API密钥的远程集群安全模型相比基于TLS证书的安全模型,为管理员提供了更精细的访问控制。因此,您可能希望从基于证书的安全模型迁移到基于API密钥的模型。

虽然可以通过定义一个新的远程集群连接、使用一个新的别名来进行迁移,但这有几个缺点:

  • 对于跨集群复制,无法更改现有任务的领导者集群别名。因此,使用新的远程集群时,需要从头开始重新创建跟随者索引。
  • 对于跨集群搜索,转换和异常检测作业确实允许更新远程集群别名。但是,如果作业是使用通配符创建的,例如*:source_index,并且superuser,添加新的远程集群将导致作业执行双倍的工作量,并可能导致结果出现重复。

由于这些原因,您可能更倾向于通过以下步骤就地迁移远程集群:

如果您遇到任何问题,请参考故障排除

前提条件

edit
  • 本地和远程集群的节点必须为8.10或更高版本。
  • 本地和远程集群必须具有适当的许可证。更多信息,请参阅https://www.elastic.co/subscriptions

重新配置远程集群并生成跨集群API密钥

edit

在远程集群上:

  1. 在远程集群的每个节点上启用远程集群服务器。在 elasticsearch.yml中:

    1. remote_cluster_server.enabled 设置为 true
    2. 配置远程集群服务器的绑定和发布地址,例如使用 remote_cluster.host。如果不配置地址,远程集群流量可能会绑定到本地接口,其他机器上运行的远程集群将无法连接。
    3. 可选地,使用 remote_cluster.port 配置远程服务器端口(默认为 9443)。
  2. 接下来,生成一个证书颁发机构(CA)和一个服务器证书/密钥对。 在远程集群的一个节点上,从已安装Elasticsearch的目录中:

    1. 创建一个CA,如果你还没有CA的话:

      ./bin/elasticsearch-certutil ca --pem --out=cross-cluster-ca.zip --pass CA_PASSWORD

      CA_PASSWORD 替换为您希望用于CA的密码。如果您不是部署到生产环境中,可以删除 --pass 选项及其参数。

    2. 解压生成的 cross-cluster-ca.zip 文件。这个压缩文件包含以下内容:

      /ca
      |_ ca.crt
      |_ ca.key
    3. 为远程集群中的节点生成证书和私钥对:

      ./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地址。
    4. 如果远程集群有多个节点,您可以:

      • 为所有节点创建一个通配符证书;
      • 或者,为每个节点手动或批量创建单独的证书,使用 静默模式
  3. 在远程集群的每个节点上:

    1. cross-cluster.p12 文件从上一步复制到 config 目录。如果您没有创建通配符证书,请确保复制正确的节点特定p12文件。
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_server.ssl.enabled: true
      xpack.security.remote_cluster_server.ssl.keystore.path: cross-cluster.p12
    3. 将SSL密钥库密码添加到Elasticsearch密钥库中:

      ./bin/elasticsearch-keystore add xpack.security.remote_cluster_server.ssl.keystore.secure_password

      当提示时,输入前面步骤中的CERT_PASSWORD

  4. 重启远程集群。
  5. 在远程集群上,生成一个跨集群API密钥,该密钥提供对您希望用于跨集群搜索或跨集群复制的索引的访问权限。您可以使用 创建跨集群API密钥APIKibana
  6. 将编码的密钥(响应中的encoded)复制到一个安全的位置。稍后您将需要它来连接到远程集群。

停止跨集群操作

edit

在本地集群上,停止任何引用远程集群的持久任务:

重新连接到远程集群

edit

在本地集群上:

  1. 为本地集群用户使用的任何角色增强所需的 远程索引权限,以支持跨集群复制和跨集群搜索。 请参阅 配置角色和用户。注意:

    • You only need to assign additional remote_indices privileges to existing roles used for cross-cluster operations. You should be able to copy these privileges from the original roles on the remote cluster, where they are defined under the certification based security model.
    • The roles on the local cluster can’t exceed the access privilege granted by the cross-cluster API key. Any extra local privileges will be suppressed by the cross-cluster API key’s privileges.
    • No update is needed if the cross-cluster replication or cross-cluster search tasks have been configured with a superuser role. The superuser role is automatically updated to allow access to all remote indices.
    • Tasks that are run as regular users with named roles are immediately updated with the new privileges. A task will load a new definition the next time it runs.
    • You need to restart tasks that are run using an API key (done in a later step).
  2. 如果您已通过集群设置API动态配置了远程集群:

    1. 检索当前的远程集群配置,并将其安全地存储起来。如果以后需要回滚,您可能会需要它。使用集群设置 API:

      GET /_cluster/settings?filter_path=persistent.cluster.remote
    2. Remove the existing remote cluster definition by setting the remote cluster settings to null.
  3. If you’ve statically configured the remote cluster (via elasticsearch.yml), copy the cluster.remote settings from elasticsearch.yml, and store them in a safe place. You may need them later in case you need to roll back.
  4. 在本地集群的每个节点上:

    1. Copy the ca.crt file generated on the remote cluster earlier into the config directory, renaming the file remote-cluster-ca.crt.
    2. 将以下配置添加到 elasticsearch.yml

      xpack.security.remote_cluster_client.ssl.enabled: true
      xpack.security.remote_cluster_client.ssl.certificate_authorities: [ "remote-cluster-ca.crt" ]
    3. 将之前在远程集群上创建的跨集群API密钥添加到密钥库中:

      ./bin/elasticsearch-keystore add cluster.remote.ALIAS.credentials

      ALIAS 替换为迁移前用于跨集群操作的相同别名。当提示时,输入之前在远程集群上创建的编码跨集群 API 密钥。

  5. 如果您已通过集群设置API动态配置了远程集群:

    1. Restart the local cluster to load changes to the keystore and settings.
    2. 重新添加远程集群。使用相同的远程集群别名,并将传输端口更改为远程集群端口。例如:

      PUT /_cluster/settings
      {
        "persistent" : {
          "cluster" : {
            "remote" : {
              "my_remote" : { 
                "mode": "proxy",
                "proxy_address": "my.remote.cluster.com:9443" 
              }
            }
          }
        }
      }

      远程集群别名。使用与迁移前相同的别名。

      远程集群地址和远程集群端口,默认端口为 9443

  6. 如果您已通过elasticsearch.yml静态配置了远程集群:

    1. Update the cluster.remote settings in elasticsearch.yml on each node of the local cluster. Change the port into the remote cluster port, which defaults to 9443.
    2. Restart the local cluster to load changes to the keystore and settings.
  7. 使用远程集群信息 API 来验证本地集群是否已成功连接到远程集群:

    GET /_remote/info

    API 响应应表明本地集群已连接到远程集群:

    {
      "my_remote": {
        "connected": true, 
        "mode": "proxy",
        "proxy_address": "my.remote.cluster.com:9443",
        "server_name": "",
        "num_proxy_sockets_connected": 0,
        "max_proxy_socket_connections": 18,
        "initial_connect_timeout": "30s",
        "skip_unavailable": false,
        "cluster_credentials": "::es_redacted::" 
      }
    }

    远程集群已连接。

    如果存在,表示远程集群已使用API密钥认证进行连接。

恢复跨集群操作

edit

恢复您之前停止的任何持久任务。任务应由迁移前创建该任务的同一用户或API密钥重新启动。确保此用户或API密钥的角色已更新为具有所需的remote_indices权限。对于用户,任务在启动时捕获调用者的凭据并在该用户的安全上下文中运行。对于API密钥,重新启动任务将使用更新的API密钥更新任务。

禁用基于证书的身份验证和授权

edit

仅在本地集群上的迁移已被证明成功的情况下继续此步骤。如果迁移不成功,请找出问题所在并尝试修复回滚

接下来,禁用基于认证的连接。可选地,您也可以撤销授权。

  1. 没有特定的设置来启用或禁用基于证书的跨集群连接,因为它与集群内节点间通信共享相同的传输协议。

    远程集群管理员可以通过更改TLS信任来阻止现有本地集群连接的一种方法。具体步骤因集群的配置方式而异。一个通用的解决方案是重新创建远程传输接口使用的CA和证书/密钥,以便任何现有的证书/密钥,无论是本地的还是分布式的,都不再受信任。

    另一种解决方案是对传输接口应用IP过滤器,阻止来自集群外部的流量。

  2. 可选地,删除远程集群上仅用于跨集群操作的任何角色。这些角色在基于API密钥的安全模型下不再使用。

回滚

edit

如果您需要回滚,请按照以下步骤在本地集群上操作:

  1. 停止任何引用远程集群的持久任务。
  2. 通过将远程集群设置设置为 null来删除远程集群定义。
  3. 从迁移期间更新的任何角色中删除remote_indices权限。
  4. 在每个节点上,从elasticsearch.yml中删除remote_cluster_client.ssl.*设置。
  5. 重新启动本地集群以应用对密钥库和elasticsearch.yml的更改。
  6. 在本地集群上应用原始的远程集群设置。如果远程集群连接已静态配置(使用elasticsearch.yml文件),请重新启动集群。
  7. 使用远程集群信息API验证本地集群是否已连接到远程集群。响应应包含"connected": true且不包含"cluster_credentials": "::es_redacted::"
  8. 重新启动您之前停止的任何持久任务。

远程集群设置

edit

以下设置适用于嗅探模式代理模式。特定于嗅探模式和代理模式的设置将单独描述。

cluster.remote.<cluster_alias>.mode
用于远程集群连接的模式。唯一支持的模式是 sniffproxy。默认是 sniff。有关这些模式的更多信息,请参阅 连接模式,以及有关其设置的更多信息,请参阅 嗅探模式远程集群设置代理模式远程集群设置
cluster.remote.initial_connect_timeout
节点启动时等待远程连接建立的时间。默认值为 30秒
remote_cluster_client role
默认情况下,集群中的任何节点都可以充当跨集群客户端并连接到远程集群。要阻止节点连接到远程集群,请在elasticsearch.yml中指定node.roles设置,并从列出的角色中排除remote_cluster_client。针对远程集群的搜索请求必须发送到允许充当跨集群客户端的节点。其他功能,如机器学习数据馈送转换跨集群复制需要remote_cluster_client角色。
cluster.remote.<cluster_alias>.skip_unavailable
每个集群的布尔设置,允许在无可用节点且它们是远程集群请求的目标时跳过特定集群。

在 Elasticsearch 8.15 中,skip_unavailable 的默认值从 false 更改为 true。在 Elasticsearch 8.15 之前,如果您希望将一个集群视为跨集群搜索的可选集群,则需要设置该配置。从 Elasticsearch 8.15 开始,您需要设置配置以使一个集群成为跨集群搜索的必需集群。一旦您将本地(查询)集群搜索协调节点(您发送 CCS 请求的节点)升级到 8.15 或更高版本,任何没有为 skip_unavailable 显式设置的远程集群将立即更改为使用新的默认值 true。无论您是否已将远程集群升级到 8.15,这都是正确的,因为 skip_unavailable 搜索行为完全由您配置远程的本地集群上的设置决定。

cluster.remote.<cluster_alias>.transport.ping_schedule
设置定期发送的应用程序级别ping消息的时间间隔,以尝试保持远程集群连接的活动状态。如果设置为-1,则不会向此远程集群发送应用程序级别的ping消息。如果未设置,应用程序级别的ping消息将根据全局transport.ping_schedule设置发送,默认值为-1,表示不发送ping消息。建议正确配置TCP keep-alives,而不是配置ping_schedule,因为TCP keep-alives由操作系统处理,而不是由Elasticsearch处理。默认情况下,Elasticsearch在远程集群连接上启用TCP keep-alives。远程集群连接是传输连接,因此与TCP keep-alives相关的transport.tcp.* 高级设置适用于它们。
cluster.remote.<cluster_alias>.transport.compress
针对特定远程集群的请求配置压缩的每个集群设置。处理集群将自动压缩对压缩请求的响应。设置选项为trueindexing_datafalse。如果未设置,则默认为节点范围的transport.compress设置所指定的行为。有关进一步信息,请参阅关于transport.compress设置的文档
cluster.remote.<cluster_alias>.transport.compression_scheme
每个集群的设置,使您能够配置对特定集群的请求的压缩方案,如果这些请求被选择为由cluster.remote..transport.compress设置进行压缩。处理集群将自动使用与相应请求相同的压缩方案进行响应。设置选项为deflatelz4。如果未设置,则默认为由节点范围的transport.compression_scheme设置指定的行为。有关更多信息,请参阅关于transport.compression_scheme设置的文档
cluster.remote.<cluster_alias>.credentials
(安全, 可重新加载) 用于配置基于API密钥模型的远程集群的每个集群设置。此设置采用跨集群API密钥的编码值,并且必须在集群中的每个节点上的Elasticsearch密钥库中设置。 此设置的存在与否决定了远程集群使用的模型。如果存在,远程集群使用API密钥模型。否则,它使用基于证书的模型。如果在Elasticsearch密钥库中添加、删除或更新此设置并通过节点重新加载安全设置API重新加载,集群将自动重建与远程集群的连接。

嗅探模式远程集群设置

edit

要使用嗅探模式连接到远程集群,请设置 cluster.remote..mode: sniff,然后配置以下 设置。您也可以不设置cluster.remote..mode,因为 sniff是默认模式。

cluster.remote.<cluster_alias>.seeds
用于嗅探远程集群状态的种子节点列表。
cluster.remote.<cluster_alias>.node_connections
连接到此远程集群的网关节点数量。默认值为3
cluster.remote.node.attr
用于过滤远程集群中符合网关节点条件的节点属性。例如,一个节点可以具有节点属性 node.attr.gateway: true,这样只有具有此属性的节点才会被连接,如果cluster.remote.node.attr设置为gateway

代理模式远程集群设置

edit

要使用代理模式连接到远程集群,请设置 cluster.remote..mode: proxy,然后配置以下 设置。

cluster.remote.<cluster_alias>.proxy_address
用于所有远程连接的地址。
cluster.remote.<cluster_alias>.proxy_socket_connections
每个远程集群要打开的套接字连接数。默认值是 18
cluster.remote.<cluster_alias>.server_name
一个可选的主机名字符串,如果启用了TLS,则会在TLS服务器名称指示扩展的server_name字段中发送。如果此字段不符合TLS SNI规范定义的有效主机名,TLS传输将无法打开远程连接。

远程集群故障排除

edit

在为跨集群复制或跨集群搜索设置远程集群时,您可能会遇到几个问题。

一般故障排除

edit

检查远程集群是否成功连接

edit

成功调用添加或更新远程集群的集群设置更新API并不一定意味着配置成功。使用远程集群信息API来验证本地集群是否成功连接到远程集群。

GET /_remote/info

API 应返回 "connected" : true。当使用 API 密钥认证时,还应返回 "cluster_credentials": "::es_redacted::"

{
  "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" : false,
    "cluster_credentials": "::es_redacted::", 
    "mode" : "sniff"
  }
}

远程集群已成功连接。

如果存在,表示远程集群已使用 API密钥认证 而不是 基于证书的认证 进行连接。

启用远程集群服务器

edit

当使用API密钥认证时,跨集群流量发生在远程集群接口上,而不是传输接口上。远程集群接口默认情况下未启用。这意味着默认情况下,节点未准备好接受传入的跨集群请求,而它已准备好发送传出的跨集群请求。请确保在远程集群的每个节点上启用了远程集群服务器。在elasticsearch.yml中:

  • remote_cluster_server.enabled 设置为 true
  • 配置远程集群服务器的绑定和发布地址,例如使用 remote_cluster.host。如果不配置地址,远程集群流量可能会绑定到本地接口,其他机器上运行的远程集群将无法连接。
  • 可选地,使用 remote_cluster.port 配置远程服务器端口(默认为 9443)。

常见问题

edit

以下问题按其在设置远程集群时可能出现的顺序列出。

远程集群不可访问

edit
症状
edit

本地集群可能由于多种原因无法访问远程集群。例如,远程集群服务器可能未启用,配置了错误的主机或端口,或者防火墙可能正在阻止流量。当远程集群无法访问时,请检查本地集群的日志以查找connect_exception

当远程集群使用代理模式配置时:

[2023-06-28T16:36:47,264][WARN ][o.e.t.ProxyConnectionStrategy] [local-node] failed to open any proxy connections to cluster [my]
org.elasticsearch.transport.ConnectTransportException: [][192.168.0.42:9443] connect_exception

当远程集群使用嗅探模式配置时:

[2023-06-28T16:38:37,731][WARN ][o.e.t.SniffConnectionStrategy] [local-node] fetching nodes from external cluster [my] failed
org.elasticsearch.transport.ConnectTransportException: [][192.168.0.42:9443] connect_exception
分辨率
edit

远程集群连接不可靠

edit
症状
edit

本地集群可以连接到远程集群,但连接并不稳定。例如,某些跨集群请求可能会成功,而其他请求则报告连接错误、超时或似乎在等待远程集群响应时卡住。

当Elasticsearch检测到远程集群连接不可用时,它将在其日志中报告以下消息:

[2023-06-28T16:36:47,264][INFO ][o.e.t.ClusterConnectionManager] [local-node] transport connection to [{my-remote#192.168.0.42:9443}{...}] closed by remote

如果Elasticsearch连接的远程集群节点关闭或重启,此消息也会被记录。

请注意,在某些网络配置下,操作系统可能需要几分钟或几小时才能检测到连接已停止工作。在故障被检测到并报告给Elasticsearch之前,涉及远程集群的请求可能会超时或看起来卡住。

分辨率
edit
  • 确保集群之间的网络尽可能可靠。
  • 确保网络配置为允许长连接
  • 确保网络配置为能够快速检测故障连接。 特别是,您必须启用并完全支持TCP keepalives,并设置一个 短的重传超时
  • 在Linux系统上,执行ss -tonie以验证集群之间每个网络连接的配置细节。
  • 如果问题仍然存在,捕获连接两端的网络数据包并分析流量以查找延迟和丢失的消息。

未建立TLS信任

edit

TLS 可能在本地或远程集群上配置错误。结果是本地集群不信任远程集群提供的证书。

症状
edit

本地集群日志显示 未能与服务器建立信任

[2023-06-29T09:40:55,465][WARN ][o.e.c.s.DiagnosticTrustManager] [local-node] failed to establish trust with server at [192.168.0.42]; the server provided a certificate with subject name [CN=remote_cluster], fingerprint [529de35e15666ffaa26afa50876a2a48119db03a], no keyUsage and no extendedKeyUsage; the certificate is valid between [2023-01-29T12:08:37Z] and [2032-08-29T12:08:37Z] (current time is [2023-08-16T23:40:55.464275Z], certificate dates are valid); the session uses cipher suite [TLS_AES_256_GCM_SHA384] and protocol [TLSv1.3]; the certificate has subject alternative names [DNS:localhost,DNS:localhost6.localdomain6,IP:127.0.0.1,IP:0:0:0:0:0:0:0:1,DNS:localhost4,DNS:localhost6,DNS:localhost.localdomain,DNS:localhost4.localdomain4,IP:192.168.0.42]; the certificate is issued by [CN=Elastic Auto RemoteCluster CA] but the server did not provide a copy of the issuing certificate in the certificate chain; this ssl context ([(shared) (with trust configuration: JDK-trusted-certs)]) is not configured to trust that issuer but trusts [97] other issuers
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

远程集群日志显示 客户端不信任此服务器的证书

[2023-06-29T09:40:55,478][WARN ][o.e.x.c.s.t.n.SecurityNetty4Transport] [remote-node] client did not trust this server's certificate, closing connection Netty4TcpChannel{localAddress=/192.168.0.42:9443, remoteAddress=/192.168.0.84:57305, profile=_remote_cluster}
分辨率
edit

仔细阅读本地集群上的警告日志信息,以确定故障的确切原因。例如:

  • 远程集群证书是否未由受信任的CA签名?这是最有可能的原因。
  • 主机名验证是否失败?
  • 证书是否已过期?

一旦你知道了原因,你应该能够通过调整本地集群或远程集群上的远程集群相关SSL设置来修复它。

通常,问题出在本地集群上。例如,通过配置必要的受信任CA(xpack.security.remote_cluster_client.ssl.certificate_authorities)来解决。

如果您更改了elasticsearch.yml文件,关联的集群需要重新启动以使更改生效。

API 密钥认证问题

edit

使用API密钥认证时连接到传输端口

edit

当使用API密钥认证时,本地集群应连接到远程集群的远程集群服务器端口(默认为9443),而不是传输端口(默认为9300)。配置错误可能导致多种症状:

症状 1
edit

建议为传输接口和远程集群服务器接口使用不同的CA和证书。如果遵循此建议,远程集群客户端节点将不信任在传输接口上由远程集群提供的证书。

本地集群日志显示未能与服务器建立信任

[2023-06-28T12:48:46,575][WARN ][o.e.c.s.DiagnosticTrustManager] [local-node] failed to establish trust with server at [1192.168.0.42]; the server provided a certificate with subject name [CN=transport], fingerprint [c43e628be2a8aaaa4092b82d78f2bc206c492322], no keyUsage and no extendedKeyUsage; the certificate is valid between [2023-01-29T12:05:53Z] and [2032-08-29T12:05:53Z] (current time is [2023-06-28T02:48:46.574738Z], certificate dates are valid); the session uses cipher suite [TLS_AES_256_GCM_SHA384] and protocol [TLSv1.3]; the certificate has subject alternative names [DNS:localhost,DNS:localhost6.localdomain6,IP:127.0.0.1,IP:0:0:0:0:0:0:0:1,DNS:localhost4,DNS:localhost6,DNS:localhost.localdomain,DNS:localhost4.localdomain4,IP:192.168.0.42]; the certificate is issued by [CN=Elastic Auto Transport CA] but the server did not provide a copy of the issuing certificate in the certificate chain; this ssl context ([xpack.security.remote_cluster_client.ssl (with trust configuration: PEM-trust{/rcs2/ssl/remote-cluster-ca.crt})]) is not configured to trust that issuer, it only trusts the issuer [CN=Elastic Auto RemoteCluster CA] with fingerprint [ba2350661f66e46c746c1629f0c4b645a2587ff4]
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

远程集群日志显示 客户端不信任此服务器的证书

[2023-06-28T12:48:46,584][WARN ][o.e.x.c.s.t.n.SecurityNetty4Transport] [remote-node] client did not trust this server's certificate, closing connection Netty4TcpChannel{localAddress=/192.168.0.42:9309, remoteAddress=/192.168.0.84:60810, profile=default}
症状 2
edit

CA和证书可以在传输和远程集群服务器接口之间共享。由于远程集群客户端默认没有客户端证书,服务器将无法验证客户端证书。

本地集群日志显示 Received fatal alert: bad_certificate

[2023-06-28T12:43:30,705][WARN ][o.e.t.TcpTransport       ] [local-node] exception caught on transport layer [Netty4TcpChannel{localAddress=/192.168.0.84:60738, remoteAddress=/192.168.0.42:9309, profile=_remote_cluster}], closing connection
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

远程集群日志显示 空的客户端证书链

[2023-06-28T12:43:30,772][WARN ][o.e.t.TcpTransport       ] [remote-node] exception caught on transport layer [Netty4TcpChannel{localAddress=/192.168.0.42:9309, remoteAddress=/192.168.0.84:60783, profile=default}], closing connection
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Empty client certificate chain
症状 3
edit

如果远程集群客户端配置为mTLS并提供有效的客户端证书,连接将失败,因为客户端没有发送预期的身份验证头。

本地集群日志显示缺少身份验证

[2023-06-28T13:04:52,710][WARN ][o.e.t.ProxyConnectionStrategy] [local-node] failed to open any proxy connections to cluster [my]
org.elasticsearch.transport.RemoteTransportException: [remote-node][192.168.0.42:9309][cluster:internal/remote_cluster/handshake]
Caused by: org.elasticsearch.ElasticsearchSecurityException: missing authentication credentials for action [cluster:internal/remote_cluster/handshake]

这不会显示在远程集群的日志中。

症状 4
edit

如果远程集群启用了匿名访问且不需要身份验证,根据匿名用户的权限,本地集群可能会记录以下内容。

如果匿名用户没有建立连接所需的必要权限,本地集群会记录未授权

org.elasticsearch.transport.RemoteTransportException: [remote-node][192.168.0.42:9309][cluster:internal/remote_cluster/handshake]
Caused by: org.elasticsearch.ElasticsearchSecurityException: action [cluster:internal/remote_cluster/handshake] is unauthorized for user [anonymous_foo] with effective roles [reporting_user], this action is granted by the cluster privileges [cross_cluster_search,cross_cluster_replication,manage,all]

如果匿名用户具有必要的权限,例如它是超级用户,本地集群会记录需要通道配置为[_remote_cluster],但得到的是[default]

[2023-06-28T13:09:52,031][WARN ][o.e.t.ProxyConnectionStrategy] [local-node] failed to open any proxy connections to cluster [my]
org.elasticsearch.transport.RemoteTransportException: [remote-node][192.168.0.42:9309][cluster:internal/remote_cluster/handshake]
Caused by: java.lang.IllegalArgumentException: remote cluster handshake action requires channel profile to be [_remote_cluster], but got [default]
分辨率
edit

检查端口号,并确保您确实连接到远程集群服务器,而不是传输接口。

在没有跨集群API密钥的情况下进行连接

edit

本地集群使用跨集群 API 密钥的存在来确定它连接到远程集群的模型。如果存在跨集群 API 密钥,则使用基于 API 密钥的身份验证。否则,它使用基于证书的身份验证。您可以在本地集群上使用 远程集群信息 API 检查正在使用的模型:

GET /_remote/info

API 应返回 "connected" : true。当使用 API 密钥认证时,还应返回 "cluster_credentials": "::es_redacted::"

{
  "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" : false,
    "cluster_credentials": "::es_redacted::", 
    "mode" : "sniff"
  }
}

远程集群已成功连接。

如果存在,表示远程集群已使用 API密钥认证 而不是 基于证书的认证 进行连接。

除了检查远程集群信息API的响应外,您还可以检查日志。

症状 1
edit

如果没有使用跨集群API密钥,本地集群将使用基于证书的身份验证方法,并通过传输接口的TLS配置连接到远程集群。如果远程集群的传输和远程集群服务器接口使用不同的TLS CA和证书(这是推荐的做法),TLS验证将会失败。

本地集群日志显示 未能与服务器建立信任

[2023-06-28T12:51:06,452][WARN ][o.e.c.s.DiagnosticTrustManager] [local-node] failed to establish trust with server at [<unknown host>]; the server provided a certificate with subject name [CN=remote_cluster], fingerprint [529de35e15666ffaa26afa50876a2a48119db03a], no keyUsage and no extendedKeyUsage; the certificate is valid between [2023-01-29T12:08:37Z] and [2032-08-29T12:08:37Z] (current time is [2023-06-28T02:51:06.451581Z], certificate dates are valid); the session uses cipher suite [TLS_AES_256_GCM_SHA384] and protocol [TLSv1.3]; the certificate has subject alternative names [DNS:localhost,DNS:localhost6.localdomain6,IP:127.0.0.1,IP:0:0:0:0:0:0:0:1,DNS:localhost4,DNS:localhost6,DNS:localhost.localdomain,DNS:localhost4.localdomain4,IP:192.168.0.42]; the certificate is issued by [CN=Elastic Auto RemoteCluster CA] but the server did not provide a copy of the issuing certificate in the certificate chain; this ssl context ([xpack.security.transport.ssl (with trust configuration: PEM-trust{/rcs2/ssl/transport-ca.crt})]) is not configured to trust that issuer, it only trusts the issuer [CN=Elastic Auto Transport CA] with fingerprint [bbe49e3f986506008a70ab651b188c70df104812]
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

远程集群日志显示 客户端不信任此服务器的证书

[2023-06-28T12:52:16,914][WARN ][o.e.x.c.s.t.n.SecurityNetty4Transport] [remote-node] client did not trust this server's certificate, closing connection Netty4TcpChannel{localAddress=/192.168.0.42:9443, remoteAddress=/192.168.0.84:60981, profile=_remote_cluster}
症状 2
edit

即使TLS验证不是问题,由于缺少凭据,连接也会失败。

本地集群日志 请确保您已配置远程集群凭据

Caused by: java.lang.IllegalArgumentException: Cross cluster requests through the dedicated remote cluster server port require transport header [_cross_cluster_access_credentials] but none found. Please ensure you have configured remote cluster credentials on the cluster originating the request.

这不会显示在远程集群的日志中。

分辨率
edit

将跨集群API密钥添加到本地集群中每个节点的Elasticsearch密钥库中。使用节点重新加载安全设置API重新加载密钥库。

使用错误的API密钥类型

edit

基于API密钥的身份验证需要 跨集群API密钥。它不适用于REST API密钥

症状
edit

本地集群日志 预期的 API 密钥类型为 [cross_cluster]

[2023-06-28T13:26:53,962][WARN ][o.e.t.ProxyConnectionStrategy] [local-node] failed to open any proxy connections to cluster [my]
org.elasticsearch.transport.RemoteTransportException: [remote-node][192.168.0.42:9443][cluster:internal/remote_cluster/handshake]
Caused by: org.elasticsearch.ElasticsearchSecurityException: authentication expected API key type of [cross_cluster], but API key [agZXJocBmA2beJfq2yKu] has type [rest]

这不会显示在远程集群的日志中。

分辨率
edit

请远程集群管理员创建并分发一个 跨集群 API 密钥。将 Elasticsearch 密钥库中的现有 API 密钥替换为本地集群中每个节点上的这个跨集群 API 密钥。使用 节点重新加载安全设置 API 来重新加载密钥库。

无效的API密钥

edit

跨集群API可能无法进行身份验证。例如,当其凭据不正确,或者如果它被无效化或过期时。

症状
edit

本地集群日志显示无法进行身份验证

[2023-06-28T13:22:58,264][WARN ][o.e.t.ProxyConnectionStrategy] [local-node] failed to open any proxy connections to cluster [my]
org.elasticsearch.transport.RemoteTransportException: [remote-node][192.168.0.42:9443][cluster:internal/remote_cluster/handshake]
Caused by: org.elasticsearch.ElasticsearchSecurityException: unable to authenticate user [agZXJocBmA2beJfq2yKu] for action [cluster:internal/remote_cluster/handshake]

远程集群日志显示 使用apikey进行身份验证失败

[2023-06-28T13:24:38,744][WARN ][o.e.x.s.a.ApiKeyAuthenticator] [remote-node] Authentication using apikey failed - invalid credentials for API key [agZXJocBmA2beJfq2yKu]
分辨率
edit

请远程集群管理员创建并分发一个 跨集群 API 密钥。将 Elasticsearch 密钥库中的现有 API 密钥替换为本地集群中每个节点上的这个跨集群 API 密钥。使用 节点重新加载安全设置 API 来重新加载密钥库。

API 密钥或本地用户权限不足

edit

本地用户在远程集群上运行请求的有效权限由跨集群API密钥的权限与本地用户的remote_indices权限的交集决定。

症状
edit

由于权限不足导致的请求失败会返回类似以下的API响应:

{
    "type": "security_exception",
    "reason": "action [indices:data/read/search] towards remote cluster is unauthorized for user [foo] with assigned roles [foo-role] authenticated by API key id [agZXJocBmA2beJfq2yKu] of user [elastic-admin] on indices [cd], this action is granted by the index privileges [read,all]"
}

这不会显示在任何日志中。

分辨率
edit
  1. 检查本地用户是否具有必要的remote_indices权限。如果需要,授予足够的remote_indices权限。
  2. 如果本地权限没有问题,请要求远程集群管理员创建并分发一个 跨集群API密钥。将本地集群中每个节点上的Elasticsearch密钥库中的现有API密钥替换为这个跨集群API密钥。使用节点重新加载安全设置API来重新加载密钥库。

本地用户没有remote_indices权限

edit

这是一个权限不足的特殊情况。在这种情况下,本地用户对目标远程集群完全没有remote_indices权限。Elasticsearch可以检测到这一点,并发出更明确的错误响应。

症状
edit

这将导致API响应如下:

{
    "type": "security_exception",
    "reason": "action [indices:data/read/search] towards remote cluster [my] is unauthorized for user [foo] with effective roles [] (assigned roles [foo-role] were not found) because no remote indices privileges apply for the target cluster"
}
分辨率
edit

授予本地用户足够的remote_indices权限。