Опыт миграции инфраструктуры клиента из AWS в Яндекс.Облако

image-loader.svg

Задача по миграции из одного облака в другое, на самом деле, довольно распространенная в нашей практике. Происходит это по разным причинам: ценовая политика облачного провайдера, требования местного законодательства, наличие отдельных преимуществ облака, в которое мы будем переезжать…

В этой статье мы расскажем про основные решения, которыми воспользовались в процессе одного из недавних переездов в Яндекс.Облако, и о некоторых особенностях, с которыми столкнулись во время эксплуатации. Основным мотивом к этой миграции было снижение ежемесячных расходов на облачную инфраструктуру (без существенного снижения качества эксплуатации).

NB: Статья больше именно про контекст переезда с одного облака на ЯО, чем технические детали миграции как таковой (ведь про «обычные» переносы инфраструктуры с одних серверов на другие уже рассказывалось не раз).

Итак, у клиента была инфраструктура в AWS, которая выглядела следующим образом:

  1. Kubernetes-кластер, управляемый нашим инструментом Deckhouse. Тут стандартный набор: EC2-инстансы, Elastic IP и прочие ресурсы.

  2. Несколько PostgreSQL-кластеров в RDS.

  3. Кластеры ElastiCache: Redis в production-окружении и development.

  4. Отдельный NAT-instance для обращения к внешним приложениям.

  5. S3-хранилище.

Задача — перенести её в Яндекс.Облако с минимальным простоем и в сжатые сроки.

План миграции

Как будем действовать? Из представленного ниже плана исключены действия, связанные с CI/CD, так как они не выглядят критичными в контексте этой статьи. Но если вкратце, то был реализован параллельный выкат приложения в обе инфраструктуры для того, чтобы код поддерживался в актуальном состоянии в обоих местах. Это помогло нам во время переезда, т.к. не требовалось тратить время на синхронизацию кода в новой инфраструктуре.

Сам же план переезда (до переключения) выглядел следующим образом:

  1. Создание Kubernetes-кластера в ЯО. Для нас это самый быстрый и простой этап, так как с Deckhouse всё автоматизировано и проверено ив работает на этой инфраструктуре. Из особенностей — клиенту важно, чтобы все приложения ходили через один адрес, поэтому требовалось создать NAT instance (подробности будут ниже).

  2. Миграция данных из RDS в Managed PostgreSQL. Основная задача этого этапа — получить удобный инструмент, с помощью которого мы, во-первых, всегда будем иметь актуальную базу данных в Яндекс.Облаке (там будет реплика данных из RDS), а во-вторых, сможем быстро активировать/деактивировать репликацию в момент переключения (в противном случае придется взаимодействовать с БД, работающей в режиме read-only). Соответственно, в момент переключения вторую СУБД нужно было делать мастером, отключив репликацию.

  3. Создание Redis-кластера вместо ElastiCache. Нужно было рассмотреть варианты с Managed Redis в ЯО или же self-managed на виртуальных машинах/в Kubernetes-окружении.

  4. Миграция статических файлов из S3 AWS в Object Storage ЯО. На данном этапе не требовалось постоянно держать актуальными бакеты в ЯО, поэтому выбрали способ с ручной синхронизацией перед переключением.

  5. Переезд остальных серверных приложений. Включал в себя Elasticsearch, Sentry и т.д. Здесь все предельно просто: требовалось добавить деплой этих приложений в новую инфраструктуру.

  6. Когда все вышеперечисленные пункты сделаны — выполнить само переключение.

Особенности переезда

1. Managed PostgreSQL

Важный момент во всей миграции — быстрое и по возможности беспростойное переключение кластера PostgreSQL в production-окружение в Яндексе. У Яндекса есть готовая альтернатива для RDS — Managed PostgreSQL, который мы использовали в качестве реплики во время подготовки к переключению. Этот способ удобен тем, что не нужно к очередной итерации готовить дамп базы данных: достаточно настроить логическую репликацию и дождаться синхронизации данных. Для этого решения даже написана инструкция, которая довольно просто и понятно объясняет, что нужно сделать с обеих сторон для достижения результата: в момент переключения требовалось отключить репликацию и сделать новую СУБД мастером, чтобы она не работала в режиме read-only.

Теперь об особенностях, проявившихся после миграции. Во время эксплуатации Managed PostgreSQL от Яндекса мы столкнулись с багом, связанным с изменением конфигурации СУБД, а конкретно при обновлении параметров log_min_duration_statement и log_statement (приведены ссылки на неофициальную документацию, т.к. в официальной нет явного указания, что ребут не требуется). Смысл в том, что при одновременном изменении этих настроек происходит рестарт экземпляров PostgreSQL, чего явно не должно происходить (как пример, в том же AWS такого не происходит). После обращения в поддержку проблема была исправлена в короткие сроки. Поэтому стоит напомнить, что изменение конфигурации нужно тестировать на dev«е.

Другая важная деталь — мониторинг. В панели Яндекса есть встроенный мониторинг основных показателей PostgreSQL-кластера и его узлов в частности: количество подключений к PostgreSQL, среднее время выполнения запроса, количество транзакций, а также другие метрики, связанные с потреблением ресурсов виртуальными машинами (пример на скриншоте).

Встроенная панель Яндекса для Managed PostgreSQLВстроенная панель Яндекса для Managed PostgreSQL

Также в панели можно проанализировать метрики производительности СУБД для сессий и запросов (они находятся в разделе «Диагностика производительности»), где можно увидеть, например, сколько ресурсов потребляет тот или иной запрос. Более подробно про использование этого инструмента можно почитать в официальной документации.

Данные варианты мониторинга кластера PostgreSQL нам не подошли:

  • обновления метрик в консоли происходят только раз в минуту;

  • не было метрик, которые требовались для диагностики проблем с блокировками запросов (хотя по ходу дальнейшей работы с ЯО мы видели, что там появляются и новые метрики).

Поэтому в качестве альтернативы можно рассмотреть внешние экспортеры, которые будут подключаться к PostgreSQL напрямую и собирать с него метрики в собственное хранилище (нам так даже удобнее).

Среди используемых нами средств для мониторинга инфраструктуры — сервис Okmeter. Им и воспользовались. С Okmeter можно получать больше информации о запущенном PostgreSQL-кластере. В данном случае, как уже отмечалось, в первую очередь интересовала скорость обновления метрик, а также графики по deadlocks и блокировкам таблиц, статистика по WAL«ам и т.п. Всё это стало доступным:

image-loader.svgПримеры полезных графиков для PostgreSQL, доступных «из коробки» в OkmeterПримеры полезных графиков для PostgreSQL, доступных «из коробки» в Okmeter

Конечно, аналогичным образом можно настроить и любой другой мониторинг. Надо лишь уметь его «готовить» и указать правильные credentials для подключения.

2. NAT

В Яндекс.Облаке существует два способа организации NAT:

  • с помощью отдельной виртуальной машины (данный тип виртуальных машин доступен в Marketplace);

  • включением NAT для нужной подсети в Virtual Private Cloud.

Так как второй вариант был в preview-версии, мы выбрали первый: создали виртуальную машину и стали отправлять трафик с виртуальных машин и Kubernetes-узлов с отдельной виртуальной машины. Конечно, данный вариант не является отказоустойчивым, так как завязывается на одну виртуальную машину и в случае ее отказа возникнет простой. Но для себя мы выбрали именно его из-за того, что функции NAT«a на уровне VPC еще не были рекомендованы для production, а сроки миграции были сжатыми (так что путь с минимальными сюрпризами предпочтителен).

В общем случае (если у вас есть такая возможность смелость) мы скорее рекомендуем попробовать второй вариант с включением NAT через VPC, хотя и на момент публикации он по-прежнему находится на стадии Preview. Особенно в ситуациях, когда для NAT требуется отказоустойчивость.

NAT-инстанс в Cloud MarketplaceNAT-инстанс в Cloud Marketplace

3. Redis

Предлагаемое Яндексом managed-решение мы не смогли использовать из-за того, что приложение клиента умело работать только с Redis 4.0, а эта версия не поддерживалась сервисом от Яндекса (на момент создания статьи). Поэтому мы выбрали оператор от Spotahome. Как уже рассказывали ранее, несмотря на некоторые его недостатки, считаем это решение наиболее стабильным из тех существующих, с которыми успели поработать. (Впрочем, мы не останавливаем поиски других вариантов — в частности, присматриваемся к redis-cluster-operator.)

Сами данные из Redis мы не мигрировали отдельно, так как потребности в этом не было.

4. Amazon S3 и Object Storage Яндекса

В сравнении с другими решениями, которые позволяют хранить статику, Object Storage совместим с S3 от AWS. Об этом и вообще о том, как работать с Object Storage, можно прочитать в документации. В нашей ситуации S3 в AWS занимал несколько терабайт и его тоже требовалось перенести в рамках миграции.

В качестве инструмента для миграции мы воспользовались rclone, запущенным в несколько потоков для сокращения времени копирования. Процесс копирования всех бакетов занял несколько дней, после чего мы отдельно синхронизировали ассеты, которые загружались после первой итерации.

Пример команды:

rclone lsd bucket-aws:/ | awk '{print $5}' | xargs -I {} rclone sync bucket-aws:{} bucket-yc:{}

Переключение

Когда эти шагиы были выполнены, осталось выполнить само переключение, которое оказалось тривиальным (мало чем отличается от переключения с одного сервера на другой):

  1. Перед переключением мы отключили репликацию на новом кластере PostgreSQL, загрузив дамп SEQUENCES для базы данных (она была одна и поэтому делать дополнительные усложнения не стали).

  2. Задеплоили актуальную версию приложения, после чего QA-инженеры со стороны клиента убедились, что все работает корректно.

  3. Поскольку работы проводились в «техническое окно», мы добавили на его время заглушку о проводимых работах на сайте (конкретно для этого проекта такой сценарий был допустим).

  4. Переключили DNS-записи на новую инфраструктуру. (Этот шаг можно было бы улучшить, использовав proxy-сервер, на котором переключались upsteam«ы на новую инфраструктуру и обратно.)

  5. После переключения произвели повторный запуск тестов от QA и убедились, что сайт работает корректно.

Результаты

Благодаря переезду в новое облако клиент сэкономил около 30% от предыдущей стоимости инфраструктуры. Эта разница измерялась сотнями тысяч рублей.

Хотя во время переключения и случались непродолжительные простои, за редким исключением они были согласованы с клиентом. Несогласованный downtime — последствие уже описанного бага в Managed PostgreSQL, когда после изменения параметров кластер был перезапущен (это привело к простою работы приложения, который в общей сложности составил около 10–15 минут).

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

Заключение

С помощью описанных инструментов и решений мы полностью мигрировали инфраструктуру клиента в новое облако, избежав критических проблем как во время, так и после переключения. Главная цель переезда — экономия на облачных ресурсах — была достигнута, а отличия в работе/возможностях AWS и Yandex.Cloud оказались незначительными для данного проекта.

Отдельно стоит упомянуть, что в процессе переезда мы обнаружили несколько багов в работе Яндекс.Облака, которые с помощью поддержки Яндекса были исправлены.

© Habrahabr.ru