Часть 1. Перевод приложений в Aspire
Часть 2. Локальное развертывание с помощью Aspire
Вступление
Надо сказать, что на момент создания первой статьи, эта могла быть отложена на неопределенный срок. А все из-за такого поведения. Если коротко, то aspirate не осуществлял публикацию консольных приложений, это исправили только в ночь с 7 на 8 мая. При этом больше информации о том, что приложения Microsoft.NET.Sdk не публикуются найти не получилось.
По большей части это пересказ действий, указанных здесь, с некоторыми добавлениями, которые заметил при самостоятельных попытках развернуть приложение.
Подготовка к запуску
Для начала необходимо включить Kubernetes в Docker Desktop, чтобы можно было поднять приложение. Делается это в настройках.
Также необходимо установить aspirate, с помощью этого инструмента осуществляется развертывание приложения в kubernetes.
dotnet tool install --global aspirate --version 8.0.4
Версия должна быть не ниже 8.0.4, именно в этой версии исправили создание контейнеров для консольных и иже с ними приложений.
Также можно установить Kubernetes Dashboard, чтобы просматривать состояние приложений.
Разворачивать мы будем приложение из предыдущей части. В том же репозитории доступна версия проекта с необходимыми для запуска исправлениями.
Исправление консольных приложений
Просто так приложения Microsoft.NET.Sdk не запустятся, для этого необходимо внести следующую правку в их .csproj файл:
<!--Необходимо добавить в файл данный блок-->
<PropertyGroup>
<IsPublishable>true</IsPublishable>
<EnableSdkContainerSupport>true</EnableSdkContainerSupport>
</PropertyGroup>
Это разрешит публикацию приложения в контейнер.
Также, как оказалось, Aspire не создаст https адрес для API, поэтому нужно исправить строку с созданием фабрики для HttpClient:
// Меняем название переменной окружения на "services__api__http__0"
services.AddHttpClient("WebAPI", x=> x.BaseAddress = new Uri(Environment.GetEnvironmentVariable("services__api__http__0")));
Публикация приложений
Вроде бы все просто: в Readme описан процесс публикации, но есть пара моментов, которые как минимум в моем случае не давали опубликовать приложение (именно из-за этого вынес данный публикацию в отдельную статью), но обо всем по порядку.
Первым делом нужно создать реестр контейнеров:
docker run -d -p 5000:5000 --name registry registry:latest
Лучше создать на порту 5000, а не на 6000, как в руководстве, потому что 6000 порт блокируется браузерами (как минимум Chrome) (на самом деле не критично, но быстро посмотреть список контейнеров может и не получиться).
Следующим шагом нужно инициализировать Aspir8, для этого в папке с проектом выполняем следующую команду:
aspirate init
Дальше нужно настроить параметры инициализации. Обязательно необходимо установить хранилище образов, следующие параметры можно не устанавливать:
Would you like to set a fall-back value for the container registry? [y/n] (n): y
Please enter the container registry to use as a fall-back value: localhost:5000
Следующим шагом необходимо собрать и опубликовать приложение в хранилище образов, для этого используется следующая команда. Тут может быть проблема при повторной публикации приложения: при попытках использовать прошлые настройки, сборка может завершиться ошибкой. Поэтому мы выполняем следующие команды:
aspirate generate
Would you like to use all previous state values, and skip re-prompting where possible ? [y/n] (y): n
При первом выполнении команды, вторая строка не требуется. Если же сборка выполняется в первый раз, то необходимо установить пароль для шифрования секретов приложения:
Please enter new Password: <Ваш пароль>
Please enter it again to confirm: <Ваш пароль>
Дальше необходимо выбрать компоненты, которые необходимо использовать. В нашем случае выбираем все компоненты. Чтобы выбрать какой-то конкретный компонент, необходимо при его выборе нажать пробел. После этого будет предложено добавить панель Aspire (ту самую, которую видно при запуске проекта через VS, но с урезанным функционалом). Выбираем требуемый вариант, я добавлю ее:
Would you like to deploy the aspire dashboard and connect the OTLP endpoint? [y/n] (y): y
Дальше потребуется ввести значения переменных, которые будут в дальнейшем зашифрованы. Но тут есть загвоздка, на мой взгляд: эти данные записываются в открытом виде, а не скрываются звездочками. После ввода и подтверждения значений начнется сборка и публикация в хранилище образов.
После публикации у вас запросят imagePullPolicy для Kubernetes, выбираем IfNotPresent.И последним важным параметров при генерации образов является генерация манифеста для Kubernetes. Его необходимо создать:
Would you like to generate the top level kustomize manifest to run against your kubernetes cluster? [y/n] (y): y
Последним этапом будет развертывание приложения в кластере Kubernetes. Вводим в консоль команду и обязательно выбираем использование предыдущих значений (как минимум в версии Aspir8 (aspirate) 8.0.2 выбор другого варианта приводил к ошибке):
aspirate apply
Would you like to use all previous state values, and skip re-prompting where possible ? [y/n] (y): y
Дальше вводим пароль, используем манифест, сгенерированный этапом раньше:
Would you like to deploy the generated manifests to a kubernetes cluster defined in your kubeconfig file? [y/n] (y): y
И выбираем контекст для публикации (в случае локальной публикации на Windows - docker-desktop). После этого начнется развертывание приложения. Чтобы проверить работоспособность, откроем панель управления Kubernetes. В ней можно увидеть, что все необходимые pods работают исправно:
Теперь посмотрим в панель управления Aspire. Для этого необходимо в командной строке перенаправить порты для Aspire Dashboard с помощью консоли:
kubectl port-forward aspire-dashboard-586bccb649-q8nz7 18888:18888
После чего переходим по адресу localhost:18888 и видим следующее:
Данная панель мониторинга достаточно сильно урезана по функционалу по сравнению с открывающейся при запуске приложения через VS, потому что она просто собирает телеметрию, но сама не администрирует проекты.
Заключение
В рамках данной статьи было разобран деплой приложения в локальный кластер Kubernetes. Получить итоговую версию проекта, доступную для развертывания можно в этом репозитории.
buldo
Aspire выглядит интересным, но можно ли его использовать, если каждый сервис лежит в отдельной репе?
nyarovoy Автор
В первой части статьи рассматривал переход как раз-таки из отдельных проектов, но там я просто перевел все проекты в новый репозиторий.
Но действительно может возникнуть проблема с тем, что разрабатывать все сервисы внутри Aspire решения может быть проблематично. Лично я собираюсь эту проблему решать так (не говорю, что метод оптимальный):
0) Если в репозитории лежит все решение, а не отдельный проект, выделить проект в подмодуль. Например так: https://web.archive.org/web/20170813014246/http://ishmuradov.ru/page/git-otdelit-direktoriju-v-otdelnyj-repozitorij
Также можно добавить полный существующий репозиторий как подмодуль в Aspire, и просто из него взять проекты, но зачем тащить .sln файл?
1) В решение каждого сервиса добавить проект ServiceDefaults, в builder'ах добавить AssServiceDefaults()
2) В Aspire добавить каждый сервис как подмодуль
3) В случае необходимости запуска сервисов по отдельности для тестов, вставить следующий костыль:
3.1) При запуске проекта через Aspire передавать переменную среды с заранее определенным именем и значением в случае, если запускается через Aspire.
3.2) Выделить AddServiceDefaults, а также всю информацию, получаемую из Aspire в if, в котором проверяется существование переменной среды и ее название.
3.3) Если данной переменной среды не существует, запускать так, как запускалось до перехода в Aspire
Но в этом своем решении не претендую на истину в последней инстанции.
nyarovoy Автор
Забыл добавить, что 0 шаг на самом деле не обязателен: Aspire ориентирован на проекты, то есть можно добавить весь репозиторий как подмодуль, но остальные шаги все равно все также обязательны для исполнения
buldo
Я читаю этот цикл статей и мне начинает казаться, что Aspire - это замена serviceFabric только на стеройдах.