[Yandex Cloud documentation](../../index.md) > [Yandex Managed Service for Apache Kafka®](../index.md) > [Step-by-step guides](index.md) > Clusters > Migrating hosts to a different availability zone

# Migrating Apache Kafka® cluster hosts to a different availability zone


Managed Service for Apache Kafka® cluster hosts reside in Yandex Cloud availability zones. You can move Apache Kafka® hosts from one availability zone to another. The migration process is different for single-host and multi-host clusters.

{% note info %}

Clusters with hosts residing in the `ru-central1-d` [availability zone](../../overview/concepts/geo-scope.md) do not support:

- Intel Broadwell
- Local SSD storage if using Intel Cascade Lake

{% endnote %}

If a Managed Service for Apache Kafka® cluster is an endpoint in Yandex Data Transfer, restart the transfer to make it work correctly. For more information on which transfers to restart and how to do it, see [Specifics of migration in Yandex Data Transfer](#data-transfer).

## Migrating a single-host cluster {#one-host}

You can migrate your cluster in the following ways:

* [Use the Yandex Cloud interfaces](#yandex-cloud-interfaces). In this case, the availability zone in the cluster configuration will change. You do not need to create an additional cluster.

   This option is easier to implement; however, the cluster will remain idle during migration while changing its availability zone. This may take a few minutes.

* [Use auxiliary tools](#auxiliary-instruments) offered by MirrorMaker or Yandex Data Transfer. In this case, you need to create a new cluster and transfer data from the source cluster into it.

   This option is more challenging to implement since it requires building and configuring the infrastructure. However, it allows you to avoid downtime: you can maintain two clusters with up-to-date data until you delete the source one.

### Migrating a single-host cluster using Yandex Cloud interfaces {#yandex-cloud-interfaces}

To move an Apache Kafka® host to a different availability zone in a Managed Service for Apache Kafka® cluster:

1. [Create a subnet](../../vpc/operations/subnet-create.md) in the target availability zone.
1. If the cluster security group is set up for a subnet in the availability zone you are moving your cluster from, reconfigure the group for the new subnet. To do so, replace the source subnet CIDR with the new subnet CIDR in the security group rules.
1. Change the availability zone of your cluster and its Apache Kafka® host:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
      1. Navigate to **Managed Service for&nbsp;Kafka**.
      1. In the cluster row, click ![image](../../_assets/console-icons/ellipsis.svg) and select ![image](../../_assets/console-icons/pencil.svg) **Edit**.
      1. Under **Network settings**, specify the new availability zone.
      1. If the new availability zone has multiple subnets, specify the one you need.
      1. Click **Save**.

   - CLI {#cli}

      If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

      The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

      To change the availability zone for a cluster and its Apache Kafka® host, run this command:

      ```bash
      yc managed-kafka cluster update <cluster_name_or_ID> \
         --zone-ids <availability_zone> \
         --subnet-ids <subnet_ID>
      ```

      If there is only one subnet in the new availability zone, you do not need to specify `--subnet-ids`.

   - Terraform {#tf}

      1. Open the current Terraform configuration file describing your infrastructure.

         For information about creating this file, see [Creating a cluster Apache Kafka®](cluster-create.md).

      1. In the Managed Service for Apache Kafka® cluster description, specify the new subnet in `subnet_ids` and the new availability zone in `zones`:

         ```hcl
         resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
           ...
           subnet_ids = ["<subnet>"]
           config {
             ...
             zones = ["<availability_zone>"]
           }
           ...
         }
         ```

         If there is only one subnet in the new availability zone, you do not need to specify `subnet_ids`.

      1. Make sure the settings are correct.

         1. In the command line, navigate to the directory that contains the current Terraform configuration files defining the infrastructure.
         1. Run this command:
         
            ```bash
            terraform validate
            ```
         
            Terraform will show any errors found in your configuration files.

      1. Confirm resource changes.

         1. Run this command to view the planned changes:
         
            ```bash
            terraform plan
            ```
         
            If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
         
         1. If everything looks correct, apply the changes:
            1. Run this command:
         
               ```bash
               terraform apply
               ```
         
            1. Confirm updating the resources.
            1. Wait for the operation to complete.

      For more information, see [this Terraform provider guide](../../terraform/resources/mdb_kafka_cluster.md).

      {% note warning "Timeouts" %}
      
      The Terraform provider limits the time for all operations with the Managed Service for Apache Kafka® cluster to 60 minutes.
      
      Operations exceeding the timeout are aborted.
      
      {% cut "How do I change these limits?" %}
      
      Add the `timeouts` section to your cluster description, such as the following:
      
      ```hcl
      resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
        ...
        timeouts {
          create = "1h30m" # 1 hour 30 minutes
          update = "2h"    # 2 hours
          delete = "30m"   # 30 minutes
        }
      }
      ```
      
      {% endcut %}
      
      {% endnote %}

   - REST API {#api}

       1. [Get an IAM token for API authentication](../api-ref/authentication.md) and put it into an environment variable:

          ```bash
          export IAM_TOKEN="<IAM_token>"
          ```

       1. Call the [Cluster.update](../api-ref/Cluster/update.md) method, e.g., via the following [cURL](https://curl.se/) request:

          {% note warning %}
          
          The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `updateMask` parameter as a single comma-separated string.
          
          {% endnote %}

          ```bash
          curl \
              --request PATCH \
              --header "Authorization: Bearer $IAM_TOKEN" \
              --header "Content-Type: application/json" \
              -url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>' \
              --data '{
                        "updateMask": "configSpec.zoneId,subnetIds",
                        "subnetIds": [
                          "<subnet>"
                        ]
                        "configSpec": {
                          "zoneId": [
                            "<availability_zone>"
                          ]
                        }
                      }'
          ```

          Where:

          * `updateMask`: Comma-separated string of settings you want to update.

              Specify the relevant parameters:
              * `subnetIds`: To change the list of subnets.
              * `configSpec.zoneId`: To change the availability zone.
          * `subnetIds`: Array of strings. Each string is a subnet ID. If there is only one subnet in the new availability zone, you do not need to specify `subnetIds`.
          * `zoneId`: New availability zone for the cluster.

          You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. View the [server response](../api-ref/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   - gRPC API {#grpc-api}

       1. [Get an IAM token for API authentication](../api-ref/authentication.md) and put it into an environment variable:

           ```bash
           export IAM_TOKEN="<IAM_token>"
           ```

       1. Clone the [cloudapi](https://github.com/yandex-cloud/cloudapi) repository:
          
          ```bash
          cd ~/ && git clone --depth=1 https://github.com/yandex-cloud/cloudapi
          ```
          
          Below, we assume that the repository contents reside in the `~/cloudapi/` directory.

       1. Call the [ClusterService/Update](../api-ref/grpc/Cluster/update.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:

            {% note warning %}
            
            The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `update_mask` parameter as an array of `paths[]` strings.
            
            {% cut "Format for listing settings" %}
            
            ```yaml
            "update_mask": {
                "paths": [
                    "<setting_1>",
                    "<setting_2>",
                    ...
                    "<setting_N>"
                ]
            }
            ```
            
            {% endcut %}
            
            {% endnote %}

            ```bash
            grpcurl \
                -format json \
                -import-path ~/cloudapi/ \
                -import-path ~/cloudapi/third_party/googleapis/ \
                -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
                -rpc-header "Authorization: Bearer $IAM_TOKEN" \
                -d '{
                      "cluster_id": "<cluster_ID>",
                      "update_mask": {
                        "paths": [
                          "subnet_ids",
                          "config_spec.zone_id"
                        ]
                      },
                      "subnet_ids": [
                        "<subnet>"
                      ]
                      "config_spec": {
                        "zone_id": [
                          "<availability_zone>"
                        ]
                      }
                    }' \
                mdb.api.cloud.yandex.net:443 \
                yandex.cloud.mdb.kafka.v1.ClusterService.Update
            ```

            Where:

            * `update_mask`: List of settings you want to update as an array of strings (`paths[]`).

               Specify the relevant parameters:
               * `subnet_ids`: To change the list of subnets.
               * `config_spec.zone_id`: To change the availability zone.
            * `subnet_ids`: Array of strings. Each string is a subnet ID. If there is only one subnet in the new availability zone, you do not need to specify `subnet_ids`.
            * `zone_id`: New availability zone for the cluster.

            You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. Check the [server response](../api-ref/grpc/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   {% endlist %}

1. To successfully connect to topics after migration, specify the new broker’s FQDN in your backend or client, e.g., in your application code or graphical IDE. Delete the FQDN of the original broker in your source availability zone.

   To find out the FQDN, get the list of hosts in the cluster:

   {% list tabs group=instructions %}
   
   - Management console {#console}
   
      1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
      1. Navigate to **Managed Service for&nbsp;Kafka**.
      1. Click the name of your cluster and select the **Hosts** tab.
   
   - CLI {#cli}
   
      ```bash
      yc managed-kafka cluster list-hosts <cluster_name_or_ID>
      ```
   
      You will see the FQDN under `NAME` in the command output.
   
   - REST API {#api}
   
       1. Call the [Cluster.listHosts](../api-ref/Cluster/listHosts.md) method, e.g., via the following [cURL](https://curl.se/) request:
   
           ```bash
           curl \
               --request GET \
               --header "Authorization: Bearer $IAM_TOKEN" \
               --url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>/hosts'
           ```
   
           You can get the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).
   
       1. Check the [server response](../api-ref/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.
   
   - gRPC API {#grpc-api}
   
       1. Call the [ClusterService/ListHosts](../api-ref/grpc/Cluster/listHosts.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:
   
           ```bash
           grpcurl \
               -format json \
               -import-path ~/cloudapi/ \
               -import-path ~/cloudapi/third_party/googleapis/ \
               -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
               -rpc-header "Authorization: Bearer $IAM_TOKEN" \
               -d '{
                       "cluster_id": "<cluster_ID>"
                   }' \
               mdb.api.cloud.yandex.net:443 \
               yandex.cloud.mdb.kafka.v1.ClusterService.ListHosts
           ```
   
           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).
   
       1. Check the [server response](../api-ref/grpc/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.
   
   {% endlist %}

### Migrating a single-host cluster using auxiliary tools {#auxiliary-instruments}

To move an Apache Kafka® host to a different availability zone in a Managed Service for Apache Kafka® cluster:

1. [Create a subnet](../../vpc/operations/subnet-create.md) in the target availability zone.
1. If the cluster security group is set up for a subnet in the availability zone you are moving your cluster from, reconfigure the group for the new subnet. To do so, replace the source subnet CIDR with the new subnet CIDR in the security group rules.
1. [Create](cluster-create.md) a Managed Service for Apache Kafka® cluster with the same configuration as the source cluster, except for a different subnet and security group.
1. Migrate data from your source cluster to the new one using one of the following tools:

   * [MirrorMaker](../tutorials/kafka-connectors.md): You can use either the MirrorMaker connector embedded in Managed Service for Apache Kafka® or the MirrorMaker utility.
   * [Data Transfer](../../data-transfer/tutorials/mkf-to-mkf.md).

1. To successfully connect to topics after migration, specify the new cluster’s broker FQDN in your backend or client, e.g., in your application code or graphical IDE. Delete the FQDN of your source cluster's broker in the source availability zone.

   You can get this FQDN from the list of hosts in your cluster:

   {% list tabs group=instructions %}
   
   - Management console {#console}
   
      1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
      1. Navigate to **Managed Service for&nbsp;Kafka**.
      1. Click the name of your cluster and select the **Hosts** tab.
   
   - CLI {#cli}
   
      ```bash
      yc managed-kafka cluster list-hosts <cluster_name_or_ID>
      ```
   
      You will see the FQDN under `NAME` in the command output.
   
   - REST API {#api}
   
       1. Call the [Cluster.listHosts](../api-ref/Cluster/listHosts.md) method, e.g., via the following [cURL](https://curl.se/) request:
   
           ```bash
           curl \
               --request GET \
               --header "Authorization: Bearer $IAM_TOKEN" \
               --url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>/hosts'
           ```
   
           You can get the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).
   
       1. Check the [server response](../api-ref/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.
   
   - gRPC API {#grpc-api}
   
       1. Call the [ClusterService/ListHosts](../api-ref/grpc/Cluster/listHosts.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:
   
           ```bash
           grpcurl \
               -format json \
               -import-path ~/cloudapi/ \
               -import-path ~/cloudapi/third_party/googleapis/ \
               -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
               -rpc-header "Authorization: Bearer $IAM_TOKEN" \
               -d '{
                       "cluster_id": "<cluster_ID>"
                   }' \
               mdb.api.cloud.yandex.net:443 \
               yandex.cloud.mdb.kafka.v1.ClusterService.ListHosts
           ```
   
           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).
   
       1. Check the [server response](../api-ref/grpc/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.
   
   {% endlist %}

1. [Delete the source Managed Service for Apache Kafka® cluster](cluster-delete.md).

## Migrating a multi-host cluster {#multiple-hosts}

{% note info %}

[Clusters running Apache Kafka® 3.6 or higher](../concepts/index.md#kraft) do not use ZooKeeper hosts. Migration is only possible for configurations with three brokers in the same availability zone.

{% endnote %}

If you create an Apache Kafka® 3.5 cluster out of more than one broker host, three separate ZooKeeper hosts will be automatically added to the cluster. Each host is assigned a subnet from different availability zones. After you create a cluster, you cannot change its subnet in the availability zone.

The migration process of an Apache Kafka® 3.5 cluster depends on which availability zones Apache Kafka® and ZooKeeper hosts reside in prior to migration and how many subnets each zone contains. See [these examples](#examples) to better understand how migration works.

To move Apache Kafka® hosts to a different availability zone in an Apache Kafka® 3.5 cluster:

1. Find out in which availability zones Apache Kafka® and ZooKeeper hosts reside:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
      1. Navigate to **Managed Service for&nbsp;Kafka**.
      1. Click the name of your cluster and select the **Hosts** tab. The **Availability zone** column lists the availability zones for each host.

   - CLI {#cli}

      If you do not have the Yandex Cloud CLI yet, [install and initialize it](../../cli/quickstart.md#install).

      The folder used by default is the one specified when [creating](../../cli/operations/profile/profile-create.md) the CLI profile. To change the default folder, use the `yc config set folder-id <folder_ID>` command. You can also specify a different folder for any command using `--folder-name` or `--folder-id`. If you access a resource by its name, the search will be limited to the default folder. If you access a resource by its ID, the search will be global, i.e., through all folders based on access permissions.

      ```bash
      yc managed-kafka cluster list-hosts <cluster_name_or_ID>
      ```

      The availability zone is specified in the command output under `ZONE ID`.

   - REST API {#api}

       1. [Get an IAM token for API authentication](../api-ref/authentication.md) and put it into an environment variable:

           ```bash
           export IAM_TOKEN="<IAM_token>"
           ```

       1. Call the [Cluster.listHosts](../api-ref/Cluster/listHosts.md) method, e.g., via the following [cURL](https://curl.se/) request:

           ```bash
           curl \
               --request GET \
               --header "Authorization: Bearer $IAM_TOKEN" \
               --url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>/hosts'
           ```

           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. Check the [server response](../api-ref/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the availability zone in the `hosts[].zoneId` field of the response.

   - gRPC API {#grpc-api}

       1. [Get an IAM token for API authentication](../api-ref/authentication.md) and put it into an environment variable:

           ```bash
           export IAM_TOKEN="<IAM_token>"
           ```

       1. Clone the [cloudapi](https://github.com/yandex-cloud/cloudapi) repository:
          
          ```bash
          cd ~/ && git clone --depth=1 https://github.com/yandex-cloud/cloudapi
          ```
          
          Below, we assume that the repository contents reside in the `~/cloudapi/` directory.

       1. Call the [ClusterService/ListHosts](../api-ref/grpc/Cluster/listHosts.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:

           ```bash
           grpcurl \
               -format json \
               -import-path ~/cloudapi/ \
               -import-path ~/cloudapi/third_party/googleapis/ \
               -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
               -rpc-header "Authorization: Bearer $IAM_TOKEN" \
               -d '{
                       "cluster_id": "<cluster_ID>"
                   }' \
               mdb.api.cloud.yandex.net:443 \
               yandex.cloud.mdb.kafka.v1.ClusterService.ListHosts
           ```

           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. Check the [server response](../api-ref/grpc/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the availability zone in the `hosts[].zone_id` field of the response.

   {% endlist %}

1. If the target availability zone for Apache Kafka® hosts is not on the list, [create a subnet](../../vpc/operations/subnet-create.md) in this zone.

   If the target availability zone is on the list, Apache Kafka® hosts will migrate to the subnet that already contains Apache Kafka® or ZooKeeper hosts in that zone.

1. Check the cluster security group. If it is set up for a subnet in the source availability zone, reconfigure the group for the subnet in the target availability zone. To do so, replace the source subnet CIDR with the target subnet CIDR in the security group rules.
1. Change the availability zone of your cluster and its Apache Kafka® hosts:

   {% list tabs group=instructions %}

   - Management console {#console}

      1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
      1. Navigate to **Managed Service for&nbsp;Kafka**.
      1. In the cluster row, click ![image](../../_assets/console-icons/ellipsis.svg) and select ![image](../../_assets/console-icons/pencil.svg) **Edit**.
      1. Under **Network settings**, set the new availability zones. Their total number must not decrease.

         {% note warning %}

         After adding a new availability zone, deselect one of the old zones. Otherwise, you will not be able to delete an old availability zone after you save the settings.

         {% endnote %}

      1. Specify a subnet in the new availability zone if:

         * Apache Kafka® or ZooKeeper hosts were not previously placed in the target availability zone.
         * The target availability zone has more than one subnet.

      1. Click **Save**.

   - CLI {#cli}

      To update availability zones for a cluster and its Apache Kafka® hosts, run this command:

      ```bash
      yc managed-kafka cluster update <cluster_name_or_ID> \
         --zone-ids <availability_zones> \
         --subnet-ids <subnet_IDs>
      ```

      In `--zone-ids`, list the availability zones separated by commas. Their total number must not decrease.

      {% note warning %}

      After adding a new availability zone, remove one of the old zones from the list. Otherwise, you will not be able to delete an old availability zone after you run the command.

      {% endnote %}

      In `--subnet-ids`, list the subnets for the `ru-central1-a`, `ru-central1-b`, and `ru-central1-d` availability zones, separated by commas. You must specify subnets for these zones even if the Apache Kafka® hosts are deployed in fewer zones. You need all three availability zones for ZooKeeper hosts.

   - Terraform {#tf}

      1. Open the current Terraform configuration file describing your infrastructure.

         For information about creating this file, see [Creating a cluster Apache Kafka®](cluster-create.md).

      1. In the Managed Service for Apache Kafka® cluster description, change the list of availability zones under `zones`:

         ```hcl
         resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
           ...
           config {
             ...
             zones = ["<availability_zones>"]
           }
           ...
         }
         ```

         The number of availability zones must not decrease.

         {% note warning %}

         After adding a new availability zone, remove one of the old zones from the list. Otherwise, you will not be able to delete an old availability zone after you save the settings.

         {% endnote %}

      1. Change the list of subnets under `subnet_ids` if these two conditions are met:

         * You are migrating Apache Kafka® hosts to an availability zone where ZooKeeper hosts were not previously placed.
         * The target availability zone has more than one subnet.

         If the cluster hosts are placed in the `ru-central1-a` and `ru-central1-b` availability zones, and you change the availability zones to `ru-central1-a`, `ru-central1-b`, and `ru-central1-d`, specify a subnet only if the `ru-central1-d` zone has multiple subnets. Otherwise, you do not need to specify it.

         ```hcl
         resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
           ...
           subnet_ids = ["<subnets>"]
           ...
         }
         ```

      1. Make sure the settings are correct.

         1. In the command line, navigate to the directory that contains the current Terraform configuration files defining the infrastructure.
         1. Run this command:
         
            ```bash
            terraform validate
            ```
         
            Terraform will show any errors found in your configuration files.

      1. Confirm resource changes.

         1. Run this command to view the planned changes:
         
            ```bash
            terraform plan
            ```
         
            If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
         
         1. If everything looks correct, apply the changes:
            1. Run this command:
         
               ```bash
               terraform apply
               ```
         
            1. Confirm updating the resources.
            1. Wait for the operation to complete.

      For more information, see [this Terraform provider guide](../../terraform/resources/mdb_kafka_cluster.md).

      {% note warning "Timeouts" %}
      
      The Terraform provider limits the time for all operations with the Managed Service for Apache Kafka® cluster to 60 minutes.
      
      Operations exceeding the timeout are aborted.
      
      {% cut "How do I change these limits?" %}
      
      Add the `timeouts` section to your cluster description, such as the following:
      
      ```hcl
      resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
        ...
        timeouts {
          create = "1h30m" # 1 hour 30 minutes
          update = "2h"    # 2 hours
          delete = "30m"   # 30 minutes
        }
      }
      ```
      
      {% endcut %}
      
      {% endnote %}

   - REST API {#api}

       1. Call the [Cluster.update](../api-ref/Cluster/update.md) method, e.g., via the following [cURL](https://curl.se/) request:

          {% note warning %}
          
          The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `updateMask` parameter as a single comma-separated string.
          
          {% endnote %}

          ```bash
          curl \
              --request PATCH \
              --header "Authorization: Bearer $IAM_TOKEN" \
              --header "Content-Type: application/json" \
              -url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>' \
              --data '{
                        "updateMask": "configSpec.zoneId,subnetIds",
                        "subnetIds": [
                          <subnet_list>
                        ],
                        "configSpec": {
                          "zoneId": [
                            <list_of_availability_zones>
                          ]
                        }
                      }'
          ```

          Where:

          * `updateMask`: Comma-separated string of settings you want to update.

            Specify the relevant parameters:
            * `subnetIds`: To change the list of subnets.
            * `configSpec.zoneId`: To change the list of availability zones.
          * `subnetIds`: Array of strings. Each string is a subnet ID. Change the list of subnets if these two conditions are met:

            * You are migrating Apache Kafka® hosts to an availability zone where ZooKeeper hosts were not previously placed.
            * The target availability zone has more than one subnet.

            If the cluster hosts are placed in the `ru-central1-a`, `ru-central1-b`, and `ru-central1-c` availability zones, and you change the availability zones to `ru-central1-a`, `ru-central1-b`, and `ru-central1-d`, specify a subnet only if the `ru-central1-d` zone has multiple subnets. Otherwise, you do not need to specify it.
          * `zoneId`: New availability zones for the cluster. Their total number must not decrease.

          You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. View the [server response](../api-ref/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   - gRPC API {#grpc-api}

       1. Call the [ClusterService/Update](../api-ref/grpc/Cluster/update.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:

           {% note warning %}
           
           The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `update_mask` parameter as an array of `paths[]` strings.
           
           {% cut "Format for listing settings" %}
           
           ```yaml
           "update_mask": {
               "paths": [
                   "<setting_1>",
                   "<setting_2>",
                   ...
                   "<setting_N>"
               ]
           }
           ```
           
           {% endcut %}
           
           {% endnote %}

           ```bash
           grpcurl \
               -format json \
               -import-path ~/cloudapi/ \
               -import-path ~/cloudapi/third_party/googleapis/ \
               -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
               -rpc-header "Authorization: Bearer $IAM_TOKEN" \
               -d '{
                     "cluster_id": "<cluster_ID>",
                     "update_mask": {
                       "paths": [
                         "subnet_ids",
                         "config_spec.zone_id"
                       ]
                     },
                     "subnet_ids": [
                       <subnet_list>
                     ],
                     "config_spec": {
                       "zone_id": [
                         <list_of_availability_zones>
                       ]
                     }
                   }' \
               mdb.api.cloud.yandex.net:443 \
               yandex.cloud.mdb.kafka.v1.ClusterService.Update
           ```

           Where:

           * `update_mask`: List of settings you want to update as an array of strings (`paths[]`).

              Specify the relevant parameters:
              * `subnet_ids`: To change the list of subnets.
              * `config_spec.zone_id`: To change the list of availability zones.
           * `subnet_ids`: Array of strings. Each string is a subnet ID. Change the list of subnets if these two conditions are met:

             * You are migrating Apache Kafka® hosts to an availability zone where ZooKeeper hosts were not previously placed.
             * The target availability zone has more than one subnet.

             If the cluster hosts are placed in the `ru-central1-a`, `ru-central1-b`, and `ru-central1-c` availability zones, and you change the availability zones to `ru-central1-a`, `ru-central1-b`, and `ru-central1-d`, specify a subnet only if the `ru-central1-d` zone has multiple subnets. Otherwise, you do not need to specify it.
           * `zone_id`: New availability zones for the cluster. Their total number must not decrease.

           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. Check the [server response](../api-ref/grpc/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   {% endlist %}

To move Apache Kafka® hosts to a different availability zone in an Apache Kafka® cluster version 3.6 or higher:

1. [Create a subnet](../../vpc/operations/subnet-create.md) in the target availability zone you are migrating Apache Kafka® hosts to.
1. Check the cluster security group. If it is set up for a subnet in the source availability zone, reconfigure the group for the subnet in the target availability zone. To do so, replace the source subnet CIDR with the target subnet CIDR in the security group rules.
1. Change the availability zone of your cluster and its Apache Kafka® hosts:

   {% list tabs group=instructions %}

   - CLI {#cli}

      To change the availability zone for a cluster and its Apache Kafka® hosts, run this command:

      ```bash
      yc managed-kafka cluster update <cluster_name_or_ID> \
         --zone-ids <availability_zone> \
         --subnet-ids <subnet_ID>
      ```

   - Terraform {#tf}

      1. Open the current Terraform configuration file describing your infrastructure.

         For information about creating this file, see [Creating a cluster Apache Kafka®](cluster-create.md).

      1. In the Managed Service for Apache Kafka® cluster description, change the availability zone in the `zones` parameter:

         ```hcl
         resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
           ...
           config {
             ...
             zones = ["<availability_zone>"]
           }
           ...
         }
         ```

      1. In the `subnet_ids` parameter, specify a subnet in the target availability zone.

         ```hcl
         resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
           ...
           subnet_ids = ["<subnet>"]
           ...
         }
         ```

      1. Make sure the settings are correct.

         1. In the command line, navigate to the directory that contains the current Terraform configuration files defining the infrastructure.
         1. Run this command:
         
            ```bash
            terraform validate
            ```
         
            Terraform will show any errors found in your configuration files.

      1. Confirm resource changes.

         1. Run this command to view the planned changes:
         
            ```bash
            terraform plan
            ```
         
            If you described the configuration correctly, the terminal will display a list of the resources to update and their parameters. This is a verification step that does not apply changes to your resources.
         
         1. If everything looks correct, apply the changes:
            1. Run this command:
         
               ```bash
               terraform apply
               ```
         
            1. Confirm updating the resources.
            1. Wait for the operation to complete.

      For more information, see [this Terraform provider guide](../../terraform/resources/mdb_kafka_cluster.md).

      {% note warning "Timeouts" %}
      
      The Terraform provider limits the time for all operations with the Managed Service for Apache Kafka® cluster to 60 minutes.
      
      Operations exceeding the timeout are aborted.
      
      {% cut "How do I change these limits?" %}
      
      Add the `timeouts` section to your cluster description, such as the following:
      
      ```hcl
      resource "yandex_mdb_kafka_cluster" "<cluster_name>" {
        ...
        timeouts {
          create = "1h30m" # 1 hour 30 minutes
          update = "2h"    # 2 hours
          delete = "30m"   # 30 minutes
        }
      }
      ```
      
      {% endcut %}
      
      {% endnote %}

   - REST API {#api}

       1. Call the [Cluster.update](../api-ref/Cluster/update.md) method, e.g., via the following [cURL](https://curl.se/) request:

          {% note warning %}
          
          The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `updateMask` parameter as a single comma-separated string.
          
          {% endnote %}

          ```bash
          curl \
              --request PATCH \
              --header "Authorization: Bearer $IAM_TOKEN" \
              --header "Content-Type: application/json" \
              -url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>' \
              --data '{
                        "updateMask": "configSpec.zoneId,subnetIds",
                        "subnetIds": [
                          <subnet_in_target_availability_zone>
                        ],
                        "configSpec": {
                          "zoneId": [
                            <target_availability_zone>
                          ]
                        }
                      }'
          ```

          Where:

          * `updateMask`: Comma-separated string of settings to update.

             In this case, specify `subnetIds` and `configSpec.zoneId`.

          * `subnetIds`: Array of strings. Each string is a subnet ID. Specify only the subnet in the target availability zone.
          * `zoneId`: New availability zones for the cluster. Specify only the target availability zone.

          You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. View the [server response](../api-ref/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   - gRPC API {#grpc-api}

       1. Call the [ClusterService/Update](../api-ref/grpc/Cluster/update.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:

           {% note warning %}
           
           The API method will assign default values to all the parameters of the object you are modifying unless you explicitly provide them in your request. To avoid this, list the settings you want to change in the `update_mask` parameter as an array of `paths[]` strings.
           
           {% cut "Format for listing settings" %}
           
           ```yaml
           "update_mask": {
               "paths": [
                   "<setting_1>",
                   "<setting_2>",
                   ...
                   "<setting_N>"
               ]
           }
           ```
           
           {% endcut %}
           
           {% endnote %}

           ```bash
           grpcurl \
               -format json \
               -import-path ~/cloudapi/ \
               -import-path ~/cloudapi/third_party/googleapis/ \
               -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
               -rpc-header "Authorization: Bearer $IAM_TOKEN" \
               -d '{
                     "cluster_id": "<cluster_ID>",
                     "update_mask": {
                       "paths": [
                         "subnet_ids",
                         "config_spec.zone_id"
                       ]
                     },
                     "subnet_ids": [
                       <subnet_in_target_availability_zone>
                     ],
                     "config_spec": {
                       "zone_id": [
                         <target_availability_zone>
                       ]
                     }
                   }' \
               mdb.api.cloud.yandex.net:443 \
               yandex.cloud.mdb.kafka.v1.ClusterService.Update
           ```

           Where:

           * `update_mask`: List of settings to update as an array of strings (`paths[]`).

              In this case, the array consists of the `subnetIds` and `configSpec.zoneId` strings.

           * `subnetIds`: Array of strings. Each string is a subnet ID. Specify only the subnet in the target availability zone.
           * `zoneId`: New availability zones for the cluster. Specify only the target availability zone.

           You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

       1. Check the [server response](../api-ref/grpc/Cluster/update.md#yandex.cloud.operation.Operation) to make sure your request was successful.

   {% endlist %}

To successfully connect to topics after migration, specify the new broker’s FQDN in your backend or client, e.g., in your application code or graphical IDE. Delete the FQDN of the original broker in your source availability zone.

You can get this FQDN from the list of hosts in your cluster:

{% list tabs group=instructions %}

- Management console {#console}

   1. In the [management console](https://console.yandex.cloud), navigate to the relevant folder.
   1. Navigate to **Managed Service for&nbsp;Kafka**.
   1. Click the name of your cluster and select the **Hosts** tab.

- CLI {#cli}

   ```bash
   yc managed-kafka cluster list-hosts <cluster_name_or_ID>
   ```

   You will see the FQDN under `NAME` in the command output.

- REST API {#api}

    1. Call the [Cluster.listHosts](../api-ref/Cluster/listHosts.md) method, e.g., via the following [cURL](https://curl.se/) request:

        ```bash
        curl \
            --request GET \
            --header "Authorization: Bearer $IAM_TOKEN" \
            --url 'https://mdb.api.cloud.yandex.net/managed-kafka/v1/clusters/<cluster_ID>/hosts'
        ```

        You can get the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

    1. Check the [server response](../api-ref/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.

- gRPC API {#grpc-api}

    1. Call the [ClusterService/ListHosts](../api-ref/grpc/Cluster/listHosts.md) method, e.g., via the following [gRPCurl](https://github.com/fullstorydev/grpcurl) request:

        ```bash
        grpcurl \
            -format json \
            -import-path ~/cloudapi/ \
            -import-path ~/cloudapi/third_party/googleapis/ \
            -proto ~/cloudapi/yandex/cloud/mdb/kafka/v1/cluster_service.proto \
            -rpc-header "Authorization: Bearer $IAM_TOKEN" \
            -d '{
                    "cluster_id": "<cluster_ID>"
                }' \
            mdb.api.cloud.yandex.net:443 \
            yandex.cloud.mdb.kafka.v1.ClusterService.ListHosts
        ```

        You can request the cluster ID with the [list of clusters in the folder](cluster-list.md#list-clusters).

    1. Check the [server response](../api-ref/grpc/Cluster/listHosts.md#yandex.cloud.mdb.kafka.v1.ListClusterHostsResponse) to make sure your request was successful. You will find the FQDN in the `hosts[].name` field of the response.

{% endlist %}

### Examples of migrating a multi-host cluster {#examples}

The examples below provide insight into situations where you need to specify a subnet to migrate a Managed Service for Apache Kafka® 3.5 multi-host cluster to a different availability zone.

#### A ZooKeeper host already resides in the target availability zone {#already-located}

Let’s assume your cluster comprises the following hosts:

* Apache Kafka® host 1 in the `ru-central1-a` availability zone
* Apache Kafka® host 2 in the `ru-central1-c` availability zone
* ZooKeeper host 1 in the `ru-central1-a` availability zone
* ZooKeeper host 2 in the `ru-central1-b` availability zone
* ZooKeeper host 3 in the `ru-central1-d` availability zone

You need to migrate Apache Kafka® hosts to the `ru-central1-a` and `ru-central1-d` availability zones.

ZooKeeper host 3 already resides in the `ru-central1-d` zone, which means it belongs to one of the subnets in this availability zone. This subnet will be used for migration, since you cannot change subnets after you create the cluster. As a result, you do not need to specify a subnet during migration.

#### The target availability zone contains no hosts and has one subnet {#one-subnet}

Let’s assume your cluster comprises the following hosts:

* Apache Kafka® host 1 in the `ru-central1-a` availability zone
* Apache Kafka® host 2 in the `ru-central1-b` availability zone
* Apache Kafka® host 3 in the `ru-central1-c` availability zone
* ZooKeeper host 1 in the `ru-central1-a` availability zone
* ZooKeeper host 2 in the `ru-central1-b` availability zone
* ZooKeeper host 3 in the `ru-central1-c` availability zone

You need to migrate Apache Kafka® hosts to the `ru-central1-a`, `ru-central1-b`, and `ru-central1-d` availability zones.

No hosts initially reside in the `ru-central1-d` zone. But there is only one subnet in it, so you need not specify a subnet when performing the migration.

#### The target availability zone contains no hosts and has multiple subnets {#several-subnets}

Let’s assume your cluster comprises the following hosts:

* Apache Kafka® host 1 in the `ru-central1-a` availability zone
* Apache Kafka® host 2 in the `ru-central1-b` availability zone
* Apache Kafka® host 3 in the `ru-central1-c` availability zone
* ZooKeeper host 1 in the `ru-central1-a` availability zone
* ZooKeeper host 2 in the `ru-central1-b` availability zone
* ZooKeeper host 3 in the `ru-central1-c` availability zone

You need to migrate Apache Kafka® hosts to the `ru-central1-a`, `ru-central1-b`, and `ru-central1-d` availability zones.

No hosts initially reside in the `ru-central1-d` zone. However, there are multiple subnets, so you need to specify a subnet to perform the migration.

## Specifics of migration in Yandex Data Transfer {#data-transfer}

If your cluster is used as an [endpoint](../../data-transfer/concepts/index.md#endpoint) when transferring data with Data Transfer, and the [transfer type](../../data-transfer/concepts/transfer-lifecycle.md#transfer-types) is **Replication** or **Snapshot and increment**, restart the transfer after migrating the cluster. This way, the transfer will get data about the cluster's new topology.

You do not need to restart **Snapshot** transfers, as information about the new topology is provided automatically upon their activation.

To restart a transfer, choose one of the two methods:

* [Deactivate](../../data-transfer/operations/transfer.md#deactivate) the transfer and wait for its status to change to **Stopped**. Next, [reactivate](../../data-transfer/operations/transfer.md#activate) the transfer and wait for its status to change to **Replicating**.
* Update any [setting for the transfer](../../data-transfer/operations/transfer.md#update) or [endpoint](../../data-transfer/operations/endpoint/index.md#update).

For more information, see [Migrating a Data Transfer transfer and endpoints to a different availability zone](../../data-transfer/operations/endpoint/migration-to-an-availability-zone.md).

For an example of transferring data using Data Transfer, see [this tutorial](../../data-transfer/tutorials/mkf-to-mkf.md).