Принимайте участие в зарплатном опросе! Уже собрано почти 8 000 анкет.

От легаси к Service Fabric за 360 часов. История одной миграции

Статья посвящена бесконечной борьбе с legacy. Это история о том, что можно сделать, если взять двух разработчиков (второй — для код-ревью) и 360 часов. А также о том, как перенести легаси-код в модный и молодежный клауд-сервис. Код с пошаговой инструкцией тут. Это репозиторий с примером переноса .NET Core Web API как stateless-сервиса Azure Service Fabric c секьюрити, API versioning и т. п.

Начало

Customer: We need to add a new feature to the legacy system, can you give an estimate?
Developer: It depends on when the legacy system will be replaced?
Customer: In five months.
Developer: Then the new feature will take six :)

Иногда кажется, что поработать с новыми технологиями на проекте не представляется возможным, но это не так. Если знать о планах, процессах и проблемах клиента, то в результате можно предложить новый функционал, основанный на технологиях, для которых нужен fancy tech.

У меня процесс стартовал с обсуждения возможности масштабирования части платформы и уменьшения latency-запросов. Проблемная часть системы была построена на старых сервисах Windows Communication Foundation с классической трехслойной архитектурой. WCF-фреймворк — это SOAP-монстр, но надежный и с широким функционалом, в 2010 году он был основой для Enterprise-решений. На этом же этапе поддержка сервисов и DevOps-задачи забирали приличный объем времени.

Оптимальным считается подход Lift and Shift, который подразумевает перенос сервисов в облако на виртуальные машины с дальнейшим постепенным разделением и рефакторингом на отдельные компоненты. Но такой подход не входил в мои планы, хотя на первый взгляд физически и экономически он выглядел вполне разумно. С другой стороны, перенос кода на .NET Core Web API было достаточно сложно оценить. В результате я сделал PoC за несколько выходных, чтобы оценить возможные риски. Конечно же, оценку рисков стоит начать с проверки качества текущего кода, проверить, живы ли Unit-тесты и т. п. Важно также не планировать отпуск, пока миграция не завершилась успешным развертыванием :)

Почему Service Fabric, а не Kubernetes

Focus on development, not on the infrastructure

Одной из проблем при переходе на новые фреймворки и технологии является повышение сложности систем. Связка Kubernetes + Docker буквально означала, что в результате я получу такой объем DevOps-задач, как и при работе с WCF-сервисами, развернутыми на VMware-фермах.

Эффект IKEA — это когнитивное искажение, которое появляется, когда покупатели непропорционально высоко оценивают значимость (ценность) товаров, которые они создают отчасти сами (Wikipedia).

Простой совет: если сложно сформировать мысль о том, зачем нужна оркестрация контейнеров, то и думать о ней не стоит. Если получилось понять зачем, тогда следует уточнить, нельзя ли сделать это с помощью Serverless-архитектуры. Когда преимущества ясны, тогда дальше статью можно не читать :)

Одной из моих задач было сокращение объема maintenance и DevOps-активностей, чтобы освободить время на разработку нового функционала. Azure Service Fabric после небольшого PoC полностью удовлетворил этим требованиям, плюс кривая обучения гораздо более пологая в сравнении с Kubernetes.

Почему Azure Service Fabric?

  • Сокращение цикла разработки.
  • Почти полное отсутствие DevOps-задач.
  • Простой деливери с помощью Azure DevOps CI/CD pipelines.
  • Надежный scale-out and scale-in и отказоустойчивость.
  • Простая разработка, кластер ASF запускается на ПК разработчика.

Оценка

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

Главное, с чего стоит начать, это с проверки зависимостей и NuGet-пакетов на совместимость с .NET Standard 2.0. Мне повезло, и тут проблем не оказалось.

Что было сделано во время PoC?

  • Проверка зависимостей на совместимость с .NET Standard 2.0.
  • Создание кластера Azure Service Fabric с подходящей конфигурацией VM.
  • Проект с stateless-сервисом Azure Service Fabric.
  • Публикация сервиса в облако и создание нескольких простых нагрузочных тестов с помощью Postman и Loader.io.

Пример создания кластера с помощью CLI из воркшопа для Azure Bootcamp Lviv

Что нужно не забыть при оценке проекта?

  • Использовать данные, полученные на этапе PoC.
  • Добавить время на Infrastructure as Code и настройку CI/CD через Azure DevOps.
  • Об установке дополнительных сертификатов и о работе с Azure Key Vault.
  • Определиться с секьюрити и выбрать Identity-провайдера.
  • Учесть в оценке стоимость работы Dev, Test and Stage энвайронментов.
  • Не забыть о мониторинге (и начать с него).

Если взять за основу месяц, два спринта и количество часов в районе 300, то все получится. Нужно подготовить список преимуществ и проблем, которые будут решены в результате завершения проекта. Упомянуть уменьшение времени (стоимости) будущих изменений и указать на пользу в ближайшем будущем.

Security — это просто и сложно одновременно. Если сервисы используются внутри сети, то необходимо развернуть Azure VNet и Network Security Group для ограничения доступа к сервисам из интернета. Если же подразумевается открытый доступ, то, имхо, оптимальный вариант — это Identity as a Service в виде Azure AD B2C, OAuth 2.0 или самописного решения на Identity Server 4.

Что нужно знать перед работой с сервис-фабрикой

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

Во-первых, нужно знать разницу между The durability tier и The reliability tier и для чего они нужны.

А во-вторых, понимать, что кластеры Azure Service Fabric работают на тех же Virtual Machine Scale Sets (VMSS), которые используются в Azure App Service. Если с VMSS уже опыт был, тогда переход будет легким. Стоит помнить, что выполнять манипуляции с VMSS в Service Fabric надо только после полного уяснения терминов выше.

Кластер ASF

Cluster: A network-connected set of virtual or physical machines into which your microservices are deployed and managed. Clusters can scale to thousands of machines.

Node: A machine or VM that’s part of a cluster is called a node. Each node is assigned a node name (a string). Nodes have characteristics, such as placement properties. Each machine or VM has an auto-start Windows service, FabricHost.exe, that starts running upon boot and then starts two executables: Fabric.exe and FabricGateway.exe. These two executables make up the node.

Сколько нужно нод и машин в VMSS? Для старта я бы использовал 3 ноды. После первых нагрузочных тестов конфигурацию и количество машин в VMSS можно изменить в любую сторону. Протестируйте нагрузку, и если при нужном вам количестве запросов в минуту (например, 1000) задержки ниже 200 мс, то можно оставить как есть.

Primary-нода в Service Fabric кластере выполняет задачи, связанные с оркестрацией кластера, и делит ресурсы вашего приложения с системными сервисами. Поэтому не стоит удалять и делать эксперименты на ней, а также производить операции scale-up и scale-in без предварительных тестов.

Обязательно нужно различать кластеры durability и reliability tiers. Знать ограничения, касающиеся понижения уровня с золотого до серебряного и т. п. Если вы оценили нагрузку на старые WCF-сервисы и выполнили нагрузочное тестирование API, то после настройки VMSS scale-out можно спать спокойно.

Перенос кода

План был достаточно простым.

  • Перенести код из WCF в Web API.
  • Добавить API в stateless ASF-проект.
  • Добавить все секреты и сертификаты в Azure Key Vault.
  • Распределить функционал по нескольким сервисам.
  • Протестировать результат.

Переносим код. Это несложная операция, требующая внимания и покрытия тестами :) Этап начался с переноса WCF-сервисов в контроллеры Web API, используя правило: 1 сервис => 1 контроллер. Компоненты 3-tier-архитектуры легко переносятся в Onion-архитектуру с composition root в Startup.cs (детали вне контекста этой статьи).

После того как перенос кода выполнен, стоит протестировать результат: сделать набор запросов к API и прогнать с помощью Postman. Если HTTP 200, то можно приступать к рефакторингу старых Unit- и Integration-тестов.

Устанавливаем Azure Service Fabric SDK. К сожалению, компоненты локального кластера не работают нормально с Visual Studio 2019, по-прежнему необходима установленная Visual Studio 2017. Перегружаемся и получаем информационное сообщение о запуске локального кластера ASF. После перезагрузки и автоматического запуска кластера стоит сразу уменьшить capacity до 1 ноды, чтобы не тратить ресурсы VM впустую.

Создаем проект Service Fabric с stateless-сервисом для Web, запускаем и переходим по URL созданного контроллера для проверки. Затем заменяем созданное веб-приложение Web API и изменяем GUID проекта в sln-файле. Собираем проект, запускаем и затем проверяем контроллеры с помощью набора запросов в Postman. Вуаля!

Разбиваем сервис на несколько логических частей. Руководствоваться стоит данными по нагрузке, собранными на этапе эстимирования, и здравым (!) смыслом. В описанном выше случае 10 WCF-сервисов поместились в 3 Web-сервиса. Нагрузка при этом оказалась неравномерной, и много ресурсов VMSS (Standard_D1_v2) попросту простаивали. К сожалению, серебряной пули нет и придется проверять нагрузку с помощью нагрузочных тестов. В идеале запускать нагрузочные тесты лучше из Azure DevOps, для этого создать нужное число аккаунтов и использовать бесплатный объем тестов из каждого ;)

К сожалению, к моменту запуска не все тесты в солюшене были переписаны под новое .NET Core приложение :(

Конечно же, были и проблемы

Оказалось, что подход Infrastructure as Code подкинул проблем. При попытке создать кластер фабрики через портал с названиями из скрипта Azure CLI названия не проходят валидацию в инпутах :) Видимо, на портале валидация слегка устаревшая, так как инфраструктурные скрипты продолжают выполняться.

Вывод: не используйте GUI, описывайте вашу инфраструктуру в коде и храните ее в Git или хотя бы в проектной Wiki.

Правильная настройка конфигурации environment variables была изначально упущена, и пришлось поиграть, чтобы решить проблему с помощью xml-конфигурации ASF. Вот статья о том, как это правильно сделать для фабрики.

Цена кластера из 5 нод будет в районе 500 долларов США в месяц. Чтобы уменьшить цену минимум в 3 раза, нужно использовать Linux-машины с shared compute типа Standard_B2s и контракт на 3 года. Но тут надо трезво оценить свои силы (время), так как проект .NET Core Web API, скорее всего, не запустится сразу под Linux.

Установка сертификатов кластера тоже имеет специфику и лучшим образом выполняется только с помощью PowerShell-скриптов. Внимательно отнеситесь к эстимированию задач по деплойменту ;) И храните секреты (сертификаты) в Azure Key Vault. Но если надо, то ниже скрипт для установки сертификатов в кластере.

Полезно разобраться в том, как работает Load Balancer, каковы принципы работы Reverse Proxy, что такое VNet и почему нужна Network Security Group. Но, строго говоря, для старта достаточно двух действий: добавления Load Balancer порта 443 и health probe для этого порта. И не забыть удалить порт 80 :)

Для администрирования кластера я использую PowerShell и Azure CLI

Заключение

Как показал опыт, инвестиция своего времени окупается в будущем. Миграция прошла практически без проблем, но дальнейшего роста кластера не последовало. Ответом на рост нагрузки стал перенос кода в Serverless-решения.

Что я бы сделал сейчас по-другому? В принципе, многое. Как минимум перенес бы часть нагруженных сервисов на FaaS в виде Azure Functions с увеличением эстимейта. Но это уже совсем другая история. С учетом требований этот проект оправдал себя. Cheers!

Полезные ссылки:


Если будут вопросы, пишите мне в Twitter.

LinkedIn

11 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.
Главное, с чего стоит начать, это с проверки зависимостей и NuGet-пакетов на совместимость с .NET Standard 2.0. Мне повезло, и тут проблем не оказалось.

Повезло — это слишком мягко сказано.

>

Переносим код. Это несложная операция, требующая внимания и покрытия тестами :) Этап начался с переноса WCF-сервисов в контроллеры Web API, используя правило: 1 сервис => 1 контроллер. Компоненты 3-tier-архитектуры легко переносятся в Onion-архитектуру с composition root в Startup.cs (детали вне контекста этой статьи).

Welcome to HTTP-RPC?
Сертифікати і деплой в Azure звичайно жесть і ARM шаблони не сильно помагають.

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

Все не совсем так, а точнее совсем не так. Хостинг одной stateless апишки под окрестратором — это непрофильная задача, которая не раскрывает реальные бенефеты от использования Service fabric или kuber точно так же как и не дает ответа на то с чем мороки больше или меньше.
В целом по некоторым пунктам

— Sf без контейнеров это только IaaS решение и работы там девопс в разы больше чем при работы с Managed Kuber в AKS/EKS не важно где.
— Sf имеет отвратительнейшую интеграцию даже с ms стеком и крайне слабую поддержку community(ни о каких package managers речи не идет — все делать надо самому с самых low level штук), слабый тулинг пол linux, крайне убогую поддержку iac тулингом — по сравнению с kuber, что оставляет его далеко позади для развертывания быстрых и дешевых решений и добавляет необходимость писать кучу инфраструктурного кода для интеграции со стандартными либами тем же Asp.net core, di контейнерами, переменными окружениям взятыми из паблиш профайлов и тому подобным в отличии от Kuber — где можно накидать все готовое .

Отличный фитбек.

Видимо статья зашла, раз есть отклик о том, что необходимо понимать область применения решения, его стоимость и объем времени на развертывание и обслуживание в продакшене. Нужно избегать мороки и приносить value клиенту, а также делегировать DevOps/SecOps таски клауд провайдеру. Проблемы у ASF конечно же есть, без них никак.

K8s нужен для определенного круга задач, но это статья не про них :). Согласен также с тем, что kubernetes не подходит для хостинга десятка реплик stateless сервисов — это не профильная задача.

— IaaS все же это VMSS за нодами ASF, а сам Fabric is a custom PaaS. МС использует его под капотом большей части сервисов Azure и скорее всего Azure Kubernetes Service работает тоже поверх него.
— По паблиш профайлам все так :), у меня как раз статья есть
medium.com/...​fabric-series-148b1739d95
— про интеграцию, DI, .NET Core и тп, можно попробовать лабу(воркшоп) с моего гитхаба, там как раз это все, проблем не будет ;). А если будут, то у меня будет повод для новой статьи.

Вообще с удовольствием пообщаюсь при встрече, буду на .NET Fest как спикер и участник.

Cheers!

— IaaS все же это VMSS за нодами ASF, а сам Fabric is a custom PaaS. МС использует его под капотом большей части сервисов Azure и скорее всего Azure Kubernetes Service работает тоже поверх него.

Sf это не PaaS никакой, а самый настойщий IaaS, он не managed сервис. Azure Kuber — managed, имеет опциональную поддержку работы с низкоуровневой инфраструктурой типа сети с nsg, а в Sf ось, сеть, вм-ки это обязательный этап. Sf Managed сервис они начали делать год назад где-то — mesh, но без контейнеров он не работает.

Мне тоже иногда кажется, что похож на IaaS :), но нет.

Можно посмотреть инфографику и прочитать детально по линке ниже.
kristiannese.blogspot.com/...​of-microservices-and.html

А лучше спросить автора, senior program manager at Microsoft via Twitter.
He will explain why its a PaaS. twitter.com/kristiannese

Как же убого все сделанное Microsoft. Сколько с Azure не работал, всегда плевался. Вот и здесь, с одной стороны прикольно написано, но технологическое убожество так и прет.

И как оно прёт?

Рад, что статья понравилась :).
Насчет же облака — тут два поинта: IKEA effect и то, что конкретное облако должно решать проблему. Ну и CLI via bash тоже нужен.
Но имхо стоит использовать то, что нравиться. Cheers.

Задача була вирішена, автор навів підтвердження, бізнес лише виграв. Ідеальних рішень немає з технологічної точки зору, Azure не ідеальний, GC, AWS — також. Завжди є альтернатива, on premise. Буду дуже вдячний, якщо ви конкретизуєте, в чому саме технологічна бідність Azure, і в чому саме альтернативні рішення впереді планети всієї? Дякую.

Подписаться на комментарии