Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Aspire offre API avanzate per la creazione di immagini del contenitore dalle risorse durante le operazioni di pubblicazione e distribuzione. Questo articolo illustra i componenti chiave che consentono la creazione di immagini del contenitore a livello di codice e la creazione di report sullo stato di avanzamento.
Informazioni generali
Durante la pubblicazione e la distribuzione, il generatore di immagini del contenitore è disponibile per creare immagini per le risorse necessarie. Aspire usa questo generatore quando una risorsa richiede un'immagine del contenitore, ad esempio durante la pubblicazione con Docker Compose. Il processo prevede due componenti principali:
- IResourceContainerImageBuilder: servizio che trasforma le definizioni delle risorse in immagini contenitore eseguibili.
-
IPipelineActivityReporter: l'API che fornisce report sullo stato di avanzamento strutturati durante le operazioni a esecuzione prolungata.
Queste API offrono un controllo granulare sul processo di compilazione delle immagini e forniscono feedback in tempo reale agli utenti durante operazioni di compilazione lunghe.
Importante
Queste API sono attualmente in anteprima e soggette a modifiche. Sono progettati per scenari avanzati in cui è necessario un controllo personalizzato sulla creazione di immagini del contenitore e sulla creazione di report sullo stato di avanzamento. Per eliminare gli avvisi per queste API, vedere Errore del compilatore ASPIREPUBLISHERS001.
Quando usare queste API
Prendere in considerazione l'uso delle API di creazione delle immagini e di generazione dei report di avanzamento del container in questi scenari:
- Destinazioni di distribuzione personalizzate: quando è necessario eseguire la distribuzione in piattaforme che richiedono formati di immagine specifici o configurazioni di compilazione.
- Pipeline di compilazione complesse: quando il processo di pubblicazione prevede più passaggi che gli utenti dovrebbero vedere.
- Scenari aziendali: quando è necessario creare report sullo stato di avanzamento personalizzati per l'integrazione con sistemi o dashboard CI/CD.
- Tipi di risorse personalizzati: quando si implementano risorse personalizzate che devono partecipare al processo di pubblicazione e distribuzione.
Annotazioni
Per la maggior parte delle applicazioni standard Aspire , il processo di pubblicazione predefinito compila automaticamente immagini del contenitore senza richiedere queste API.
API del generatore di immagini del contenitore di risorse
IResourceContainerImageBuilder è il servizio principale nel Aspire.Hosting.Publishing livello che converte le definizioni delle risorse in immagini del contenitore. Analizza ogni risorsa nel modello di applicazione distribuita e determina se:
- Riutilizzare un'immagine esistente.
- Compilare da un .NET progetto usando
dotnet publish /t:PublishContainer. - Compilare da un Dockerfile usando il runtime del contenitore locale.
Opzioni di build del contenitore
La ContainerBuildOptions classe fornisce una configurazione fortemente tipizzata per le compilazioni di contenitori. Questa classe consente di specificare:
- Formato immagine: Docker o Formato OCI (Open Container Initiative).
- Piattaforma di destinazione: Linux x64, Windows, ARM64 e così via.
- Percorso di output: dove salvare le immagini compilate.
Verifiche di integrità del runtime del contenitore
Il generatore esegue controlli di integrità del runtime del contenitore (Docker/Podman) solo quando almeno una risorsa richiede una Dockerfile compilazione. Questa modifica elimina gli errori falsi positivi nei progetti che pubblicano direttamente dagli .NET assembly. Se il runtime del contenitore è necessario ma malfunzionante, il compilatore genera un'eccezione esplicita InvalidOperationException in modo precoce per far emergere il problema.
API del reporter dell'attività della pipeline
L'API PipelineActivityReporter permette la creazione di report strutturati sullo stato di avanzamento durante i comandi aspire publish e aspire deploy. Ciò riduce l'incertezza durante le operazioni a esecuzione prolungata e presenta in anticipo gli errori.
Panoramica e comportamento delle API
Il reporter di avanzamento utilizza un modello gerarchico con ordinamento garantito e operazioni sicure per i thread.
| Concetto | Description | Rendering dell'interfaccia della riga di comando | Comportamento |
|---|---|---|---|
| Step | Fase di primo livello, ad esempio "Compilare immagini" o "Distribuire carichi di lavoro". | Messaggio di fase con glifi di stato e tempo trascorso. | Forma una struttura ad albero rigorosa; i passaggi annidati non sono supportati. I passaggi vengono creati automaticamente durante l'esecuzione della pipeline. |
| Attività | Unità di lavoro discreta annidata in un passaggio. | Messaggio di attività con rientro. | Appartiene a un singolo passaggio; supporta la creazione parallela con l'ordinamento di completamento deterministico. |
| Stato di completamento | Stato finale: Completed, Warningo Error. |
✅ (Completato), ⚠️ (avviso), ❌ (errore) | Ogni passaggio/attività passa esattamente una volta a uno stato finale. |
Struttura e utilizzo delle API
L'API reporter fornisce accesso strutturato alla creazione di report sullo stato di avanzamento con le caratteristiche seguenti:
-
Acquisizione: recuperata da
PublishingContext.ActivityReportero tramite la proprietà nei passaggi dellaPipelineStepContext.ReportingSteppipeline. -
Creazione dei passaggi: i passaggi vengono ora creati automaticamente durante l'esecuzione della pipeline. Il
CreateStepAsync(title, ct)metodo restituisce un oggettoIReportingStep. -
Creazione di attività:
IReportingStep.CreateTaskAsync(title, ct)restituisce un oggettoIReportingTask. -
Transizioni di stato:
SucceedAsync,WarnAsynciFailAsyncmetodi accettano un messaggio di riepilogo. -
Completamento:
CompletePublishAsync(message, state, isDeploy, ct)contrassegna l'intera operazione. - Ordinamento: gli eventi di creazione e completamento mantengono l'ordine di chiamata; gli aggiornamenti vengono serializzati.
- Annullamento: tutte le API accettano CancellationToken e propagano l'annullamento all'interfaccia della riga di comando.
- Contratto di smaltimento: i passaggi di smaltimento vengono completati automaticamente se incompleti, impedendo le fasi orfane.
Esempio: Compilare immagini del contenitore e segnalare lo stato di avanzamento
Per usare queste API, aggiungere un PublishingCallbackAnnotation, un DeployingCallbackAnnotation, o entrambi a una risorsa nel modello di app. È possibile annotare risorse personalizzate (o predefinite) aggiungendo annotazioni alla IResource.Annotations raccolta.
Gli sviluppatori possono scegliere di:
Usare entrambe le annotazioni se la risorsa deve eseguire operazioni sia nella pubblicazione che nella distribuzione. Ad esempio, compilare immagini e generare manifesti durante la pubblicazione, quindi eseguire il push delle immagini o configurare le destinazioni di distribuzione durante la distribuzione. La pubblicazione avviene sempre prima della distribuzione, in modo da poter mantenere separata la logica per ogni fase.
Usare solo
PublishingCallbackAnnotationse la risorsa deve eseguire operazioni solo durante la pubblicazione. Questa operazione è comune quando è sufficiente compilare artefatti o immagini, ma non è necessario eseguire alcuna operazione durante la distribuzione.Usare solo
DeployingCallbackAnnotationse la risorsa deve eseguire operazioni solo durante la distribuzione. Questo si adatta ai casi in cui si usano immagini predefinite ed è sufficiente distribuirle o configurarle.
Scegliere una o più annotazioni che corrispondono alle responsabilità della risorsa per mantenere il modello di applicazione chiaro e gestibile. Questa separazione consente di poter definire chiaramente la logica per ogni fase, ma è possibile usare sia il rilevatore di attività che il builder delle immagini del contenitore di risorse in entrambi i callback secondo necessità.
Risorsa di esempio con annotazioni
Si consideri ad esempio il ComputeEnvironmentResource costruttore:
public ComputeEnvironmentResource(string name) : base(name)
{
Annotations.Add(new PublishingCallbackAnnotation(PublishAsync));
Annotations.Add(new DeployingCallbackAnnotation(DeployAsync));
}
Quando viene creata un'istanza, definisce sia una pubblicazione che un'annotazione di callback.
Dato il tipo di esempio ComputeEnvironmentResource (Resource), si supponga di avere un metodo di estensione che consente ai consumatori di aggiungere l'ambiente di calcolo.
using System.Diagnostics.CodeAnalysis;
[Experimental("ASPIRECOMPUTE001")]
public static class ComputeEnvironmentResourceExtensions
{
public static IResourceBuilder<ComputeEnvironmentResource> AddComputeEnvironment(
this IDistributedApplicationBuilder builder,
[ResourceName] string name)
{
var resource = new ComputeEnvironmentResource(name);
return builder.AddResource(resource);
}
}
Il codice precedente:
- Definisce un metodo di estensione in IDistributedApplicationBuilder.
- Accetta un
namecome oggetto per la risorsa dell'ambiente di calcolo, protetto da ResourceNameAttribute. - Crea un'istanza di
ComputeEnvironmentResourcedato ilnamee lo aggiunge all'builder.
Esempio di AppHost
Nel tuo AppHost, puoi aggiungere il ComputeEnvironmentResource al modello di applicazione come questo:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedis("redis");
builder.AddProject<Projects.Api>("api")
.WithReference(cache);
builder.AddComputeEnvironment("compute-env");
builder.Build().Run();
Il codice precedente usa il AddComputeEnvironment metodo di estensione per aggiungere l'oggetto ComputeEnvironmentResource al modello di applicazione.
Pubblicazione dell'annotazione del callback
Quando si aggiunge ComputeEnvironmentResource, registra un oggetto PublishingCallbackAnnotation. Il callback usa il PublishAsync metodo :
private static async Task PublishAsync(PublishingContext context)
{
var reporter = context.ActivityReporter;
var imageBuilder = context.Services.GetRequiredService<IResourceContainerImageBuilder>();
// Build container images for all project resources in the application
await using (var buildStep = await reporter.CreateStepAsync(
"Build container images", context.CancellationToken))
{
// Find all resources that need container images
var projectResources = context.Model.Resources
.OfType<ProjectResource>()
.ToList();
if (projectResources.Count > 0)
{
// Configure how images should be built
var buildOptions = new ContainerBuildOptions
{
ImageFormat = ContainerImageFormat.Oci,
TargetPlatform = ContainerTargetPlatform.LinuxAmd64,
OutputPath = Path.Combine(context.OutputPath, "images")
};
var buildTask = await buildStep.CreateTaskAsync(
$"Building {projectResources.Count} container image(s)", context.CancellationToken);
// Build all the container images
await imageBuilder.BuildImagesAsync(
projectResources, buildOptions, context.CancellationToken);
await buildTask.SucceedAsync(
$"Built {projectResources.Count} image(s) successfully", context.CancellationToken);
}
else
{
var skipTask = await buildStep.CreateTaskAsync(
"No container images to build", context.CancellationToken);
await skipTask.SucceedAsync("Skipped - no project resources found", context.CancellationToken);
}
await buildStep.SucceedAsync("Container image build completed", context.CancellationToken);
}
// Generate deployment manifests
await using (var manifestStep = await reporter.CreateStepAsync(
"Generate deployment manifests", context.CancellationToken))
{
var bicepTask = await manifestStep.CreateTaskAsync(
"Write main.bicep", context.CancellationToken);
// Write file to context.OutputPath …
await bicepTask.SucceedAsync(
$"main.bicep at {context.OutputPath}", context.CancellationToken);
await manifestStep.SucceedAsync("Manifests ready", context.CancellationToken);
}
// Complete the publishing operation
await reporter.CompletePublishAsync(
completionMessage: "Publishing pipeline completed successfully",
completionState: CompletionState.Completed,
cancellationToken: context.CancellationToken);
}
Il codice precedente:
- Implementa una pipeline di pubblicazione che costruisce immagini contenitore e genera manifesti di distribuzione.
- Usa l'API
IResourceContainerImageBuilderper compilare immagini del contenitore. - Segnala lo stato di avanzamento e completamento usando l'API
PipelineActivityReporter.
Il callback di pubblicazione potrebbe usare IResourceContainerImageBuilder per compilare immagini del contenitore, mentre il callback della distribuzione potrebbe usare le immagini compilate ed eseguirne il push in un registro o in una destinazione di distribuzione.
Implementazione dell'annotazione di callback
Analogamente al callback di pubblicazione, il callback di distribuzione viene registrato usando DeployingCallbackAnnotation e chiama il DeployAsync metodo :
private static async Task DeployAsync(DeployingContext context)
{
var reporter = context.ActivityReporter;
await using (var deployStep = await reporter.CreateStepAsync(
"Deploy to target environment", context.CancellationToken))
{
var applyTask = await deployStep.CreateTaskAsync(
"Apply Kubernetes manifests", context.CancellationToken);
// Simulate deploying to Kubernetes cluster
await Task.Delay(1_000, context.CancellationToken);
await applyTask.SucceedAsync("All workloads deployed", context.CancellationToken);
await deployStep.SucceedAsync("Deployment to cluster completed", context.CancellationToken);
}
// Complete the deployment operation
await reporter.CompletePublishAsync(
completionMessage: "Deployment completed successfully",
completionState: CompletionState.Completed,
isDeploy: true,
cancellationToken: context.CancellationToken);
}
Il codice precedente:
- Simula la distribuzione dei carichi di lavoro in un Kubernetes cluster.
- Usa l'API
PipelineActivityReporterper creare e gestire i passaggi e le attività di distribuzione. - Segnala lo stato di avanzamento e contrassegna ogni fase di distribuzione come completata.
- Completa l'operazione di distribuzione con un aggiornamento dello stato finale.
- Gestisce l'annullamento tramite l'oggetto fornito
CancellationToken.
Procedure consigliate
Quando si usano queste API, seguire queste linee guida:
Creazione di immagini
- Specificare sempre esplicitamente
ContainerBuildOptionsper gli scenari di produzione. - Prendere in considerazione i requisiti della piattaforma di destinazione durante la preparazione per la distribuzione.
- Usare il formato OCI per garantire la massima compatibilità con i registri contenitori.
- Gestire
InvalidOperationExceptionquando le verifiche di integrità del runtime del contenitore hanno esito negativo.
Relazione sullo stato di avanzamento
- Incapsulare le fasi logiche a lungo termine nei passi anziché emettere attività grezze.
- Mantenere concisi i titoli (sotto 60 caratteri) perché l'interfaccia della riga di comando tronca stringhe più lunghe.
- Chiamare
CompletePublishAsyncesattamente una volta per operazione di pubblicazione o distribuzione. - Considerare gli avvisi come ripristinabili e consentire ai passaggi successivi di procedere.
- Considerare gli errori come fatali e fallire rapidamente con una diagnostica chiara.
- Usare operazioni asincrone con riconoscimento dell'annullamento per evitare di bloccare l'elaborazione degli eventi.
Gestione dello stato
- Ogni passaggio e attività viene avviato nello stato In esecuzione e passa esattamente una volta a Completato, Avviso o Errore.
- Generare un'eccezione quando si tentano più transizioni di stato.
- Sfrutta il reporter per garantire eventi ordinati e impedire l'interferenza.
- Smaltisci
IPublishingActivityStepper completare automaticamente i passaggi non completati.