Aspire: оркестрация локальной разработки и деплой

↑ 7.6 DevOps для бэкенд-разработчика · ← Предыдущая

Желательно~7 мин чтенияУровень: middle

Зачем это на собесе

«Как вы поднимаете десять сервисов, базу, кэш и очередь у себя на машине?» Обычно это docker compose и README на три страницы. Aspire решает ту же задачу кодом на C♯ и сразу добавляет телеметрию и панель. Это новый стандартный инструмент экосистемы .NET, о нём всё чаще спрашивают.

Подтемы

  • Зачем Aspire и что это
  • AppHost, ресурсы и ссылки
  • Service discovery и ServiceDefaults
  • Панель и телеметрия
  • Интеграции (PostgreSQL, Redis, RabbitMQ и другие)
  • Публикация и ограничения

Объяснение

Проблема

Современное приложение состоит из нескольких сервисов и зависимостей: API, воркер, PostgreSQL, Redis, брокер. Чтобы запустить всё локально, нужны compose-файл, строки подключения, порядок старта и ручная настройка телеметрии. Строки подключения дублируются в разных местах, а у каждого разработчика «работает по-своему».

Что такое Aspire

Aspire (ранее называлась .NET Aspire) — набор инструментов и библиотек для описания распределённого приложения. Центральный элемент: проект AppHost на C♯, который описывает ресурсы (ваши проекты, контейнеры, базы данных) и связи между ними. При запуске Aspire поднимает всё, передаёт приложениям адреса и строки подключения и показывает панель управления.

flowchart LR
    A["AppHost (C#)<br/>описание приложения"] --> P1["Проект: Api"]
    A --> P2["Проект: Worker"]
    A --> C1["Контейнер: PostgreSQL"]
    A --> C2["Контейнер: Redis"]
    P1 --> C1
    P1 --> C2
    P2 --> C1
    A --> D["Панель Aspire:<br/>логи, метрики, трейсы, статусы"]

AppHost

var builder = DistributedApplication.CreateBuilder(args);
 
var postgres = builder.AddPostgres("postgres").WithDataVolume();
var db = postgres.AddDatabase("appdb");
var cache = builder.AddRedis("cache");
 
builder.AddProject<Projects.Api>("api")
    .WithReference(db)              // строка подключения "appdb" попадёт в конфигурацию Api
    .WithReference(cache)
    .WaitFor(db)                    // запускать API после готовности базы
    .WithExternalHttpEndpoints();
 
builder.Build().Run();

Методы AddPostgres, AddRedis и другие находятся в пакетах интеграций (Aspire.Hosting.PostgreSQL, Aspire.Hosting.Redis). Projects.Api генерируется из ссылки на проект.

Service discovery и ServiceDefaults

Проекты сервисов подключают общий проект ServiceDefaults, который добавляет: настройку OpenTelemetry (трассировка, метрики, логи), проверки здоровья, устойчивость HTTP-клиентов (повторы, таймауты) и service discovery. Сервисы обращаются друг к другу по логическому имени (http://api), а Aspire подставляет реальный адрес.

Панель

Панель показывает ресурсы и их состояние, консольные логи, структурированные логи, метрики и распределённые трейсы в одном месте. Это бесплатный аналог связки Prometheus, Grafana и Jaeger для локальной отладки (Observability на бэкенде).

Интеграции

Готовые пакеты для PostgreSQL, SQL Server, MongoDB, Redis, RabbitMQ, Kafka, Elasticsearch, Keycloak, MinIO и других: поднимают контейнер с нужными настройками и передают данные подключения приложению. Клиентские пакеты (Aspire.Npgsql, Aspire.StackExchange.Redis) подключаются в самом сервисе одной строкой.

Публикация

Aspire не заменяет продакшен-оркестратор. Описание AppHost можно превратить в манифест и использовать для развёртывания: генерировать файлы Docker Compose, манифесты Kubernetes или публиковать в облако (Azure Container Apps через azd). Продакшен-настройки, секреты и сети всё равно определяются отдельно (как мы поднимаем Clinic).

Aspire или Docker Compose

Docker ComposeAspire
ОписаниеYAMLC♯
Свои проекты .NETчерез Dockerfile и сборкузапускаются напрямую, без образа, с отладчиком
Телеметрия и панельнастраивать отдельновстроено
Service discovery и строки подключениявручнуюавтоматически
Независимость от языкадаориентирован на .NET (поддерживает и другие языки как ресурсы)
Продакшенпривычный форматэкспорт в Compose, Kubernetes, облако

Примеры

Подключение клиентских интеграций в сервисе

var builder = WebApplication.CreateBuilder(args);
 
builder.AddServiceDefaults();                  // OpenTelemetry, health checks, resilience, service discovery
builder.AddNpgsqlDataSource("appdb");          // строка подключения приходит от AppHost по имени ресурса
builder.AddRedisClient("cache");
 
var app = builder.Build();
app.MapDefaultEndpoints();                     // /health и /alive
app.MapGet("/", () => "ok");
app.Run();

Запуск

dotnet run --project AppHost     # поднимает контейнеры, проекты и открывает панель Aspire

Нюансы и подводные камни

  • Aspire для разработки и сборки манифестов, не замена Kubernetes. В продакшене нужны свои настройки.
  • Нужен Docker или совместимая среда для контейнерных ресурсов.
  • Версии пакетов держите согласованными (хост и интеграции одной мажорной версии).
  • Секреты. Параметры вроде паролей передавайте через параметры и user-secrets, не в коде AppHost.
  • WaitFor и готовность. Порядок запуска не заменяет корректной обработки недоступности зависимостей в приложении.
  • Данные контейнеров. Без WithDataVolume данные базы пропадают при пересоздании контейнера.
  • Проекты не на .NET тоже можно подключать как ресурсы, но удобство меньше.

Вопросы с ответами

Связанные темы