Унаследованные приложения, как правило, имеют монолитную архитектуру и запускаются на одной или нескольких виртуальных машинах. Некоторые из таких систем легче поддаются модернизации, поскольку в мире контейнеров для них есть неплохие аналоги (EAP, Spring Boot и т.д.). Однако большие классические приложения на .Net, работающие под IIS на Windows-сервере, модернизировать гораздо сложнее, тем более за одну итерацию. Но благодаря OpenShift Virtualization такие ВМ-нагрузки можно импортировать в OpenShift как есть и затем контейнеризировать их поэтапно.
В OpenShift виртуальные машины являются привилегированными гражданами и имеют ровно те же возможности, что и podы, включая обращение к другим объектам и предоставление доступа к себе через конечные точки служб (service endpoints). Поэтому выполнив первичный перенос ВМ-приложения в OpenShift, его затем можно поэтапно модернизировать, а заодно и расширять функционал.
Стратегия миграции Shift and Modernize
Чтобы показать, как это делается, мы для примера возьмем приложение .Net, работающее под IIS на виртуалке Windows Server, импортируем его в OpenShift Virtualization, а затем поэтапно контейнеризуем все его логические слои. Обратите внимание, что стратегия shift and modernize подходит и для других связок операционная системасвязующее ПО.
Этап 1. Импорт ВМ в OpenShift Virtualization
Импорт ВМ в OpenShift возможен несколькими способами. Для виртуальных машин VMware можно использоватьвстроенный инструментарий миграции, который позволяет подключиться к экземпляру VSphere и напрямую импортировать эти виртуалки в OpenShift Virtualization. Для других платформ виртуализации, включая Hyper-V и Xen, можно использовать virt-v2v, чтобы конвертировать образ ВМ в формат, поддерживаемый OpenShift Virtualization, а затем импортировать этот образ, используя методы описанные здесь (EN).
Виртуальная машина запускается с помощью Yaml-конфигурации, базовый вариант которой можно найтиздесь. Этот Yaml-файл содержит определение ВМ, а также объектов service и route, плюс, некоторые функциональные конфигурации для более эффективной работы Windows-ВМ на платформе OpenShift Virtualization.
Нас интересует следующее секция:
features: acpi: {} apic: {} hyperv: reenlightenment: {} ipi: {} synic: {} synictimer: {} spinlocks: spinlocks: 8191 reset: {} relaxed: {} vpindex: {} runtime: {} tlbflush: {} frequencies: {} vapic: {} evmcs: {} # do not use evmcs if testing with nested virt
После применения этого yaml, мы получаем доступ к графическому интерфейсу Windows UI через VNC Console, которую нам дает OpenShift Virtualization.
Кроме того, теперь у нас есть доступ к приложению через exposed route.
Этап 2. Контейнеризация UI приложения
Не всегда можно мигрировать всё сразу, особенно в случае больших приложений. Например, этому могут препятствовать зависимости от библиотек, которые есть в классическом .NET, но отсутствуют в .Net Core. В этом случае код приложения придется доработать.
И поскольку это можно делать поэтапно, мы начнем с веб-интерфейса и после того, как переведем UI-слой на .Net Core, упакуем его в контейнерный образ для OpenShift. Этот новый UI-pod будет потреблять API, которые предоставляются старым сайтом, работающем под IIS на виртуальной машине.
Приведенный ниже Dockerfile компилирует ваш код .Net Core и создает runtime-образ. Это также можно сделать через сборки S2I.
# https://hub.docker.com/_/microsoft-dotnet-coreFROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS buildWORKDIR /source# copy csproj and restore as distinct layersCOPY ./source .RUN dotnet restore# copy and publish app and librariesCOPY . .RUN dotnet publish -c release -o /app --no-restore# final stage/imageFROM mcr.microsoft.com/dotnet/core/aspnet:3.1WORKDIR /appCOPY --from=build /app .ENTRYPOINT ["dotnet", "ClientListUI.dll"]
Для сборки и отправки этого образа в реестр можно использовать podman. Затем остается только развернуть этот отвечающий за веб-интерфейс pod вместе с виртуальной машиной приложения.
Этап 3. Контейнеризация API
Вслед за UI-слоем мигрируем на .Net Core слой API и развернем его в виде отдельного podа. После чего на исходной виртуалке остается только база данных SQL Server. Соответствующим образом поправим сервис ВМ в части описания доступа:
kind: ServiceapiVersion: v1metadata: name: stage3-win2019-db-vm namespace: stage3 labels: kubevirt.io: virt-launcher kubevirt.io/domain: stage3-win2019-iis-vmspec: ports: - protocol: TCP port: 1433 targetPort: 1433 selector: kubevirt.io: virt-launcher kubevirt.io/domain: stage3-win2019-iis-vm
Итак, теперь UI-pod нашего приложения вызывает API через service URL нашего API-podа, а тот в свою очередь использует service URL нашей виртуальной машины, чтобы делать запросы к базе данных.
Этап 4. Контейнеризация БД
Да, вы правильно поняли: миграция экземпляра MS SQL в контейнер RHEL. Лет пять назад такое и в голову бы никому не пришло, но сегодня это вполне рабочий вариант и подробнее узнать о том, как настроить и запустить MS SQL в контейнере, можно узнать здесь (EN).
После того, SQL-pod будет готов, остается настроить port forwarding, чтобы можно было работать с БД через MS SQL Management Studio или Azure Data Studio:
oc get pod | grep sql | grep Runningsql2019-1-1-gp29h 1/1 Running 0 39h oc port-forward sql2019-1-1-gp29h 1433:1433Forwarding from 127.0.0.1:1433 -> 1433Forwarding from [::1]:1433 -> 1433Handling connection for 1433
Теперь можно переносить БД из экземпляра MS SQL на Windows-виртуалке в контейнер SQL Server. После чего, необходимо изменить строку подключения для API-podа приложения и указать в ней pod, где теперь живет ваш MS SQL.
Всё, приложение полностью, на 100% контейнеризовано, и виртуальную машину которую, мы перенесли на первом этапе, можно навсегда отключить.
Заключение
Поэтапная миграция ВМ-нагрузки по методу shift and modernize позволяет снизить технический долг, минимизировать любого рода регрессии, которые могут возникнуть входе этого процесса, ну и попутно расширить функционал приложения в рамках проводимой при такой миграции доработки кода.