﻿---
title: Connect to Elasticsearch clusters in a different Elastic Cloud on Kubernetes environment
description: These steps describe how to configure a remote cluster connection between Elasticsearch clusters handled by different Elastic Cloud on Kubernetes (ECK)...
url: https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/eck-remote-clusters-to-other-eck
products:
  - Elastic Cloud on Kubernetes
applies_to:
  - Elastic Cloud on Kubernetes: Generally available
---

# Connect to Elasticsearch clusters in a different Elastic Cloud on Kubernetes environment
These steps describe how to configure a remote cluster connection between Elasticsearch clusters handled by different Elastic Cloud on Kubernetes (ECK) operators.
After the connection is established, you’ll be able to [run CCS queries from Elasticsearch](https://www.elastic.co/elastic/docs-builder/docs/3016/explore-analyze/cross-cluster-search) or [set up CCR](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/tools/cross-cluster-replication/set-up-cross-cluster-replication).
<admonition title="Note about terminology">
  In the case of remote clusters, the Elasticsearch cluster or deployment initiating the connection and requests is often referred to as the **local cluster**, while the Elasticsearch cluster or deployment receiving the requests is referred to as the **remote cluster**.
</admonition>

In this scenario, most of the configuration must be performed manually, as Elastic Cloud on Kubernetes cannot orchestrate the setup across both clusters. For fully automated configuration between ECK-managed clusters, refer to [Connect to Elasticsearch clusters in the same ECK environment](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/eck-remote-clusters).
For other remote cluster scenarios with ECK, refer to [Remote clusters on ECK](/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/eck-remote-clusters-landing#eck-rcs-setup).

## Allow the remote connection

Before you start, consider the [security model](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/security-models) that you would prefer to use for authenticating remote connections between clusters, and follow the corresponding steps.
<definitions>
  <definition term="API key">
    For deployments based on Elastic Stack 8.14 or later, you can use an API key to authenticate and authorize cross-cluster operations to a remote cluster. This model uses a dedicated service endpoint, on port `9443` by default, and gives administrators fine-grained control over remote access. The API key is created on the remote cluster and defines the permissions available to all cross-cluster requests, while local user roles can further restrict, but not extend, those permissions.
    Starting with Elastic Stack 9.3, the API key security model also supports [strong identity verification](/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/security-models#remote-cluster-strong-verification), adding an extra layer of security. With this feature, the API key can be restricted to only be usable by requests that present an allowed certificate identity, which the remote cluster validates during authentication.
  </definition>
  <definition term="TLS certificate (deprecated in Elastic Stack 9.0.0)">
    This model uses mutual TLS authentication over the Elasticsearch transport interface for cross-cluster operations. User authentication is performed on the local cluster and a user's role names are passed to the remote cluster for authorization. Because a superuser on the local cluster automatically gains full read access to the remote cluster, this model is only suitable for clusters within the same security domain.
  </definition>
</definitions>

<tab-set>
  <tab-item title="API key">
    Follow these steps to configure the [API key security model](/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/security-models#api-key) for remote clusters. If you run into any issues, refer to [Troubleshooting](https://www.elastic.co/elastic/docs-builder/docs/3016/troubleshoot/elasticsearch/remote-clusters).

    #### Prerequisites and limitations

    - The local and remote deployments must be on Elastic Stack 8.14 or later.
    - Unlike the certificate-based security model, the API key model does not require mutual trust between clusters; only the local cluster is required to trust the remote cluster's certificate.


    #### Enable the remote cluster server interface on the remote ECK cluster

    By default, the remote cluster server interface is not enabled on ECK-managed clusters. To use the API key–based security model for cross-cluster connections, you must first enable it on the remote Elasticsearch cluster by setting `spec.remoteClusterServer.enabled: true`:
    ```yaml
    apiVersion: elasticsearch.k8s.elastic.co/v1
    kind: Elasticsearch
    metadata:
      name: <cluster-name>
      namespace: <namespace>
    spec:
      version: 9.3.2
      remoteClusterServer:
        enabled: true
      nodeSets:
        - name: default
          count: 3
          ...
          ...
    ```

    <note>
      Enabling the remote cluster server triggers a restart of the Elasticsearch cluster.
    </note>


    #### Configure external access to the remote cluster server interface

    When the remote cluster server is enabled, ECK automatically creates a Kubernetes service named `<cluster-name>-es-remote-cluster` that exposes the server internally on port `9443`.
    To allow clusters running outside your Kubernetes environment to connect to this Elasticsearch cluster, you must expose this service externally. The way to expose this service depends on your ECK version.
    <applies-switch>
      <applies-item title="eck: ga 3.3" applies-to="Elastic Cloud on Kubernetes: Generally available since 3.3">
        You can customize how the remote cluster service is exposed by overriding its service specification directly under `spec.remoteClusterServer.service` in the Elasticsearch resource. By default, this service listens on port 9443.
        ```yaml
        apiVersion: elasticsearch.k8s.elastic.co/v1
        kind: Elasticsearch
        metadata:
          name: <cluster-name>
          namespace: <namespace>
        spec:
          version: 9.2.1
          remoteClusterServer:
            enabled: true
            service:
              spec:
                type: LoadBalancer 
          nodeSets:
            - name: default
              count: 3
              ...
              ...
        ```

        1. On cloud providers that support external load balancers, setting the type to `LoadBalancer` provisions a load balancer for your service. Alternatively, expose the service `<cluster-name>-es-remote-cluster` through one of the Kubernetes Ingress controllers that support TCP services.
      </applies-item>

      <applies-item title="eck: ga 3.0-3.2" applies-to="Elastic Cloud on Kubernetes: Generally available from 3.0 to 3.2">
        You can't customize the service that ECK generates for the remote cluster interface, but you can create your own `LoadBalancer` service, `Ingress` object, or use another method available in your environment.For example, for a cluster named `quickstart`, the following command creates a separate `LoadBalancer` service named `quickstart-es-remote-cluster-lb`, pointing to the ECK-managed service `quickstart-es-remote-cluster`:
        ```sh
        kubectl expose service quickstart-es-remote-cluster \
          --name=quickstart-es-remote-cluster-lb \
          --type=LoadBalancer \ 
          --port=9443 --target-port=9443
        ```

        1. On cloud providers that support external load balancers, setting the type to `LoadBalancer` provisions a load balancer for your service. Alternatively, expose the service `<cluster-name>-es-remote-cluster` through one of the Kubernetes Ingress controllers that support TCP services.
      </applies-item>
    </applies-switch>

    <warning>
      If you change the service’s `port` to expose a different port externally, set `targetPort` explicitly to `9443`, which is the default remote cluster server listening port. Otherwise, Kubernetes uses the same value for both fields, resulting in failed connections.
    </warning>


    #### Retrieve the ECK-managed CA certificate of the remote cluster server

    The certificate authority (CA) used by ECK to issue certificates for the remote cluster server interface is stored in the `ca.crt` key of the secret named `<cluster_name>-es-transport-certs-public`.
    If the external connections reach the Elasticsearch Pods on port `9443` without any intermediate TLS termination, you need to retrieve this CA because it is required in the local cluster configuration to establish trust.
    If TLS is terminated by any intermediate component and the certificate presented is not the ECK-managed one, use the CA associated with that component, or omit the CA entirely if it uses a publicly trusted certificate.
    To save the transport CA certificate of a cluster named `quickstart` into a local file, run the following command:
    ```sh
    kubectl get secret quickstart-es-transport-certs-public \
    -o go-template='{{index .data "ca.crt" | base64decode}}' > eck_transport_ca.crt
    ```

    <important>
      ECK-managed CA certificates are automatically rotated after one year by default, but you can [configure](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/deploy/cloud-on-k8s/configure-eck) a different validity period. When the CA certificate is rotated, ensure that this CA is updated in all environments where it's used to preserve trust.
    </important>


    #### Create a cross-cluster API key on the remote cluster

    1. On the remote cluster, use the [Elasticsearch API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-security-create-cross-cluster-api-key) or [Kibana](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/api-keys/elasticsearch-api-keys) to create a cross-cluster API key. Configure it to include access to the indices you want to use for cross-cluster search or cross-cluster replication.
    2. Copy the encoded key (`encoded` in the response) to a safe location. It is required for the local cluster configuration.


    #### Configure the local deployment

    The API key created previously is needed by the local cluster to authenticate with the corresponding set of permissions to the remote deployment or cluster. To enable this, add the API key to the local cluster's keystore.The steps to follow depend on whether the certificate authority (CA) presented by the remote cluster server, proxy, or load-balancing infrastructure is publicly trusted or private.
    <dropdown title="The CA is public">
      1. **Store the API key encoded value in a Secret**
         The following command creates a secret containing the encoded API key obtained earlier:
         ```sh
         cat <<EOF | kubectl apply -f -
         apiVersion: v1
         kind: Secret
         metadata:
         name: remote-api-keys
         type: Opaque
         stringData:
         cluster.remote.<remote-cluster-name>.credentials: <encoded value> 
         EOF
         ```

         1. For the `<remote-cluster-name>`, enter the alias of your choice. This alias is used when connecting to the remote cluster. It must be lowercase and only contain letters, numbers, dashes, and underscores.
      2. **Configure the Elasticsearch resource**
         Update the Elasticsearch manifest to:
         - Load the API key from the previously created secret using [`secureSettings`](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/security/k8s-secure-settings)
      - Enable the remote cluster SSL client in the `config` section of each `nodeSet`
         ```yaml
         apiVersion: elasticsearch.k8s.elastic.co/v1
         kind: Elasticsearch
         metadata:
           name: <local-cluster-name>
         spec:
           version: 9.3.2
           secureSettings:
             - secretName: remote-api-keys 
           nodeSets:
             - name: default
               count: 3
               config:
                 xpack:
                   security:
                     remote_cluster_client:
                       ssl:
                         enabled: true 
         ```
    </dropdown>

    <dropdown title="The CA is private">
      1. **Store the API key encoded value in a Secret**
         The following command creates a secret containing the encoded API key obtained earlier:
         ```sh
         cat <<EOF | kubectl apply -f -
         apiVersion: v1
         kind: Secret
         metadata:
         name: remote-api-keys
         type: Opaque
         stringData:
         cluster.remote.<remote-cluster-name>.credentials: <encoded value> 
         EOF
         ```

         1. For the `<remote-cluster-name>`, enter the alias of your choice. This alias is used when connecting to the remote cluster. It must be lowercase and only contain letters, numbers, dashes, and underscores.
      2. **Store the CA certificate in a ConfigMap or Secret**
         Store the CA certificate [retrieved earlier](#enable-rcs) in a ConfigMap or Secret. The following example creates a ConfigMap named `remote-ca` that stores the content of a local file (`my-ca.crt`) under the `remote-cluster-ca.crt` key:
         ```sh
         kubectl create configmap remote-ca -n <namespace> --from-file=remote-cluster-ca.crt=my-ca.crt
         ```
      3. **Configure the Elasticsearch resource**
         Update the Elasticsearch manifest to:
         - Load the API key from the previously created secret using [`secureSettings`](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/security/k8s-secure-settings)
      - Mount the CA certificate from the previously created ConfigMap [as a custom file](/elastic/docs-builder/docs/3016/deploy-manage/deploy/cloud-on-k8s/custom-configuration-files-plugins#use-a-volume-and-volume-mount-together-with-a-configmap-or-secret) in the Elasticsearch Pods
      - Enable and configure the remote cluster SSL client in the `config` section of each `nodeSet`
         ```yaml
         apiVersion: elasticsearch.k8s.elastic.co/v1
         kind: Elasticsearch
         metadata:
           name: <local-cluster-name>
         spec:
           version: 9.3.2
           secureSettings:
             - secretName: remote-api-keys
           nodeSets: 
             - name: default
               count: 3
               config:
                 xpack:
                   security:
                     remote_cluster_client:
                       ssl:
                         enabled: true
                         certificate_authorities: [ "remote-certs/remote-cluster-ca.crt" ] 
               podTemplate:
                 spec:
                   containers:
                   - name: elasticsearch
                     volumeMounts:
                     - name: remote-ca
                       mountPath: /usr/share/elasticsearch/config/remote-certs
                   volumes:
                   - name: remote-ca
                     configMap:
                       name: remote-ca 
         ```
    </dropdown>
  </tab-item>

  <tab-item title="TLS certificate (deprecated)">
    Follow these steps to configure the [TLS certificate security model](/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/security-models#tls-certificate-authentication) for remote clusters. If you run into any issues, refer to [Troubleshooting](https://www.elastic.co/elastic/docs-builder/docs/3016/troubleshoot/elasticsearch/remote-clusters).

    #### Make sure both clusters trust each other's certificate authority

    When using TLS certificate–based authentication, the first step is to establish mutual trust between the clusters at the transport layer. This requires exchanging and trusting each cluster's transport certificate authority (CA):
    - The transport CA of the remote cluster must be added as a trusted CA in the local cluster.
    - The local cluster’s transport CA must be added as a trusted CA in the remote cluster.
    The following steps assume that the local and remote clusters are handled by different ECK installations.
    1. Extract and save the transport CAs of both clusters:
       ECK stores the CA used to issue certificates for the Elasticsearch transport layer in a secret named `<cluster_name>-es-transport-certs-public`.
       For example, to save the transport CA certificate of a cluster named `quickstart` into a local file, run the following command:
       ```sh
       kubectl get secret quickstart-es-transport-certs-public \
       -o go-template='{{index .data "ca.crt" | base64decode}}' > quickstart_transport_ca.crt
       ```

       <note>
       Beware of copying the source secret as-is into a different namespace. Refer to [Copying secrets with Owner References](/elastic/docs-builder/docs/3016/troubleshoot/deployments/cloud-on-k8s/common-problems#k8s-common-problems-owner-refs) for more information.
       </note>

       <note>
       CA certificates are automatically rotated after one year by default. You can [configure](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/deploy/cloud-on-k8s/configure-eck) this period. Make sure to keep the copy of the certificates secret up-to-date.
       </note>
    2. Configure the local cluster to trust the transport CA of the remote cluster:
       1. In the Kubernetes cluster and namespace where the local cluster is running, create a config map with the CA certificate of the remote cluster you extracted previously:
       ```sh
       kubectl create configmap remote-certs --from-file=ca.crt=<quickstart_transport_ca.crt> 
       ```
    2. Configure the Elasticsearch resource manifest to trust the previous config map through the `spec.transport.tls.certificate_authorities` setting:
       ```yaml
       apiVersion: elasticsearch.k8s.elastic.co/v1
       kind: Elasticsearch
       metadata:
         name: <local-cluster-name>
       spec:
         version: 9.3.2
         transport:
           tls:
             certificateAuthorities:
               configMapName: remote-certs
         nodeSets:
         - count: 3
           name: default
       ```
    3. Repeat the previous step for the remote cluster to trust the CA of the local cluster.


    #### Configure external access to the transport interface of the remote cluster

    Expose the transport service (defaults to port `9300`) of your ECK cluster to allow external Elasticsearch clusters to connect:
    ```yaml
    apiVersion: elasticsearch.k8s.elastic.co/v1
    kind: Elasticsearch
    metadata:
      name: <remote-cluster-name>
    spec:
      transport:
        service:
          spec:
            type: LoadBalancer 
    ```

    1. On cloud providers which support external load balancers, setting the `type` field to `LoadBalancer` provisions a load balancer for your service. Alternatively, expose the service `<cluster-name>-es-transport` through one of the Kubernetes Ingress controllers that support TCP services.

    <note>
      If you change the service’s `port` to expose a different port externally, set `targetPort` explicitly to `9300`, which is the default transport service listening port. Otherwise, Kubernetes uses the same value for both fields, resulting in failed connections.
    </note>
  </tab-item>
</tab-set>


## Connect to the remote cluster

On the local cluster, use Kibana or the Elasticsearch API to add the remote ECK cluster with the following connection settings:
- **Remote address**: Use the FQDN or IP address of the LoadBalancer service or alternative resource that you created to expose the remote cluster.
  - For API key-based authentication, use the server interface address and port.
- For TLS certificate-based authentication, use the transport interface address and port.
  If you haven't changed the external listening port of the kubernetes service, the port should be `9443` for API key-based authentication, or `9300` for TLS certificate-based authentication.
- **TLS server name**: You can try leaving this field empty first. If the connection fails, and your environment is presenting the ECK-managed certificates during the TLS handshake, use `<cluster-name>-es-remote-cluster.<namespace>.svc` as the server name. For example, for a cluster named `quickstart` in the `default` namespace, use `quickstart-es-remote-cluster.default.svc`.

<admonition title="About connection modes">
  This guide uses the `proxy` connection mode, connecting to the remote cluster through the Kubernetes service abstraction.If the remote cluster resides in the same Kubernetes cluster as the local cluster, and if the local cluster can reach the remote nodes’ publish addresses directly, you can use `sniff` mode instead. Refer to [connection modes](https://www.elastic.co/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/connection-modes) documentation for details on each mode and their connectivity requirements.
</admonition>


### Using Kibana

To add a remote cluster in Kibana:
1. Go to the **Remote Clusters** management page in the navigation menu or use the [global search field](https://www.elastic.co/elastic/docs-builder/docs/3016/explore-analyze/find-and-organize/find-apps-and-objects).
2. Select **Add a remote cluster**.
3. In **Select connection type**, choose the authentication mechanism you prepared earlier (**API keys** or **Certificates**), and click **Next**.
4. Set the **Remote cluster name**: This *cluster alias* is a unique identifier that represents the connection to the remote cluster and is used to distinguish local and remote indices.
   When using API key authentication, this alias must match the **Remote cluster name** you configured when [adding the API key](#configure-local-cluster).
5. In **Connection mode**, select **Manually enter proxy address and server name** to enable the proxy mode and fill in the following fields:
   - **Proxy address**: Enter the endpoint of the remote cluster, including the hostname, FQDN, or IP address, and the port:
  Make sure you use the correct port for your authentication method:
  - **API keys**: Use the port configured in the remote cluster interface of the remote cluster (defaults to `9443`).
- **TLS certificates**: Use the Elasticsearch transport port (defaults to `9300`).
  Starting with Kibana 9.2, this field also supports IPv6 addresses. When using an IPv6 address, enclose it in square brackets followed by the port number. For example: `[2001:db8::1]:9443`.
- **Server name (optional)**: Specify a value if the TLS certificate presented by the remote cluster is signed for a different name than the remote address.
6. Click **Next**.
7. In **Confirm setup**, click **Add remote cluster** (you have already established trust in a previous step).


### Using the Elasticsearch API

To add a remote cluster, use the [cluster update settings API](https://www.elastic.co/docs/api/doc/elasticsearch/operation/operation-cluster-put-settings). Configure the following fields:
- **Remote cluster alias**: When using API key authentication, the cluster alias must match the one you configured when [adding the API key](#configure-local-cluster).
- **mode**: `proxy`
- **proxy_address**: Enter the endpoint of the remote cluster, including the hostname, FQDN, or IP address, and the port. Both IPv4 and IPv6 addresses are supported.
  Make sure you use the correct port for your authentication method:
  - **API keys**: Use the port configured in the remote cluster interface of the remote cluster (defaults to `9443`).
- **TLS Certificates**: Use the Elasticsearch transport port (defaults to `9300`).
  When using an IPv6 address, enclose it in square brackets followed by the port number. For example: `[2001:db8::1]:9443`.
- **server_name**: Specify a value if the certificate presented by the remote cluster is signed for a different name than the proxy_address.

This is an example of the API call to add or update a remote cluster:
```json
PUT /_cluster/settings
{
  "persistent": {
    "cluster": {
      "remote": {
        "alias-for-my-remote-cluster": {
          "mode":"proxy",
          "proxy_address": "<REMOTE_CLUSTER_ADDRESS>:9443",
          "server_name": "<REMOTE_CLUSTER_SERVER_NAME>"
        }
      }
    }
  }
}
```

For a full list of available client connection settings in proxy mode, refer to the [remote cluster settings reference](https://docs-v3-preview.elastic.dev/elastic/docs-builder/docs/3016/reference/elasticsearch/configuration-reference/remote-clusters#remote-cluster-proxy-settings).

## Verify remote cluster connection

From the local cluster, check the status of the connection to the remote cluster. If you encounter issues, refer to the [Troubleshooting guide](https://www.elastic.co/elastic/docs-builder/docs/3016/troubleshoot/elasticsearch/remote-clusters).
```json
```

In the response, verify that connected is `true`:
```
{
  "<remote-alias>": {
    "connected": true,
    "mode": "proxy",
    "proxy_address": "<REMOTE_CLUSTER_ADDRESS>:9443",
    "server_name": "<REMOTE_CLUSTER_SERVER_NAME>",
    "num_proxy_sockets_connected": 18,
    "max_proxy_socket_connections": 18,
    "initial_connect_timeout": "30s",
    "skip_unavailable": true,
    "cluster_credentials": "::es_redacted::"
  }
}
```


## Configure roles and users

If you're using the API key–based security model for cross-cluster replication or cross-cluster search, you can define user roles with [remote indices privileges](/elastic/docs-builder/docs/3016/deploy-manage/users-roles/cluster-or-deployment-auth/role-structure#roles-remote-indices-priv) on the local cluster to further restrict the permissions granted by the API key. For more details, refer to [Configure roles and users](/elastic/docs-builder/docs/3016/deploy-manage/remote-clusters/remote-clusters-api-key#remote-clusters-privileges-api-key).