OpenStack-грабли: как мы перезапустили облачную платформу Рег.ру

333bf9e255175912d704d6bf945ee8f8.png

Привет, Хабр! Я — Евгений Мартынов, директор по информационным технологиям Рег.ру. В последние пару лет я занимаюсь развитием облачной платформы. Сегодня я расскажу, как мы перезапустили это направление, с какими трудностями столкнулись и какие решения нашли. Дисклеймер: непосредственно грабли начну описывать во второй половине статьи, сначала расскажу, на каких принципах мы изначально строились в надежде избежать ошибок.

Навигация по тексту:

→ Откуда в Рег.ру облако?
→ Базовые принципы построения облака
Надёжность и отказоустойчивость
Open Source-компоненты
Сеть
→ Первые проблемы
→ Серьезные проблемы
→ Тушим пожары
→ Как у нас закончились IP-адреса
→ Биллинг тоже имеет свои узкие места
→ Запуск площадок
→ Кейсы с клиентами
Привет, я спамер, у меня есть 100 рублей
S3: сегодня на SSD, завтра на HDD
Мне нужен GPU на короткий срок
→ Внешние вызовы
→ И напоследок…

Откуда в Рег.ру облако?

Многие знают Рег.ру как регистратора и задаются вопросом — как связаны домены и облачные услуги? У нас несколько ответов.

Во-первых, Рег.ру входит в группу Рунити. Многие из компаний группы могут похвастаться большим опытом в роли поставщика услуг виртуального хостинга, VPS и других решений. Всё это базируется на комплементарном технологическом стеке — таком же, на котором крупные облачные провайдеры строят свои IaaS и PaaS-услуги. В частности, в одной из компаний нашей группы на протяжении нескольких десятилетий используется подход с контейнерным хостингом. Сначала это был jail, потом LXC и сейчас crun. Виртуализация для VPS в некоторых услугах строилась на базе OpenStack+KVM.

Во-вторых, мы, будучи крупным IT-игроком, имеем большую распределённую инфраструктуру с конкретными требованиями. Для размещения собственной инфраструктуры мы используем тот же стек, который предлагаем клиентам — OpenStack+KVM, объектное хранилище S3 и Kubernetes с самого его появления. В какой-то момент мы решили: если мы сами используем весь этот стек технологий в наших услугах и обладаем соответствующей экспертизой, то почему бы не выйти на облачный рынок?  

Сначала я расскажу о принципах нашей работы, которые помогают максимально избежать «граблей», а затем разберём те, которые всё-таки произошли.

Базовые принципы построения облака

Желание выйти на облачный рынок запустило процесс формирования требований к платформе, а также потребовало некоторых доработок и адаптации используемых решений. Мы заложили несколько базовых принципов построения платформы публичного и частного облака, используемого для собственной инфраструктуры и работы всех сервисов, в том числе и регистратора доменов.

1. Надёжность и отказоустойчивость

Наличие нескольких площадок необходимо для организации дублирования сервисов, что в результате обеспечивает высокую степень отказоустойчивости. Отсюда следует другой вопрос: если площадки разные, то они не должны иметь общие точки отказа, то есть быть недоступными одновременно. Мы этого не допускаем. При построении облачной платформы мы используем собственный control & network plane для каждой площадки (региона доступности).

Однако нужно не только разделять, но и объединять. Для этого мы предусматриваем широкие каналы связи, строим логику приватных сетей между дата-центрами и узлами. Это позволяет нам в дальнейшем развивать подходы кросс-бэкапирования между дата-центрами и репликации данных, а также настраивать маршрутизацию таким образом, чтобы при «схлопывании» одной площадки инфраструктура продолжала работать.

2. Open Source-компоненты 

Мы стараемся внедрять решения с открытым исходным кодом. Облачная платформа Рег.ру базируется на OpenStack KVM. Кроме того, мы активно используем Kubernetes, S3 и блочное хранилище на Ceph. Причин такого подхода несколько. Во-первых, мы не зависим от вендора и не боимся вендорлока. Во-вторых, мы можем самостоятельно дорабатывать решения. В-третьих, мы не теряем возможность установки обновлений от комьюнити продуктов, которые разрабатываются в том числе и с нашим влиянием. 

Мы также создаём managed сервисы в облаке по модели PaaS — в частности это относится к Kubernetes и базам данных (DBaaS).

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

Мы зафиксировали минимальный и максимальный набор нашего облака с точки зрения сетевого оборудования и серверного железа. Стараемся брать оборудование одних и тех же производителей, чтобы не сталкиваться ни с какими эксплуатационными сюрпризами. Можно сказать, что в какой-то мере мы строим инфраструктуру однотипно. Однако, забегая вперёд, скажу, что этот принцип соблюдается не всегда.

3. Сеть

При строительстве сети мы обязательно предусматриваем дублирование всех компонентов. Когда мы подключаем сервер compute ноды или сервер control plane, мы используем как минимум два патч-корда и два канала связи, чтобы соединиться с резервируемыми top of rack свчитчами. Эти свитчи, в свою очередь, соединены задублированными каналами с резервируемым ядром сети. Такая схема позволяет избежать отключения сервиса: работа будет продолжаться даже в случае отказа одного из компонентов или при необходимости его обслуживания.

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

Про публичные IP-адреса. Мы используем плавающие IP-адреса: это конструкция, не «прибитая гвоздиками» к конкретной сущности — например, к виртуальной машине не прописываем IP адреса на интерфейсы. Плавающие IP-адреса могут быть перенесены на другую виртуальную машину, роутер или балансировщик нагрузки при помощи внешнего управляющего воздействия. Мы применяем этот подход для обеспечения доступности сервисов по публичному адресу.

Первые проблемы

Запустили систему и начали принимать поток клиентов — всё, казалось бы, хорошо, всё рассчитано. Мы примерно знали, когда могут возникнуть первые узкие места. Однако проблемы появились гораздо раньше, чем мы ожидали.

Мы запустили первый узел связи и саму платформу OpenStack, а затем начали параллельно развивать второй узел, как и планировали. Дошли до 2000 услуг, что приблизительно соответствует 2000 клиентам. Однако у нас возникли первые проблемы в сети. У новых услуг, запущенных в этом регионе, иногда терялась связность по внешнему IP-адресу. Погрузившись в проблему глубже, мы поняли, что у нас возникли трудности из-за нехватки памяти в слое управления OpenStack.

На этом моменте у читателей наверняка возникнет вопрос. «Почему кончилась память? Вы ведь, наверное, делали на старте прогноз, когда столкнётесь с такой проблемой». Да, действительно, расчеты были —, но в них присутствовали некоторые допущения. Когда запускаешь сервис или новый проект, бывают моменты, когда можно немного сэкономить, особенно когда клиентов ещё нет, а расширение схемы возможно на лету. Зачем сразу разворачивать большое количество оборудования, если его можно будет добавить в online?  

Мы думали, что будет время расшириться позже, когда появятся клиенты. Это стало нашей первой ошибкой. На период отсутствия клиентов мы совместили control plane с network plane на одних физических нодах и не учли этот момент в наших предварительных расчетах. Не сказать, что у нас не было мониторинга; он также сигнализировал о возникшей проблеме. Однако у нас почти не оказалось времени на разрешение ситуации после срабатывания предупреждающего пробника.

Мы разделили control-plane и network plane на разные физические ноды, в результате чего ситуацию удалось стабилизировать. При этом мы осознавали, что текущая конструкция всё ещё не оптимальна и не позволяет достигнуть проектных расчетов. У нас 15–20 серверов compute node, а управляют ими целых шесть серверов control plane. Такая схема выглядит не очень масштабируемой и прогнозируемой. 

182aeb592cf982ac63e69b6b7cfa0ba0.png

Серьёзные проблемы

Нашей параллельной задачей был запуск второй локации. Мы понимали, что когда-нибудь займемся увеличением вместимости каждого узла, но в тот момент достигали расширяемости за счет второго узла. Мы думали, что у нас много времени, но его не оказалось. Когда на первом узле стало 3000 услуг, Neutron (система сетевого управления) начала тормозить и перестала справляться с выполнением своих задач. В результате в сети начали теряться пакеты и IP-адреса для виртуальных машин. В частности проблема затронула пакеты, связанные с назначением IP-адресов через DHCP. Инцидент оказался довольно серьёзным и затронул уже большее количество клиентов.

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

Для стабилизации первого региона мы занялись его чисткой. Сначала мы удалили неиспользуемые тестовые виртуальные машины для освобождения ресурсов. Затем углубились во внутренний анализ. В жизненном цикле процессов схемы постоянно происходят динамические изменения: клиенты приходят, покупают и уходят, и вся эта история оставляет след. В таблицах Neutron, Open vSwitch и т.п. накапливается много «мусора», который OpenStack просто игнорирует. Мы нашли тот самый золотой ключик: очистив эту информацию, мы стабилизировали ситуацию в этом регионе. Мы выиграли битву, но не войну — зато у нас появилось чуть больше времени.

61053c88157c3418edf17e21c3ca4c8c.png

Тушим пожары

К счастью, с тех пор мы не сталкивались с аналогичными проблемами — на этот раз нам хватило времени разобраться с ситуацией. Первое, что мы сделали — дожали разделение Control и Network plane, так как на момент возникновения первой проблемы мы разнесли ещё не все необходимые службы.

Также мы провели очистку мусора и разработали различные механики для поддержки чистоты — например, зачистка связанных объектов вместе с удалением ресурса или регулярное избавление от ненужного с помощью дополнительных механизмов. В результате теперь у нас полностью реализован garbage collecting & house keeping: мы больше не оставляем мусор в системе.

Третья история, которая стала частью изменений, заключалась в переносе DHCP-агентов с network plane нод непосредственно на compute ноды. Это позволяет виртуальным машинам получать динамические адреса без необходимости проходить через множество промежуточных звеньев (например, физические интерфейсы). Благодаря этому риски потери IP адреса практически нивелированы и сведены к минимуму.

Четвёртая немаловажная история — это переход на статические адреса для приватных сетей. Как я упоминал ранее, мы выделяем приватные сети каждому клиенту, и IP из этих сетей также назначались при помощи DHCP. Переход на статическую адресацию значительно снизил внутренний трафик, уменьшил количество DHCP-агентов, и в целом ситуация стала более управляемой и стабильной.

Пятый, но не менее важный элемент стабилизации — это полный переход на концепцию DVR (Distributed Virtual Routing) с переносом роутеров непосредственно на compute-ноды. Это решение позволяет отправлять и получать трафик в интернет в обход network plane. Такая схема позволяет нам держать уже около 7 тысяч услуг (14000vcpu/20Tb Ram) в одном регионе, а в дальнейшем стремимся достичь проектного показателя в 10 тысяч услуг.

5ed1246d39e728acce38e023e218463d.png

Как у нас закончились IP-адреса

Новая задача не заставила себя ждать. Хотя она и не имеет масштаба супер инцидента, но всё же довольно неприятна. Пока мы реализовывали описанные выше изменения, наши IP-адреса исчерпались. На старте проекта мы заложили достаточное количество IP-адресов. По нашим расчётам их должно было хватить даже с запасом при росте числа клиентов в два, а то и в три раза. В результате мы даже начали покупать IP-адреса на рынке и доставать их из других проектов. Почему же так произошло? Давайте разберёмся, куда уходили наши публичные IP-адреса.

Мы даём один плавающий IP-адрес всем виртуальным машинам. Почему именно так? Мы хотим перенять некоторые подходы хостинга, где клиенты ожидают немедленного доступа к виртуальной машине по публичному IP-адресу. Обычно на таких услугах только один IP-адрес на интерфейсе — на нём организуется и сервис и доступ. При этом мы предусмотрели возможность отключения IP, если в нём нет необходимости. Такие IP адреса были заложены проектно.

В результате внедрения концепции DVR ещё один публичный IP адрес расходовался на обеспечение маршрутизации на виртуальном роутере в качестве шлюза, а второй — непосредственно на compute-нодах для внутренней маршрутизации. Оба этих IP-адреса были публичными, что создавало дефицит белых адресов. Однако переход на приватные IP-адреса меняет схему маршрутизации: появляются новые элементы, такие как NAT, и его необходимо реализовать без прерывания работы у клиентов. Это добавляет сложности в процесс миграции. Решение заняло несколько месяцев, но в итоге мы смогли перейти на использование приватных адресов для этих двух лишних IP, освободив около 5000 белых IP-адресов для дальнейшего использования под клиентов и сервисы.

Биллинг тоже имеет свои узкие места

Биллинг позволяет клиентам выбирать, как оплачивать услуги: почасово или помесячно. Для подтверждения предоставления услуги есть агенты, которые проверяют статус сервиса и запускают процесс биллинга. Однако агенты начали приходить всё позже относительно старта услуг. Это привело к возможности использования услуг без оплаты в течение многих часов. Оказалось, для всех основных операций биллинг производит расчеты транзакций за всю историю существования услуги. Соответственно, со временем эти расчеты замедляются, а очередь перегружается. В итоге был риск возникновения полного коллапса. Мы внедрили понятие операционных дней: теперь все предварительные транзакции уже подсчитаны отдельно, и любая операция в биллинге стала выполнять в разы меньше вычислений.

Параллельно с этим мы перешли с Perl на Python, переписали код и перенесли очередь из SQL на Rabbit. Это решение позволило нам значительно ускорить процессы и начать обрабатывать данные практически в реальном времени. Теперь мы умеем считать не только часы, но и минуты.

Запуск площадок

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

За это время на площадке побывало много разных инженеров. Мы часто пользовались службой инженеров ЦОД для выполнения некоторых работ. В итоге непосредственно перед запуском мы получили ряд проблем — с поломанными DAC/AOC-кабелями, неправильно обжатой медью, неверными коммутациями и в целом плохой организацией cable-менеджмента для возможности простого обслуживания.

На будущее мы расширили свой горизонт планирования — заказываем оборудование заранее. А на площадку для запуска посылаем только определенных инженеров с командировками для предстартовых работ.

Самое кармическое в этой истории — то, что через неполный год появилась информация о сносе площадки в Санкт-Петербурге для дальнейшей застройки. Но это позволило нам переехать на стандартизованное оборудование, которое к тому моменту уже было в наличии. Сам переезд занял всего 2 месяца и прошел полностью в онлайне. 

Все последующие запуски (Санкт-Петербург и Самара) прошли уже без сюрпризов.

Кейсы с клиентами

1. Привет, я спамер, у меня есть 100 рублей

У нас завёлся спамер. Очень продвинутый спамер. Он создавал много аккаунтов, зачислял по 100 рублей, запускал по 10 облачных серверов и уже через несколько минут после старта рассылал десятки тысяч писем. Мы блокировали карты, IP-адреса, cookie и прочие общие паттерны, но спамер быстро адаптировался. А тем временем целые блоки наших сетей постоянно попадали в различные черные списки.

В итоге нам пришлось полностью заблокировать 25-ый порт для новых клиентов, не прошедших идентификацию. Это позволило значительно снизить вероятность попадания в блэк-листы.

383a0530b0055e6c19de94f0633621e8.png

2. S3: сегодня на SSD, завтра на HDD

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

Клиент заказал у нас частную инсталляцию S3. Мы подняли её на SSD-дисках — согласно предварительным договорённостям и ТЗ. Через месяц клиент решил расширяться — для этого ему потребовалось гораздо больше объёма. Одновременно с этим выяснилось, что для его задач не нужны такая скорость и iops, которые выдавала инсталляция на SSD-дисках. Вполне резонно полагать, что на HDD мы можем дать больший объём за меньшую стоимость. 

Эта история потребовала значительного изменения инфраструктуры, а также дополнительных временных, трудовых и финансовых затрат. Однако этот опыт подарил нам важный урок: необходимо иметь разнообразие в публичном облаке. Кроме того, мы научились делать миграции.

3. Мне нужен GPU на короткий срок

Примерно та же ситуация наблюдается и с графическими процессорами (GPU). Клиенты берут их большими партиями, но сейчас видеокарты стоят дорого — например, A100 уже около 2,5 млн. У нас есть клиенты, заказывающие сервера с такими картами. Но далеко не всегда карты берут на долгий срок, за который мы бы могли их окупить. Поколения карт тоже меняются, а новый клиент на них может и не появиться. При этом прослеживается спрос на краткосрочную аренду, но комплектовать целый сервер определенной конфигурации на несколько дней или часов не целесообразно.

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

Внешние вызовы

Помимо внутренних трудностей, нашей команде регулярно приходится справляться и со внешними вызовами. Один из них — закон о связи, который не обошёл и нас. Правки в 406-ФЗ в 2023 году продиктовали новые требования, согласно которым мы включились в реестр хостинга. Дело в том, что с точки зрения закона облачные провайдеры, предоставляющие инфраструктуру, не отличаются от провайдеров хостинга. Соответственно, мы обязаны ввести идентификацию клиентов, подключиться к ГосСОПКА и выполнять план по установке СОРМ. Конечно, мы во всём этом участвуем.

У нас есть несколько инсталляций VMware для клиентов. Хотя VMware ушла из России, нам удалось найти специализированные компании для поддержки этого продукта и получать своевременный доступ к необходимым обновлениям. 

Также не стоит забывать, что находится под капотом сложных составных сервисов. В OpenStack/Kubernetes много компонентов: их появление или обновление стало причиной переносов нескольких запусков managed-услуг (например, KaaS). С одной стороны, запускаться лучше на проверенных временем решениях. А с другой — оно может послужить ловушкой для возможности дальнейшего развития, либо же не даст требуемой функциональности или должной безопасности. Ловим баланс.

И напоследок…

С момента старта мы увеличили команды разработки почти вдвое. У нас есть две отдельные команды — разработка платформ (базовых решений и архитектур облака) и продуктовой разработки (доставки до клиента/ЛК/биллинги). Несколько раз мы переорганизовывали команды внутри, выстраивали процессы, работу по спринтам, параллельное выполнение задач, совместные планирования, появление и соблюдение сроков/дедлайнов, появлялись новые роли и экспертизы. Мы реорганизовали команду так, чтобы Рег.ру ассоциировался не только с регистрацией доменов, но и с облачными технологиями. И хотя мы еще на начальном этапе, я верю, что у нас всё получится.

© Habrahabr.ru