[Документация Yandex Cloud](../../index.md) > [Практические руководства](../index.md) > [Построение Data Platform](index.md) > Миграция БД из стороннего кластера PostgreSQL в Managed Service for PostgreSQL

# Миграция базы данных из стороннего кластера PostgreSQL в Managed Service for PostgreSQL

Перенести данные из стороннего _кластера-источника_ в _кластер-приемник_ Managed Service for PostgreSQL можно тремя способами:

* [Перенос данных с использованием сервиса Yandex Data Transfer](#data-transfer).

    Этот способ позволяет:

    * обойтись без создания промежуточной виртуальной машины или разрешения доступа к вашему кластеру-приемнику Managed Service for PostgreSQL из интернета;
    * перенести базу целиком без остановки обслуживания пользователей;
    * мигрировать со старых версий PostgreSQL на более новые, в том числе обновить кластер с версии PostgreSQL 15 до версии 17.

    Чтобы использовать этот способ, разрешите подключение к кластеру-источнику из интернета.

    Подробнее в разделе [Какие задачи решает сервис Yandex Data Transfer](../../data-transfer/concepts/use-cases.md).

* [Перенос данных с помощью логической репликации](#logical-replication).

    [_Логическая репликация_](https://www.postgresql.org/docs/current/logical-replication.html) использует механизм [подписки (subscriptions)](https://www.postgresql.org/docs/current/sql-createsubscription.html). Это позволяет перенести данные в кластер-приемник с минимальным временем простоя.

    Используйте этот способ только в том случае, если перенос данных с помощью Yandex Data Transfer по каким-либо причинам невозможен.

* [Перенос данных через создание и восстановление логического дампа](#backup).

    _Логический дамп_ — файл с набором команд, последовательное выполнение которых позволяет восстановить состояние базы данных. Он создается с помощью утилиты `pg_dump`. Чтобы обеспечить полноту логического дампа, перед его созданием кластер-источник следует перевести в режим <q>только чтение</q>.

    Используйте этот способ только в том случае, если перенос данных с помощью любого из предыдущих способов по каким-либо причинам невозможен.

{% note warning %}

Пользователи автоматически не переносятся в кластер Managed Service for PostgreSQL. Их нужно [создать](../../managed-postgresql/operations/cluster-users.md#adduser) в новом кластере заново.

{% endnote %}

## Перенос данных с использованием сервиса Yandex Data Transfer {#data-transfer}

# Миграция данных с использованием сервиса Yandex Data Transfer {#data-transfer}

{% note info %}

В [регионе Казахстан](../../overview/concepts/region.md) доступна только [зона доступности](../../overview/concepts/geo-scope.md) `kz1-a`.

{% endnote %}


### Необходимые платные ресурсы {#paid-resources}

* Кластер Managed Service for PostgreSQL: выделенные хостам вычислительные ресурсы, объем хранилища и резервных копий ([тарифы Managed Service for PostgreSQL](../../managed-postgresql/pricing.md)).
* Публичные IP-адреса, если для хостов кластера включен публичный доступ ([тарифы Virtual Private Cloud](../../vpc/pricing.md)).
* Каждый трансфер: использование вычислительных ресурсов и количество переданных строк данных ([тарифы Data Transfer](../../data-transfer/pricing.md)).


### Перенесите данные {#transfer-data}

1. [Подготовьте кластер-источник](../../data-transfer/operations/prepare.md#source-pg).
1. Подготовьте инфраструктуру:

    {% list tabs group=instructions %}

    - Вручную {#manual}

        1. [Создайте кластер-приемник Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-create.md) любой подходящей конфигурации. Включите те же [расширения PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md), что и в кластере-источнике.
        1. [Подготовьте кластер-приемник](../../data-transfer/operations/prepare.md#target-pg).
        1. [Создайте эндпоинт для источника](../../data-transfer/operations/endpoint/index.md#create) со следующими параметрами:

             * **Тип базы данных** — `PostgreSQL`.
             * **Параметры эндпоинта** → **Настройки подключения** — `Пользовательская инсталляция`.

           Укажите параметры подключения к кластеру-источнику.

        1. [Создайте эндпоинт для приемника](../../data-transfer/operations/endpoint/index.md#create) со следующими параметрами:

             * **Тип базы данных** — `PostgreSQL`.
             * **Параметры эндпоинта** → **Настройки подключения** — `Кластер Managed Service for PostgreSQL`.

           Укажите идентификатор кластера-приемника.

        1. [Создайте трансфер](../../data-transfer/operations/transfer.md#create) типа _**Копирование и репликация**_, использующий созданные эндпоинты.
        1. [Активируйте трансфер](../../data-transfer/operations/transfer.md#activate).

            {% note warning %}

            Избегайте любых изменений в схеме данных в кластере-источнике и кластере-приемнике во время работы трансфера. Подробнее в разделе [Работа с базами данных во время трансфера](../../data-transfer/operations/db-actions.md).

            {% endnote %}

    - Terraform {#tf}

        1. Если у вас еще нет Terraform, [установите его](../infrastructure-management/terraform-quickstart.md#install-terraform).
        1. [Получите данные для аутентификации](../infrastructure-management/terraform-quickstart.md#get-credentials). Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
        1. [Настройте и инициализируйте провайдер](../infrastructure-management/terraform-quickstart.md#configure-provider). Чтобы не создавать конфигурационный файл с настройками провайдера вручную, [скачайте его](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
        1. Поместите конфигурационный файл в отдельную рабочую директорию и [укажите значения параметров](../infrastructure-management/terraform-quickstart.md#configure-provider). Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.

        1. Скачайте в ту же рабочую директорию файл конфигурации [data-transfer-pgsql-mpg.tf](https://github.com/yandex-cloud-examples/yc-data-transfer-from-on-premise-postgresql-to-cloud/blob/main/data-transfer-pgsql-mpg.tf).

            В этом файле описаны:

            * [сеть](../../vpc/concepts/network.md#network);
            * [подсеть](../../vpc/concepts/network.md#subnet);
            * [группа безопасности](../../vpc/concepts/security-groups.md) и правило, необходимое для подключения к кластеру;
            * кластер-приемник Managed Service for PostgreSQL;
            * эндпоинт для источника;
            * эндпоинт для приемника;
            * трансфер.

        1. Укажите в файле `data-transfer-pgsql-mpg.tf`:

            * [параметры эндпоинта-источника](../../data-transfer/operations/endpoint/source/postgresql.md#on-premise);
            * `pg-extensions` – список [расширений PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md) в кластере-источнике;
            * параметры кластера-приемника, которые используются и как [параметры эндпоинта-приемника](../../data-transfer/operations/endpoint/target/postgresql.md#managed-service):

                * `target_pgsql_version` — версия PostgreSQL, она должна быть не ниже, чем в кластере-источнике;
                * `target_user` и `target_password` — имя и пароль пользователя-владельца базы данных.

        1. Проверьте корректность файлов конфигурации Terraform с помощью команды:

            ```bash
            terraform validate
            ```

            Если в файлах конфигурации есть ошибки, Terraform на них укажет.

        1. Создайте необходимую инфраструктуру:

            1. Выполните команду для просмотра планируемых изменений:
            
               ```bash
               terraform plan
               ```
            
               Если конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
            
            1. Если вас устраивают планируемые изменения, внесите их:
               1. Выполните команду:
            
                  ```bash
                  terraform apply
                  ```
            
               1. Подтвердите изменение ресурсов.
               1. Дождитесь завершения операции.

            В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в [консоли управления](https://kz.console.yandex.cloud).

            Трансфер активируется автоматически после создания.

    {% endlist %}

1. Дождитесь перехода трансфера в статус **Реплицируется**.
1. Снимите пишущую нагрузку с кластера-источника.
1. На странице [мониторинга трансфера](../../data-transfer/operations/monitoring.md) дождитесь снижения до нуля характеристики **Maximum data transfer delay**. Это значит, что на кластер-приемник перенесены все изменения, произошедшие в кластере-источнике после завершения копирования данных.
1. Переключите нагрузку на кластер-приемник.
1. [Деактивируйте](../../data-transfer/operations/transfer.md#deactivate) трансфер и дождитесь его перехода в статус **Остановлен**.

    Подробнее о статусах трансфера смотрите в разделе [Жизненный цикл трансфера](../../data-transfer/concepts/transfer-lifecycle.md#statuses).


1. Чтобы снизить потребление ресурсов, которые вам не нужны, удалите их:

    {% list tabs group=instructions %}

    - Ресурсы созданы вручную {#manual}

        1. [Удалите кластер Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-delete.md).
        1. [Удалите остановленный трансфер](../../data-transfer/operations/transfer.md#delete).
        1. [Удалите эндпоинты](../../data-transfer/operations/endpoint/index.md#delete) для источника и приемника.

    - Ресурсы созданы с помощью Terraform {#tf}

        1. В терминале перейдите в директорию с планом инфраструктуры.
        
            {% note warning %}
        
            Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
        
            {% endnote %}
        
        1. Удалите ресурсы:
        
            1. Выполните команду:
        
                ```bash
                terraform destroy
                ```
        
            1. Подтвердите удаление ресурсов и дождитесь завершения операции.
        
            Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.

    {% endlist %}

## Перенос данных с помощью логической репликации {#logical-replication}

Логическая репликация поддерживается PostgreSQL с версии 10. Кроме миграции данных между одинаковыми версиями PostgreSQL, логическая репликация позволяет мигрировать на более новые версии PostgreSQL.

В кластерах Managed Service for PostgreSQL подписки может использовать владелец базы данных (пользователь, созданный одновременно с кластером) и пользователи с ролью `mdb_admin` для этого кластера.

Этапы миграции:

1. [Настройте кластер-источник](#source-setup).
1. [Экспортируйте схему БД в кластере-источнике](#source-schema-export).
1. [Восстановите схему БД в кластере-приемнике](#restore-schema).
1. [Создайте публикацию и подписку PostgreSQL](#create-publication-subscription).
1. [Перенесите PostgreSQL-sequence после репликации](#transfer-sequences).
1. [Отключите репликацию и перенесите нагрузку](#transfer-load).

Если созданные ресурсы вам больше не нужны, [удалите их](#clear-out-logical).


### Необходимые платные ресурсы {#paid-resources}

* Кластер Managed Service for PostgreSQL: выделенные хостам вычислительные ресурсы, объем хранилища и резервных копий ([тарифы Managed Service for PostgreSQL](../../managed-postgresql/pricing.md)).
* Публичные IP-адреса, если для хостов кластера включен публичный доступ ([тарифы Virtual Private Cloud](../../vpc/pricing.md)).


### Перед началом работы {#before-you-begin-logical}

Создайте необходимые ресурсы:

{% list tabs group=instructions %}

- Вручную {#manual}

    [Создайте кластер-приемник Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-create.md) любой подходящей конфигурации. При этом:

    * Версия PostgreSQL должна быть не ниже, чем в кластере-источнике. Миграция с понижением версии PostgreSQL невозможна.
    * При создании кластера укажите то же имя базы данных, что и в кластере-источнике.
    * Включите те же [расширения PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md), что и в кластере-источнике.

- Terraform {#tf}

    1. Если у вас еще нет Terraform, [установите его](../infrastructure-management/terraform-quickstart.md#install-terraform).
    1. [Получите данные для аутентификации](../infrastructure-management/terraform-quickstart.md#get-credentials). Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
    1. [Настройте и инициализируйте провайдер](../infrastructure-management/terraform-quickstart.md#configure-provider). Чтобы не создавать конфигурационный файл с настройками провайдера вручную, [скачайте его](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
    1. Поместите конфигурационный файл в отдельную рабочую директорию и [укажите значения параметров](../infrastructure-management/terraform-quickstart.md#configure-provider). Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.

    1. Скачайте в ту же рабочую директорию файл конфигурации [data-migration-pgsql-mpg.tf](https://github.com/yandex-cloud-examples/yc-postgresql-data-migration-from-on-premise/blob/main/data-migration-pgsql-mpg.tf).

        В этом файле описаны:

        * [сеть](../../vpc/concepts/network.md#network);
        * [подсеть](../../vpc/concepts/network.md#subnet);
        * [группа безопасности](../../vpc/concepts/security-groups.md) и правило, необходимое для подключения к кластеру;
        * кластер Managed Service for PostgreSQL с публичным доступом из интернета.

    1. Укажите в файле `data-migration-pgsql-mpg.tf`:

        * `target_db_name` — имя базы данных;
        * `pg-extensions` – список [расширений PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md) в кластере-источнике;
        * параметры кластера-приемника:

            * `target_pgsql_version` — версия PostgreSQL, она должна быть не ниже, чем в кластере-источнике;
            * `target_user` и `target_password` — имя и пароль пользователя-владельца базы данных.

    1. Проверьте корректность файлов конфигурации Terraform с помощью команды:

        ```bash
        terraform validate
        ```

        Если в файлах конфигурации есть ошибки, Terraform на них укажет.

    1. Создайте необходимую инфраструктуру:

        1. Выполните команду для просмотра планируемых изменений:
        
           ```bash
           terraform plan
           ```
        
           Если конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
        
        1. Если вас устраивают планируемые изменения, внесите их:
           1. Выполните команду:
        
              ```bash
              terraform apply
              ```
        
           1. Подтвердите изменение ресурсов.
           1. Дождитесь завершения операции.

        В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в [консоли управления](https://kz.console.yandex.cloud).

{% endlist %}

### Настройте кластер-источник {#source-setup}

1. Внесите изменения в конфигурацию и настройки аутентификации кластера-источника. Для этого отредактируйте файлы `postgresql.conf`  и `pg_hba.conf` (на дистрибутивах Debian и Ubuntu они по умолчанию расположены в каталоге `/etc/postgresql/<версия_PostgreSQL>/main/`):

    1. Задайте максимальное количество подключений пользователя. Для этого в файле `postgresql.conf` отредактируйте параметр `max_connections`:

        ```ini
        max_connections = <количество_подключений>
        ```
        
        Где `<количество_подключений>` — максимальное число подключений. Значение этого параметра должно быть не меньше, чем `N + 1`, где `N` количество всех возможных подключений к вашей инсталляции PostgreSQL. 

        Единица в `N + 1` закладывает резерв для подписки с помощью которой далее будет выполняться логическая репликация. Если вы планируете использовать несколько подписок, то укажите соответствующее значение.

        Текущее количество подключений вы можете посмотреть в системной таблице `pg_stat_activity`:

        ```sql
        SELECT count(*) FROM pg_stat_activity;
        ```

    1. Установите уровень логирования для [Write Ahead Log (WAL)](https://www.postgresql.org/docs/current/static/wal-intro.html). Для этого установите значение `logical` для настройки [wal_level](https://www.postgresql.org/docs/current/runtime-config-wal.html#RUNTIME-CONFIG-WAL-SETTINGS) в `postgresql.conf`:

        ```ini
        wal_level = logical
        ```

    1. (Опционально) Настройте SSL: это поможет не только шифровать данные, но и сжимать их. Чтобы включить использование SSL, задайте нужное значение в файле `postgresql.conf`:

        ```ini
        ssl = on
        ```
    
    1. Разрешите подключение к кластеру. Для этого отредактируйте [параметр](https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-LISTEN-ADDRESSES) `listen_addresses` в файле `postgresql.conf`. Например, чтобы кластер-источник принимал запросы на подключение со всех IP-адресов:

        ```ini
        listen_addresses = '*'
        ```

    1. Настройте аутентификацию в файле `pg_hba.conf`:

        {% list tabs %}

        - SSL

            ```txt
            hostssl         all            all             <IP-адрес_подключения>      md5
            hostssl         replication    all             <IP-адрес_подключения>      md5
            ```

        - Без SSL

            ```txt
            host         all            all             <IP-адрес_подключения>      md5
            host         replication    all             <IP-адрес_подключения>      md5
            ```

        {% endlist %}

        Где `<IP-адрес_подключения>` может быть как точным IP-адресом, так и диапазоном IP-адресов. Например, чтобы разрешить доступ из сети Yandex Cloud, вы можете указать [все публичные IP-адреса](../../overview/concepts/public-ips.md) Yandex Cloud.

1. Если в кластере-источнике работает файрвол, разрешите входящие соединения с нужных адресов.

1. Чтобы применить настройки, перезапустите сервис PostgreSQL:

   ```bash
   sudo systemctl restart postgresql
   ```

1. Проверьте статус сервиса PostgreSQL после перезапуска:

   ```bash
   sudo systemctl status postgresql
   ```

### Экспортируйте схему БД в кластере-источнике {#source-schema-export}

С помощью утилиты `pg_dump` создайте файл со схемой БД, которую нужно будет применить в кластере-приемнике.

```bash
pg_dump -h <IP-адрес_или_FQDN_хоста-мастера_кластера-источника> \
        -U <имя_пользователя> \
        -p <порт> \
        --schema-only \
        --no-privileges \
        --no-subscriptions \
        -d <имя_БД> \
        -Fd -f /tmp/db_dump
```

В этой команде при экспорте исключаются все данные, связанные с привилегиями и ролями, чтобы не возникало конфликтов с настройками БД в Yandex Cloud. Если вашей БД нужны дополнительные пользователи, [создайте их](../../managed-postgresql/operations/cluster-users.md#adduser).

### Восстановите схему БД в кластере-приемнике {#restore-schema}

С помощью утилиты `pg_restore` восстановите схему БД в кластере-приемнике:

```bash
pg_restore -h <IP-адрес_или_FQDN_хоста-мастера_кластера-приемника> \
           -U <имя_пользователя> \
           -p 6432 \
           -Fd -v \
           --single-transaction \
           -s --no-privileges \
           -d <имя_БД> /tmp/db_dump
```

### Создайте публикацию и подписку {#create-publication-subscription}

Для работы логической репликации необходимо создать публикацию (группу логически реплицируемых таблиц) в кластере-источнике и подписку (описание соединения с другой базой) в кластере-приемнике.

1. В кластере-источнике создайте публикацию для всех таблиц базы данных. При переносе нескольких баз для каждой из них нужно создать отдельную публикацию.

   {% note info %}

   Для создания публикации на все таблицы потребуются права суперпользователя, а для переноса выбранных таблиц — нет. Более подробно о создании публикации смотрите в [документации PostgreSQL](https://www.postgresql.org/docs/current/sql-createpublication.html).

   {% endnote %}

   Запрос:

   ```sql
   CREATE PUBLICATION p_data_migration FOR ALL TABLES;
   ```

1. На хосте кластера Managed Service for PostgreSQL создайте подписку со строкой подключения к публикации. Более подробно о создании подписок смотрите в [документации PostgreSQL](https://www.postgresql.org/docs/current/sql-createsubscription.html).

   Запрос с включенным SSL:

   ```sql
   CREATE SUBSCRIPTION s_data_migration CONNECTION 'host=<адрес_кластера-источника> port=<порт> user=<имя_пользователя> sslmode=verify-full dbname=<имя_БД>' PUBLICATION p_data_migration;
   ```

   Без SSL:

   ```sql
   CREATE SUBSCRIPTION s_data_migration CONNECTION 'host=<адрес_кластера-источника> port=<порт> user=<имя_пользователя> sslmode=disable dbname=<имя_БД>' PUBLICATION p_data_migration;
   ```
   {% note tip %}

   По умолчанию `CREATE SUBSCRIPTION` также создает слот репликации. Чтобы связать подписку с существующим слотом репликации и не создавать новый, добавьте в запрос параметр `create_slot = false`.

   {% endnote %}

1. Чтобы получить статус репликации, обратитесь к каталогам `pg_subscription_rel`. Общий статус репликации в кластере-приемнике можно получить через `pg_stat_subscription`, в кластере-источнике — через `pg_stat_replication`.

   ```sql
   SELECT * FROM pg_subscription_rel;
   ```

   Прежде всего обратите внимание на поле `srsubstate`. Значение `r` в нем означает, что синхронизация завершилась, и базы готовы к репликации.

### Перенесите PostgreSQL-sequences после репликации {#transfer-sequences}

Чтобы завершить синхронизацию кластера-источника и кластера-приемника:

1. Переведите кластер-источник в режим <q>только чтение</q>.
1. Создайте дамп с PostgreSQL-sequences в кластере-источнике:

   ```bash
   pg_dump -h <IP-адрес_или_FQDN_хоста-мастера_кластера-источника> \
           -U <имя_пользователя> \
           -p <порт> \
           -d <имя_БД> \
           --data-only -t '*.*_seq' > /tmp/seq-data.sql
   ```

   Обратите внимание на используемый паттерн `*.*_seq`. Если в переносимой базе есть не соответствующие ему sequences, то для их выгрузки укажите другой паттерн.

   Подробнее о паттернах смотрите в [документации PostgreSQL](https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-PATTERNS).

1. Восстановите дамп с sequences в кластере-приемнике:

   ```bash
   psql -h <IP-адрес_или_FQDN_хоста-мастера_кластера-приемника> \
        -U <имя_пользователя> \
        -p 6432 \
        -d <имя_БД> \
        < /tmp/seq-data.sql
   ```

### Удалите подписку и перенесите нагрузку {#transfer-load}

1. Удалите подписку в кластере-приемнике:

    ```sql
    DROP SUBSCRIPTION s_data_migration;
   ```

1. Перенесите нагрузку на кластер-приемник.

### Удалите созданные ресурсы {#clear-out-logical}

Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:

{% list tabs group=instructions %}

- Вручную {#manual}

    [Удалите кластер Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-delete.md).

- Terraform {#tf}

    1. В терминале перейдите в директорию с планом инфраструктуры.
    
        {% note warning %}
    
        Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
    
        {% endnote %}
    
    1. Удалите ресурсы:
    
        1. Выполните команду:
    
            ```bash
            terraform destroy
            ```
    
        1. Подтвердите удаление ресурсов и дождитесь завершения операции.
    
        Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.

{% endlist %}

## Перенос данных через создание и восстановление логического дампа {#backup}

Создайте дамп нужной базы в кластере-источнике с помощью утилиты `pg_dump`. Для восстановления дампа в кластере-приемнике используйте утилиту `pg_restore`.

{% note info %}

Для использования утилиты `pg_restore` может понадобиться расширение базы данных `pg_repack`.

{% endnote %}

Этапы миграции:

1. [Создайте дамп переносимой базы](#dump).
1. [(Опционально) Создайте виртуальную машину в Yandex Cloud и загрузите дамп БД на нее](#create-vm).
1. [Восстановите данные из дампа в кластер-приемник](#restore).

Если созданные ресурсы вам больше не нужны, [удалите их](#clear-out-backup).


### Необходимые платные ресурсы {#paid-resources}

* Кластер Managed Service for PostgreSQL: выделенные хостам вычислительные ресурсы, объем хранилища и резервных копий ([тарифы Managed Service for PostgreSQL](../../managed-postgresql/pricing.md)).
* Публичные IP-адреса, если для хостов кластера включен публичный доступ ([тарифы Virtual Private Cloud](../../vpc/pricing.md)).
* Виртуальная машина: использование вычислительных ресурсов, хранилища, публичного IP-адреса и операционной системы ([тарифы Compute Cloud](../../compute/pricing.md)).


### Перед началом работы {#before-you-begin-backup}

Создайте необходимые ресурсы:

{% list tabs group=instructions %}

- Вручную {#manual}

    1. [Создайте кластер-приемник Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-create.md) любой подходящей конфигурации. При этом следующие параметры должны быть такими же, как и в кластере-источнике:

        * Версия PostgreSQL.
        * Имя пользователя.

            {% note info %}
            
            Вы можете использовать различные имена пользователей для источника и приемника, но это может привести к ошибке при восстановлении дампа. Подробнее читайте в разделе [Перемещение и восстановление кластера PostgreSQL](../../managed-postgresql/qa/backup.md#backup-error)
            
            {% endnote %}

        * [Расширения PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md).

    1. (Опционально) [Создайте виртуальную машину](../../compute/operations/vm-create/create-linux-vm.md) на базе [Ubuntu 20.04 LTS](https://yandex.cloud/ru-kz/marketplace/products/yc/ubuntu-20-04-lts) со следующими параметрами:

        * **Диски и файловые хранилища** → **Размер** — достаточный для хранения распакованного и нераспакованного дампов.

            Рекомендуется использовать объем в два или более раз превышающий суммарный объем дампа и архива с ним.

        * **Сетевые настройки**:

            * **Подсеть** — выберите подсеть в той же облачной сети, в которой размещен кластер-приемник.
            * **Публичный IP-адрес** — выберите `Автоматически` или один адрес из списка зарезервированных IP-адресов.

    
    1. Если вы используете группы безопасности для промежуточной виртуальной машины и кластера Managed Service for PostgreSQL, [настройте их](../../managed-postgresql/operations/connect/index.md#configure-security-groups).


- Terraform {#tf}

    1. Если у вас еще нет Terraform, [установите его](../infrastructure-management/terraform-quickstart.md#install-terraform).
    1. [Получите данные для аутентификации](../infrastructure-management/terraform-quickstart.md#get-credentials). Вы можете добавить их в переменные окружения или указать далее в файле с настройками провайдера.
    1. [Настройте и инициализируйте провайдер](../infrastructure-management/terraform-quickstart.md#configure-provider). Чтобы не создавать конфигурационный файл с настройками провайдера вручную, [скачайте его](https://github.com/yandex-cloud-examples/yc-terraform-provider-settings/blob/main/provider.tf).
    1. Поместите конфигурационный файл в отдельную рабочую директорию и [укажите значения параметров](../infrastructure-management/terraform-quickstart.md#configure-provider). Если данные для аутентификации не были добавлены в переменные окружения, укажите их в конфигурационном файле.

    1. Скачайте в ту же рабочую директорию файл конфигурации [data-restore-pgsql-mpg.tf](https://github.com/yandex-cloud-examples/yc-postgresql-data-migration-from-on-premise/blob/main/data-restore-pgsql-mpg.tf).

        В этом файле описаны:

        * [сеть](../../vpc/concepts/network.md#network);
        * [подсеть](../../vpc/concepts/network.md#subnet);
        * [группа безопасности](../../vpc/concepts/security-groups.md) и правило, необходимое для подключения к кластеру;
        * кластер Managed Service for PostgreSQL с публичным доступом из интернета;
        * (опционально) виртуальная машина с публичным доступом из интернета.

    1. Укажите в файле `data-restore-pgsql-mpg.tf`:

        * `pg-extensions` – список [расширений PostgreSQL](../../managed-postgresql/operations/extensions/cluster-extensions.md) в кластере-источнике;
        * параметры кластера-приемника:

            * `target_pgsql_version` — версия PostgreSQL, она должна быть не ниже чем в кластере-источнике;
            * `target_db_name` — имя базы данных;
            * `target_user` — имя пользователя-владельца базы данных. Должно совпадать с именем пользователя в кластере-источнике;

                {% note info %}
                
                Вы можете использовать различные имена пользователей для источника и приемника, но это может привести к ошибке при восстановлении дампа. Подробнее читайте в разделе [Перемещение и восстановление кластера PostgreSQL](../../managed-postgresql/qa/backup.md#backup-error)
                
                {% endnote %}

            * `target_password` — пароль пользователя-владельца базы данных;
        * (опционально) параметры виртуальной машины:

            * `vm_image_id` — идентификатор публичного [образа](../../compute/operations/images-with-pre-installed-software/get-list.md) с Ubuntu без [GPU](../../glossary/gpu.md). Например, для [Ubuntu 20.04 LTS](https://yandex.cloud/ru-kz/marketplace/products/yc/ubuntu-20-04-lts);
            * `vm_username` и `vm_public_key` — логин и абсолютный путь к [публичному ключу](../../compute/operations/vm-connect/ssh.md#creating-ssh-keys), которые будут использоваться для доступа к виртуальной машине. По умолчанию в образе [Ubuntu 20.04 LTS](https://yandex.cloud/ru-kz/marketplace/products/yc/ubuntu-20-04-lts) указанный логин игнорируется, вместо него создается пользователь с логином `ubuntu`. Используйте его для подключения к виртуальной машине.

    1. Проверьте корректность файлов конфигурации Terraform с помощью команды:

        ```bash
        terraform validate
        ```

        Если в файлах конфигурации есть ошибки, Terraform на них укажет.

    1. Создайте необходимую инфраструктуру:

        1. Выполните команду для просмотра планируемых изменений:
        
           ```bash
           terraform plan
           ```
        
           Если конфигурации ресурсов описаны верно, в терминале отобразится список изменяемых ресурсов и их параметров. Это проверочный этап: ресурсы не будут изменены.
        
        1. Если вас устраивают планируемые изменения, внесите их:
           1. Выполните команду:
        
              ```bash
              terraform apply
              ```
        
           1. Подтвердите изменение ресурсов.
           1. Дождитесь завершения операции.

        В указанном каталоге будут созданы все требуемые ресурсы. Проверить появление ресурсов и их настройки можно в [консоли управления](https://kz.console.yandex.cloud).

{% endlist %}

### Создайте дамп базы данных {#dump}

1. Переключите базу в режим <q>только чтение</q>.
1. Создайте дамп с помощью утилиты [pg_dump](https://www.postgresql.org/docs/current/app-pgdump.html). Для ускорения процесса запустите ее в многопоточном режиме, передав в аргументе `--jobs` количество доступных ядер процессора:

    ```bash
    pg_dump --host=<IP-адрес_или_FQDN_хоста-мастера_кластера-источника> \
            --port=<порт> \
            --username=<имя_пользователя> \
            --jobs=<количество_ядер_процессора> \
            --format=d \
            --dbname=<имя_БД> \
            --file=db_dump
    ```

### (Опционально) Загрузите дамп на виртуальную машину в Yandex Cloud {#create-vm}

Переносить данные на промежуточную виртуальную машину в Compute Cloud нужно, если:

* К вашему кластеру Managed Service for PostgreSQL нет доступа из интернета.
* Ваше оборудование или соединение с кластером в Yandex Cloud недостаточно надежны.

Нужное количество оперативной памяти и ядер процессора зависит от объема переносимых данных и требуемой скорости переноса.

Чтобы подготовить виртуальную машину для восстановления дампа:

1. В консоли управления [создайте новую виртуальную машину](../../compute/operations/vm-create/create-linux-vm.md) из образа [Ubuntu 20.04](https://yandex.cloud/ru-kz/marketplace/products/yc/ubuntu-20-04-lts) на **Marketplace**. Параметры виртуальной машины должны зависеть от размера базы, которую вы хотите перенести. Минимальной конфигурации (1 ядро, 2 ГБ RAM, 10 ГБ дискового пространства) должно хватить для переноса базы до 1 ГБ. Чем больше переносимая база, тем больше должно быть оперативной памяти, и тем больше должно быть дискового пространства (как минимум в два раза больше, чем размер базы).


    Виртуальная машина должна находиться в той же сети и зоне доступности, что и кластер PostgreSQL. Кроме того, виртуальной машине должен быть присвоен публичный IP-адрес, чтобы вы могли загрузить дамп извне Yandex Cloud.

1. Настройте [apt-репозиторий PostgreSQL](https://www.postgresql.org/download/linux/ubuntu/).

1. Установите клиент PostgreSQL и дополнительные утилиты для работы с СУБД:

    ```bash
    sudo apt install postgresql-client-common && \
    sudo apt install postgresql-client-<версия_PostgreSQL>
    ```

1. Упакуйте дамп в архив:

    ```bash
    tar -cvzf db_dump.tar.gz db_dump
    ```

1. Перенесите архив с дампом на виртуальную машину, например, используя утилиту `scp`:

    ```bash
    scp db_dump.tar.gz <имя_пользователя_ВМ>@<публичный_адрес_ВМ>:/db_dump.tar.gz
    ```

1. [Подключитесь к виртуальной машине](../../compute/operations/vm-connect/ssh.md).

1. Распакуйте архив с дампом:

    ```bash
    tar -xzf db_dump.tar.gz
    ```

### Восстановите данные из дампа в кластер-приемник {#restore}

Восстановите дамп базы данных с помощью утилиты [pg_restore](https://www.postgresql.org/docs/current/app-pgrestore.html).

Версия `pg_restore` должна совпадать с версией `pg_dump`, а мажорная версия должна быть не меньше, чем у базы на которую дамп разворачивается.

Таким образом, для восстановления дампа PostgreSQL 14, PostgreSQL 15 и PostgreSQL 16 используйте `pg_restore 14`, `pg_restore 15` и `pg_restore 16` соответственно.

```bash
pg_restore --host=<IP-адрес_или_FQDN_хоста-мастера_кластера-приемника> \
           --username=<имя_пользователя> \
           --dbname=<имя_БД> \
           --port=6432 \
           --format=d \
           --verbose \
           db_dump \
           --single-transaction \
           --no-privileges
```

Если нужно восстановить только одну схему, добавьте параметр `--schema=<имя_схемы>`. Без него команда сработает только от лица владельца базы данных.

Если восстановление прерывается из-за ошибок отсутствия необходимых прав для создания и изменения расширений, уберите из команды параметр `--single-transaction`. В этом случае ошибки будут проигнорированы:

```text
pg_restore: warning: errors ignored on restore: 3
```

Убедитесь, что ошибки относятся только к расширениям, и проверьте целостность восстановленных данных.

### Удалите созданные ресурсы {#clear-out-backup}

Удалите ресурсы, которые вы больше не будете использовать, чтобы за них не списывалась плата:

{% list tabs group=instructions %}

- Вручную {#manual}

    * [Удалите кластер Yandex Managed Service for PostgreSQL](../../managed-postgresql/operations/cluster-delete.md).
    * Если вы создавали промежуточную виртуальную машину, [удалите ее](../../compute/operations/vm-control/vm-delete.md).
    * Если вы зарезервировали публичные статические IP-адреса, освободите и [удалите их](../../vpc/operations/address-delete.md).

- Terraform {#tf}

    1. В терминале перейдите в директорию с планом инфраструктуры.
    
        {% note warning %}
    
        Убедитесь, что в директории нет Terraform-манифестов с ресурсами, которые вы хотите сохранить. Terraform удаляет все ресурсы, которые были созданы с помощью манифестов в текущей директории.
    
        {% endnote %}
    
    1. Удалите ресурсы:
    
        1. Выполните команду:
    
            ```bash
            terraform destroy
            ```
    
        1. Подтвердите удаление ресурсов и дождитесь завершения операции.
    
        Все ресурсы, которые были описаны в Terraform-манифестах, будут удалены.

{% endlist %}