[Документация Yandex Cloud](../../../../index.md) > [Yandex Network Load Balancer](../../../index.md) > [Практические руководства](../../index.md) > [Миграция сервисов с балансировщика NLB на L7-балансировщик ALB для подключения защиты Smart Web Security](../index.md) > [Балансировщик NLB с целевыми ресурсами из кластера Managed Service for Kubernetes](index.md) > Terraform

# Миграция сервисов с балансировщика NLB с целевыми ресурсами из кластера Yandex Managed Service for Kubernetes на L7-балансировщик ALB с помощью Terraform

# Миграция сервисов с балансировщика NLB с целевыми ресурсами из кластера Yandex Managed Service for Kubernetes на L7-балансировщик ALB с помощью Terraform


{% note warning %}

Часть ресурсов, необходимых для прохождения практического руководства, доступны только в [регионе Россия](../../../../overview/concepts/region.md).

{% endnote %}


Чтобы мигрировать сервис с сетевого балансировщика на L7-балансировщик:

1. [Ознакомьтесь с рекомендациями по миграции сервисов](#recommendations).
1. [Создайте инфраструктуру](#deploy).
1. [Установите Ingress-контроллер Application Load Balancer и создайте ресурсы в кластере Managed Service for Kubernetes](#install-ingress-nginx). На этом этапе вы подключите профиль безопасности Smart Web Security к L7-балансировщику.
1. [Проверьте работу L7-балансировщика](#test).
1. [Мигрируйте пользовательскую нагрузку с сетевого балансировщика на L7-балансировщик](#migration-nlb-to-alb).

## Рекомендации по миграции сервисов {#recommendations}

1. Подключите защиту от DDoS-атак на уровне L3-L4 ([модель OSI](https://ru.wikipedia.org/wiki/Сетевая_модель_OSI)). Она станет дополнением к защите на уровне L7, которую после миграции обеспечит [Yandex Smart Web Security](../../../../smartwebsecurity/index.md).

    Чтобы подключить защиту на уровне L3-L4:

    1. Перед миграцией [зарезервируйте статический публичный IP-адрес с защитой от DDoS-атак](../../../../vpc/operations/enable-ddos-protection.md#enable-on-reservation) и используйте этот адрес для обработчика L7-балансировщика. Если для сетевого балансировщика публичный IP-адрес с защитой уже есть, его можно сохранить при миграции. В противном случае IP-адрес придется поменять на защищенный.

    1. Настройте порог для срабатывания механизмов защиты, который будет соответствовать объему легитимного трафика на защищаемый ресурс. Для настройки такого порога обратитесь в [техническую поддержку](https://kz.center.yandex.cloud/support).

    1. [Задайте](../../../../vpc/operations/adjust-mtu-ddos-protection.md) значение MTU равным `1450` на целевых ресурсах за балансировщиком. Подробнее в разделе [MTU и TCP MSS](../../../../vpc/concepts/mtu-mss.md).

1. Проводите миграцию в часы наименьшей пользовательской нагрузки. Если вы решили сохранить публичный IP-адрес, то во время миграции ваш сервис будет недоступен, пока этот IP-адрес переносится с сетевого балансировщика на L7-балансировщик. Обычно это занимает несколько минут.

1. При использовании L7-балансировщика запросы на бэкенды приходят с IP-адресом источника из диапазона внутренних IP-адресов подсетей, указанных при создании L7-балансировщика. Исходный IP-адрес источника запроса (пользователя) фигурирует в заголовке `X-Forwarded-For`. Если необходимо логировать публичные IP-адреса пользователей на веб-сервере, [измените его конфигурацию](../../../../troubleshooting/application-load-balancer/how-to/getting-external-src-ip-in-x-forwarded-for-headers.md).

1. Перед миграцией определите минимальное количество ресурсных единиц для настройки [автомасштабирования](../../../../application-load-balancer/concepts/application-load-balancer.md#lcu-scaling) в L7-балансировщике.

    Количество ресурсных единиц выберите на основе анализа нагрузки на ваш сервис по следующим показателям:

    * количество запросов в секунду (RPS);
    * количество одновременных активных соединений;
    * количество новых соединений в секунду;
    * объем трафика в секунду.

1. Функциональные возможности балансировщика Application Load Balancer могут отличаться от возможностей, используемых в вашем балансировщике, развернутом в кластере Managed Service for Kubernetes. Ознакомьтесь с описанием [Ingress-контроллера Application Load Balancer](../../../../application-load-balancer/tools/k8s-ingress-controller/index.md) и [принципами его работы](../../../../application-load-balancer/tools/k8s-ingress-controller/principles.md).

1. Настройте проверки состояния бэкендов на балансировщике Application Load Balancer. Благодаря проверкам состояния балансировщик своевременно отслеживает недоступные бэкенды и направляет трафик на другие бэкенды. После обновления приложения трафик будет снова распределен на все бэкенды.

    Подробнее в разделах [Рекомендации по настройке проверок состояния Yandex Application Load Balancer](../../../../application-load-balancer/concepts/best-practices.md) и [Аннотации (metadata.annotations)](../../../../application-load-balancer/k8s-ref/service-for-ingress.md#annotations).

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

Сервисы Managed Service for Kubernetes, которые используются в качестве бэкендов, должны иметь тип `NodePort`. Если ваши сервисы используют другой тип, измените его на `NodePort`. Подробнее об этом типе смотрите в документации [Kubernetes](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport).

## Создайте инфраструктуру {#deploy}

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

1. Скачайте в ту же рабочую директорию файл конфигурации в зависимости от используемого протокола:
    * `HTTP` — файл конфигурации [alb-k8s-http.tf](https://github.com/yandex-cloud-examples/yc-nlb-alb-k8s-migration/blob/main/alb-k8s-http.tf).
    * `HTTPS` — файл конфигурации [alb-k8s-https.tf](https://github.com/yandex-cloud-examples/yc-nlb-alb-k8s-migration/blob/main/alb-k8s-https.tf).

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

    * [подсети](../../../../vpc/concepts/network.md#subnet) для L7-балансировщика;
    * [группа безопасности](../../../../vpc/concepts/security-groups.md) для L7-балансировщика;
    * статический адрес для L7-балансировщика;
    * импорт TLS-сертификата в Certificate Manager (если используется протокол `HTTPS`);
    * профиль безопасности Smart Web Security.

1. В конфигурационном файле укажите значения переменных:

    * `domain_name` — имя домена вашего сервиса.
    * `network_id` — идентификатор сети, в которой находятся виртуальные машины из целевой группы сетевого балансировщика нагрузки.
    * `certificate` (если используется протокол `HTTPS`) — путь к файлу самоподписанного пользовательского сертификата.
    * `private_key` (если используется протокол `HTTPS`) — путь к файлу с закрытым ключом.

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

    ```bash
    terraform validate
    ```

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

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

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

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

## Установите Ingress-контроллер Application Load Balancer и создайте ресурсы в кластере Managed Service for Kubernetes {#install-ingress-nginx}

{% note tip %}

Вместо ALB Ingress-контроллера и Gateway API рекомендуется использовать новый контроллер [Yandex Cloud Gwin](../../../../application-load-balancer/tools/gwin/index.md).

{% endnote %}

1. [Установите Ingress-контроллер Yandex Application Load Balancer](../../../../managed-kubernetes/operations/applications/alb-ingress-controller.md).

1. Создайте ресурс [IngressClass](../../../../application-load-balancer/k8s-ref/ingress-class.md) для Ingress-контроллера L7-балансировщика:

    1. Создайте YAML-файл, в котором опишите ресурс `IngressClass`.

        Пример ресурса `IngressClass`:

        ```yaml
        apiVersion: networking.k8s.io/v1
        kind: IngressClass
        metadata:
          labels:
            app.kubernetes.io/component: controller
          name: ingress-alb
        spec:
          controller: ingress.alb.yc.io/yc-alb-ingress-controller
        ```

    1. Создайте ресурс `IngressClass` с помощью команды:

        ```bash
        kubectl apply -f <файл_с_ресурсом_IngressClass>
        ```

1. Создайте ресурс `Ingress`:

    1. Ознакомьтесь с описанием [полей и аннотаций ресурса `Ingress`](../../../../managed-kubernetes/alb-ref/ingress.md) и [примером](../../../../managed-kubernetes/tutorials/alb-ingress-controller.md#create-ingress-and-apps).

    1. Создайте YAML-файл, в котором опишите ресурс `Ingress`:

        1. Заполните раздел [annotations](../../../../managed-kubernetes/alb-ref/ingress.md#annotations) для настроек L7-балансировщика:

            * `ingress.alb.yc.io/subnets` — идентификаторы подсетей в трех зонах доступности для узлов L7-балансировщика. Идентификаторы перечисляются через запятую без пробелов.
            * `ingress.alb.yc.io/security-groups` — идентификатор одной или нескольких групп безопасности для L7-балансировщика. Идентификаторы нескольких групп перечисляются через запятую без пробелов.
            * `ingress.alb.yc.io/external-ipv4-address` — зарезервированный ранее статический публичный IP-адрес.
            * `ingress.alb.yc.io/group-name` — имя группы ресурсов `Ingress`. Ресурсы `Ingress` объединяются в группы, каждая из которых обслуживается отдельным экземпляром Application Load Balancer с отдельным публичным IP-адресом.
            * `ingress.alb.yc.io/security-profile-id` — идентификатор созданного ранее профиля безопасности Smart Web Security.

                {% note warning %}

                Профиль безопасности будет привязан к виртуальному хосту L7-балансировщика. Подключение сервиса Smart Web Security невозможно без привязки профиля безопасности к виртуальному хосту L7-балансировщика.

                {% endnote %}

            * `ingress.alb.yc.io/autoscale-min-zone-size` — [минимальное количество ресурсных единиц](../../../../application-load-balancer/concepts/application-load-balancer.md#lcu-scaling-settings) в каждой зоне доступности в соответствии с ожидаемой нагрузкой на ваш сервис.

        1. Для поля `ingressClassName` укажите имя созданного ранее ресурса `IngressClass`.

        1. При использовании протокола HTTPS заполните раздел [tls](../../../../managed-kubernetes/alb-ref/ingress.md#tls):

            * `hosts` — доменное имя вашего сервиса, которому соответствует TLS-сертификат.
            * `secretName` — TLS-сертификат вашего сервиса в Yandex Certificate Manager в формате `yc-certmgr-cert-id-<идентификатор_сертификата>`.

        1. Заполните раздел [rules](../../../../managed-kubernetes/alb-ref/ingress.md#rule) в соответствии с правилами распределения входящего трафика по бэкендам в зависимости от доменного имени (поле `host`) и запрашиваемого ресурса (поле `http.paths`):

            * `host` — имя домена вашего сервиса.
            * `pathType` — тип указания на запрашиваемый ресурс:

                * `Exact` — путь в URI запроса должен совпадать со значением поля `path`.
                * `Prefix` — путь в URI запроса должен начинаться со значения поля `path`.

            * `path` — путь в URI входящего запроса (если тип `Exact`) или его начало (если тип `Prefix`).
            * `backend` — указание на [бэкенд или группу бэкендов](../../../../managed-kubernetes/alb-ref/ingress.md#backend), которые должны обрабатывать запросы с указанным доменным именем и путем в URI. Укажите либо сервис-бэкенд (`service`), либо группу бэкендов (`resource`), но не оба одновременно:

                * `service` — сервис Managed Service for Kubernetes, который должен обрабатывать запросы в качестве бэкенда:

                    * `name` — имя сервиса Managed Service for Kubernetes. Ресурс `Service`, на который указывает это поле, должен быть описан по [конфигурации](../../../../application-load-balancer/k8s-ref/service-for-ingress.md).
                    * `port` — порт сервиса, к которому будет обращаться `Ingress`. Для порта сервиса укажите либо номер (`number`), либо имя (`name`), но не оба одновременно.

                    {% note warning %}

                    Сервисы Managed Service for Kubernetes, используемые в качестве бэкендов, должны иметь тип `NodePort`.

                    {% endnote %}

                * `resource` — указание на группу бэкендов `HttpBackendGroup`, которые должны обрабатывать запросы. Бэкендами в такой группе могут быть сервисы Managed Service for Kubernetes и [бакеты Yandex Object Storage](../../../../storage/concepts/bucket.md). При использовании группы бэкендов доступна расширенная функциональность Application Load Balancer. Также можно указывать относительные веса бэкендов для пропорционального распределения трафика между ними.

                    * `kind` — `HttpBackendGroup`.
                    * `name` — имя группы бэкендов. Оно должно совпадать с именем, указанным в поле `metadata.name` ресурса `HttpBackendGroup`. Ресурс `HttpBackendGroup`, на который указывает это поле, должен быть описан по [конфигурации](../../../../application-load-balancer/k8s-ref/http-backend-group.md).
                    * `apiGroup` — `alb.yc.io`.

        Пример ресурса `Ingress`:

        ```yaml
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        metadata:
          name: <имя_ресурса>
          annotations:
            ingress.alb.yc.io/subnets: <идентификаторы_подсетей_в_трех_зонах_доступности>
            ingress.alb.yc.io/security-groups: <идентификатор_группы_безопасности_L7-балансировщика>
            ingress.alb.yc.io/external-ipv4-address: <статический_публичный_IP-адрес>
            ingress.alb.yc.io/group-name: <имя_группы_ресурсов>
            ingress.alb.yc.io/security-profile-id: <идентификатор_профиля_безопасности_Smart_Web_Security>
            ingress.alb.yc.io/autoscale-min-zone-size: <минимальное_количество_ресурсных_единиц_L7-балансировщика_в_каждой_зоне>
        spec:
          ingressClassName: <имя_ресурса_IngressClass>
          tls:
            - hosts:
                - <имя_домена_сервиса>
              secretName: yc-certmgr-cert-id-<идентификатор_сертификата>
          rules:
            - host: <имя_домена_сервиса>
              http:
                paths:
                - path: /
                  pathType: Prefix
                  backend:
                    service:
                      name: <имя_сервиса_Kubernetes>
                      port:
                        number: <443_или_другой_номер_порта>
        ```

    1. Создайте ресурс `Ingress` с помощью команды:

        ```bash
        kubectl apply -f <файл_с_ресурсом_Ingress>
        ```

1. По конфигурации ресурса `Ingress` будет развернут L7-балансировщик. Дождитесь завершения его создания и привязки к `Ingress` публичного IP-адреса. Этот IP-адрес понадобится для проверки запросов. Посмотреть информацию о ресурсе вы можете с помощью команды:

    ```bash
    kubectl get ingress <имя_ресурса_Ingress> -w
    ```

## Проверьте работу L7-балансировщика {#test}

Протестируйте запрос к сервису через L7-балансировщик. Например, одним из способов:

* В файле `hosts` на рабочей станции добавьте запись `<публичный_IP-адрес_L7-балансировщика> <имя_домена_сервиса>`. Удалите запись после тестирования.
* Выполните запрос с помощью [cURL](https://curl.se/) в зависимости от типа протокола:

    ```bash
    curl http://<имя_домена_сервиса> \
        --resolve <имя_домена_сервиса>:<порт_сервиса>:<публичный_IP-адрес_L7-балансировщика>
    ```

    ```bash
    curl https://<имя_домена_сервиса> \
        --resolve <имя_домена_сервиса>:<порт_сервиса>:<публичный_IP-адрес_L7-балансировщика>
    ```

## Мигрируйте пользовательскую нагрузку с сетевого балансировщика на L7-балансировщик {#migration-nlb-to-alb}

Выберите один из вариантов миграции:

* [Сохранить публичный IP-адрес для вашего сервиса](#save-public-ip).
* [Не сохранять публичный IP-адрес для вашего сервиса](#not-save-public-ip).

### Сохранить публичный IP-адрес для вашего сервиса {#save-public-ip}

1. Если у сетевого балансировщика используется динамический публичный IP-адрес, [сделайте его статическим](../../../../vpc/operations/set-static-ip.md).

1. В сетевом балансировщике [удалите все обработчики](../../../operations/listener-remove.md) для освобождения статического публичного IP-адреса. После этого ваш сервис не будет доступен через сетевой балансировщик.

1. В L7-балансировщике назначьте обработчику публичный IP-адрес, который ранее был у сетевого балансировщика:

    1. Откройте YAML-файл с описанием ресурса `Ingress`.
    1. В разделе `annotations` для поля `ingress.alb.yc.io/external-ipv4-address` укажите публичный IP-адрес, который ранее был у сетевого балансировщика.
    1. Примените изменения с помощью команды:

        ```bash
        kubectl apply -f <файл_с_ресурсом_Ingress>
        ```

1. Дождитесь завершения изменения публичного IP-адреса у ресурса `Ingress`. Посмотреть информацию о ресурсе вы можете с помощью команды:

    ```bash
    kubectl get ingress <имя_ресурса_Ingress> -w
    ```

    После изменения IP-адреса восстановится доступность вашего сервиса через L7-балансировщик.

1. Перейдите в L7-балансировщик:

    1. В [консоли управления](https://kz.console.yandex.cloud) перейдите в каталог, в котором находится кластер Managed Service for Kubernetes.
    1. Перейдите в сервис **Managed Service for&nbsp;Kubernetes**.
    1. Выберите нужный кластер.
    1. Слева выберите ![image](../../../../_assets/console-icons/timestamps.svg) **Сервисы и Ingress**, а в правой части — вкладку **Ingresses**. Для вашего `Ingress`-ресурса в столбце **Балансировщик** перейдите по ссылке на L7-балансировщик.
    1. Наблюдайте за пользовательской нагрузкой, поступающей на L7-балансировщик, на графиках [статистики работы балансировщика](../../../../application-load-balancer/operations/application-load-balancer-get-stats.md).

1. Удалите освободившийся статический публичный IP-адрес, который был зарезервирован для L7-балансировщика:

    1. Откройте конфигурационный файл, который вы использовали для создания L7-балансировщика (`alb-k8s-http.tf` или `alb-k8s-https.tf`).

    1. Удалите из файла описание ресурса `yandex_vpc_address`:

        ```hcl
        resource "yandex_vpc_address" "static-address" {
          description = "Static public IP address for the Application Load Balancer"
          name        = "alb-static-address"
          external_ipv4_address {
            zone_id                  = "ru-central1-a"
            ddos_protection_provider = "qrator"
          }
        }
        ```

    1. Примените изменения:

        1. В терминале перейдите в директорию с конфигурационным файлом.
        1. Проверьте корректность конфигурации с помощью команды:
        
           ```bash
           terraform validate
           ```
        
           Если конфигурация является корректной, появится сообщение:
        
           ```bash
           Success! The configuration is valid.
           ```
        
        1. Выполните команду:
        
           ```bash
           terraform plan
           ```
        
           В терминале будет выведен список ресурсов с параметрами. На этом этапе изменения не будут внесены. Если в конфигурации есть ошибки, Terraform на них укажет.
        1. Примените изменения конфигурации:
        
           ```bash
           terraform apply
           ```
        
        1. Подтвердите изменения: введите в терминале слово `yes` и нажмите **Enter**.

1. (Опционально) После переноса пользовательской нагрузки на L7-балансировщик [удалите сетевой балансировщик](../../../operations/load-balancer-delete.md).

### Не сохранять публичный IP-адрес для вашего сервиса {#not-save-public-ip}

1. Чтобы мигрировать пользовательскую нагрузку с сетевого балансировщика на L7-балансировщик, в DNS-сервисе, обслуживающем публичную зону вашего домена, измените значение A-записи для доменного имени сервиса на публичный IP-адрес L7-балансировщика. Если публичная зона домена была создана в [Yandex Cloud DNS](../../../../dns/index.md), то измените запись [по инструкции](../../../../dns/operations/resource-record-update.md).

    {% note info %}

    Миграция нагрузки может выполняться долго, так как распространение изменений в записи DNS зависит от времени жизни записи (TTL) и количества звеньев цепочки DNS-запросов.

    {% endnote %}

1. По мере распространения изменений в записи DNS наблюдайте за ростом запросов, поступающих на L7-балансировщик:

    1. В [консоли управления](https://kz.console.yandex.cloud) перейдите в каталог, в котором находится кластер Managed Service for Kubernetes.
    1. Перейдите в сервис **Managed Service for&nbsp;Kubernetes**.
    1. Выберите нужный кластер.
    1. Слева выберите ![image](../../../../_assets/console-icons/timestamps.svg) **Сервисы и Ingress**, а в правой части — вкладку **Ingresses**. Для вашего `Ingress`-ресурса в столбце **Балансировщик** перейдите по ссылке на L7-балансировщик.
    1. Наблюдайте за пользовательской нагрузкой, поступающей на L7-балансировщик, на графиках [статистики работы балансировщика](../../../../application-load-balancer/operations/application-load-balancer-get-stats.md).

1. Наблюдайте за снижением нагрузки на сетевой балансировщик с помощью [метрик балансировщика](../../../../monitoring/metrics-ref/network-load-balancer-ref.md) `processed_bytes` и `processed_packets`. Для визуализации этих метрик можно [создать дашборд](../../../../monitoring/operations/dashboard/create.md). Если нагрузка на сетевом балансировщике долгое время отсутствует, то перенос на L7-балансировщик завершен.

1. (Опционально) После переноса пользовательской нагрузки на L7-балансировщик [удалите сетевой балансировщик](../../../operations/load-balancer-delete.md).