Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Aspire är en verktygskedja för att bygga, köra, felsöka och distribuera distribuerade applikationer. Aspire Azure Functions-integrationen gör det möjligt för dig att utveckla, felsöka och orkestrera ett Azure Functions-projekt som en del av en Aspire AppHost. .NET-exemplen i denna artikel använder modellen för isolerad arbetare.
Förutsättningar
Konfigurera utvecklingsmiljön för användning av Azure Functions med Aspire:
Installera Aspire-kraven, inklusive .NET SDK som krävs av din AppHost.
Installera Aspire Azure Functions hosting-integration från AppHost-katalogen.
aspire add Aspire.Hosting.Azure.FunctionsInstallera Azure Functions Core Tools.
Om du använder Visual Studio, installera de senaste verktygsuppdateringarna för Visual Studio och Azure Functions:
- Gå till Verktygsalternativ>.
- Under Projekt och lösningar väljer du Azure Functions.
- Välj Sök efter uppdateringar och installera uppdateringar enligt anvisningarna.
För mer information om integrationspaketet och stödda AppHost-API:er, se Sätt upp Azure Functions i AppHost.
Lösningsstruktur
En lösning som använder Azure Functions och Aspire har flera projekt, inklusive en AppHost och ett eller flera Functions-projekt.
AppHost är ingångspunkten för din ansökan. Den samordnar installationen av komponenterna i ditt program, inklusive Functions-projektet.
Lösningen innehåller vanligtvis också ett standardprojekt för tjänsten . Det här projektet innehåller en uppsättning standardtjänster och konfigurationer som ska användas i olika projekt i ditt program.
AppHost-projekt
För att framgångsrikt konfigurera integrationen, se till att AppHost-projektet uppfyller följande krav:
- AppHost refererar till Aspire.Hosting.Azure. Functions. Detta paket definierar integrationen.
- En C# AppHost refererar till ett Functions-projekt och anropar
AddAzureFunctionsProject<TProject>(), eller anroparAddAzureFunctionsProject(name, projectPath)med sökvägen till projektfilen. TypeScript AppHosts använder projektvägsformen .addAzureFunctionsProject - Använd
AddAzureFunctionsProjecti stället förAddProject. Ett Functions-projekt som lagts till genom att användaAddProjectkan inte starta ordentligt.
Följande exempel visar en minimal AppHost.cs fil för ett C# AppHost-projekt:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");
builder.Build().Run();
Azure Functions-projekt
Om du vill konfigurera integreringen kontrollerar du att Azure Functions-projektet uppfyller följande krav:
Sikta på .NET 8 eller senare, använd .NET 9 SDK eller senare, och använd modellen för isolerad arbetare.
Referens Microsoft.Azure. Functions.Worker, Microsoft.Azure. Functions.Worker.Sdk, och, för HTTP-triggers, Microsoft.Azure. Functions.Worker.Extensions.Http.AspNetCore.
Filen
Program.csmåste användaIHostApplicationBuilder-versionen av startprocessen för värdinstansen. Det här kravet innebär att du måste användaFunctionsApplication.CreateBuilder(args).Om lösningen innehåller ett standardprojekt för tjänsten kontrollerar du att functions-projektet är konfigurerat att använda det:
- Functions-projektet bör innehålla en projektreferens till standardprojektet för tjänsten.
- Innan du skapar
IHostApplicationBuilderiProgram.csska du inkludera ett anrop tillbuilder.AddServiceDefaults().
I följande exempel visas en minimal Program.cs fil för ett Functions-projekt som används i Aspire:
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Hosting;
var builder = FunctionsApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.ConfigureFunctionsWebApplication();
builder.Build().Run();
Det här exemplet innehåller inte standardkonfigurationen för Application Insights som visas i många andra Program.cs exempel och i Azure Functions-mallarna. I stället konfigurerar du OpenTelemetry-integrering i Aspire genom att anropa builder.AddServiceDefaults() metoden.
Tänk på följande riktlinjer för att få ut mesta möjliga av integreringen:
- Inkludera inga direkta Application Insights-integreringar i Functions-projektet. Övervakning i Aspire hanteras i stället via dess OpenTelemetry-stöd. Du kan konfigurera Aspire för att exportera data till Azure Monitor via standardprojektet för tjänsten.
- När Aspire kör Functions-projektet, föredra inställningar som injiceras av AppHost. Du kan ha kvar motsvarande inställningar i
local.settings.jsonför att köra projektet fristående medfunc start; miljövariabler som injiceras av Aspire åsidosätter dem.
Anslutningskonfiguration med Aspire
AppHost definierar resurser och hjälper dig att skapa kopplingar mellan dem genom att använda kod. Det här avsnittet visar hur du konfigurerar och anpassar anslutningar som ditt Azure Functions-projekt använder.
Aspire innehåller standardanslutningsbehörigheter som kan hjälpa dig att komma igång. Dessa behörigheter kanske dock inte är lämpliga eller tillräckliga för ditt program.
För scenarier som använder rollbaserad åtkomstkontroll i Azure (RBAC) kan du anpassa behörigheter genom att anropa WithRoleAssignments() metoden för projektresursen. När du anropar WithRoleAssignments()tas alla standardrolltilldelningar bort och du måste uttryckligen definiera de fullständiga rolltilldelningar som du vill använda. Om du hostar din applikation på Azure Container Apps WithRoleAssignments() måste du också anropa AddAzureContainerAppEnvironment() på DistributedApplicationBuilder.
Azure Functions-värdlagring
Azure Functions kräver en värdlagringsanslutning (AzureWebJobsStorage) för flera av dess kärnbeteenden. När du anropar AddAzureFunctionsProject<TProject>() din AppHost skapar du en AzureWebJobsStorage anslutning som standard och tillhandahåller den till Functions-projektet. Denna standardanslutning använder Azure Storage-emulatorn för lokala utvecklingskörningar och provisionerar automatiskt ett lagringskonto när du distribuerar den. För mer kontroll, ersätt denna anslutning genom att anropa .WithHostStorage() Functions-projektresursen.
De standardbehörigheter som Aspire sätter för värdlagringsanslutningen beror på om du ringer WithHostStorage() eller inte. Genom att lägga till WithHostStorage() tas en tilldelning av rollen lagringskontodeltagare bort. I följande tabell visas de standardbehörigheter som Aspire anger för värdlagringsanslutningen:
| Värdlagringsanslutning | Förvalda roller |
|---|---|
Inget anrop till WithHostStorage() |
Storage Blob Data-bidragsgivare Lagringsködatabidragsgivare Storage Table Data-medverkare, Lagringskontomedverkare |
Kall WithHostStorage() |
Storage Blob Data-bidragsgivare Lagringsködatabidragsgivare Storage Table Data-medverkare |
Följande exempel visar en minimal AppHost.cs fil som ersätter värdlagringen och specificerar en rolltilldelning:
using Azure.Provisioning.Storage;
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureContainerAppEnvironment("myEnv");
var myHostStorage = builder.AddAzureStorage("myHostStorage");
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithHostStorage(myHostStorage)
.WithRoleAssignments(myHostStorage, StorageBuiltInRole.StorageBlobDataOwner);
builder.Build().Run();
Note
Ägare av lagringsblobdata är den roll som vi rekommenderar för de grundläggande behoven för anslutningen till värdlagringen. Din app kan stöta på problem om anslutningen till blobtjänsten bara har standardvärdet Aspire för Storage Blob Data Contributor.
För produktionsscenarier inkluderar du anrop till både WithHostStorage() och WithRoleAssignments(). Du kan sedan ange den här rollen explicit, tillsammans med andra som du behöver.
Utlösar- och bindningsanslutningar
Dina utlösare och bindningar hänvisar till anslutningar med namn. Följande Aspire-integreringar tillhandahåller dessa anslutningar via ett anrop till WithReference() på projektresursen:
Följande exempel visar en minimal AppHost.cs fil som konfigurerar en kö-trigger. I det här exemplet har motsvarande köutlösare egenskapen Connection inställd på MyQueueTriggerConnection, så anropet till WithReference() anger namnet.
var builder = DistributedApplication.CreateBuilder(args);
var myAppStorage = builder.AddAzureStorage("myAppStorage").RunAsEmulator();
var queues = myAppStorage.AddQueues("queues");
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithReference(queues, "MyQueueTriggerConnection");
builder.Build().Run();
För andra integreringar gör anrop till WithReference att ställa in konfigurationen på ett annat sätt. De gör konfigurationen tillgänglig för Aspire-klientintegreringar, men inte för utlösare och bindningar. För dessa integreringar anropar du WithEnvironment() för att skicka anslutningsinformationen för utlösaren eller bindningen för att lösa.
I följande exempel visas hur du anger miljövariabeln MyBindingConnection för en resurs som exponerar ett anslutningsstränguttryck:
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);
Om du vill att både Aspire-klientintegreringar och systemet med utlösare och bindningar ska använda en anslutning kan du konfigurera både WithReference() och WithEnvironment().
För vissa resurser kan strukturen för en anslutning skilja sig från när du kör den lokalt och när du publicerar den till Azure. I föregående exempel otherIntegration kan vara en resurs som körs som en emulator, så ConnectionStringExpression skulle returnera en emulatoranslutningssträng. Men när resursen publiceras kan Aspire konfigurera en identitetsbaserad anslutning och ConnectionStringExpression returnera tjänstens URI. I det här fallet kan du behöva ange ett annat miljövariabelnamn för att konfigurera identitetsbaserade anslutningar för Azure Functions.
I följande exempel används builder.ExecutionContext.IsPublishMode för att villkorligt lägga till det nödvändiga suffixet:
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);
Mer information om de anslutningsformat som varje bindning stöder och de behörigheter som dessa format kräver finns i bindningens referenssidor.
För mer information om hur Functions-kod läser värden injicerade av WithReference, se Azure Functions runtime-konfiguration.
Värd för applikationen
Aspire stöder Azure Container Apps-distribution för Functions-projekt. Du kan också använda den separata förhandsgranskningsintegrationen av App Service för att rikta in dig på en containerkapabel funktionsapp:
- Distribuera som en containerapp
- Distribuera som funktionsapp med hjälp av förhandsgranskningen av App Service-integrationen
I båda fallen distribueras projektet som en container. Aspire tar hand om att skapa containeravbildningen åt dig och push-överföra den till Azure Container Registry.
Distribuera som en containerapp
När din AppHost riktar sig mot Azure Container Apps sätter Aspire upp skalningsregler för ditt Functions-projekt med hjälp av KEDA. När du använder Azure Container Apps behöver du göra extra inställningar för funktionstangenter. För mer information, se Access-nycklar i Azure Container Apps.
Distribuera den konfigurerade AppHost genom att köra aspire deploy. För mer information, se Deploy to Azure Container Apps och aspire deploy.
Åtkomstnycklar i Azure Container Apps
Flera Azure Functions-scenarier använder åtkomstnycklar för att ge en grundläggande åtgärd mot oönskad åtkomst. Till exempel kräver HTTP-utlösarfunktioner som standard att en åtkomstnyckel anropas, även om det här kravet kan inaktiveras med hjälp av AuthLevel egenskapen. Se Arbeta med åtkomstnycklar i Azure Functions för scenarier som kan kräva en nyckel.
När du distribuerar ett Functions-projekt genom att använda Aspire till Azure Container Apps, skapar eller hanterar systemet inte automatiskt Functions-åtkomstnycklar. Om du behöver använda accessnycklar kan du hantera dem som en del av din AppHost-uppsättning. Detta avsnitt visar hur du skapar en tilläggsmetod som du kan anropa AppHost.cs från din AppHosts fil för att skapa och hantera åtkomstnycklar. Den här metoden använder Azure Key Vault för att lagra nycklarna och monterar dem i containerappen som hemligheter.
Note
Beteendet här bygger på den hemliga leverantören ContainerApps , som kräver Functions-värdversionen 4.1044.0 eller senare.
De här stegen kräver Bicep-version 0.38.3 eller senare. Du kan kontrollera Bicep-versionen genom att köra bicep --version från en kommandotolk. Om du har Installerat Azure CLI kan du använda az bicep upgrade för att snabbt uppdatera Bicep till den senaste versionen.
Lägg till följande NuGet-paket i ditt AppHost-projekt:
Skapa en ny klass i ditt AppHost-projekt och inkludera följande kod:
using Aspire.Hosting.Azure;
using Azure.Provisioning.AppContainers;
namespace Aspire.Hosting;
internal static class Extensions
{
private record SecretMapping(string OriginalName, IAzureKeyVaultSecretReference Reference);
public static IResourceBuilder<T> PublishWithContainerAppSecrets<T>(
this IResourceBuilder<T> builder,
IResourceBuilder<AzureKeyVaultResource>? keyVault = null,
string[]? hostKeyNames = null,
string[]? systemKeyExtensionNames = null)
where T : AzureFunctionsProjectResource
{
if (!builder.ApplicationBuilder.ExecutionContext.IsPublishMode)
{
return builder;
}
keyVault ??= builder.ApplicationBuilder.AddAzureKeyVault("functions-keys");
var hostKeysToAdd = (hostKeyNames ?? []).Append("default").Select(k => $"host-function-{k}");
var systemKeysToAdd = systemKeyExtensionNames?.Select(k => $"host-systemKey-{k}_extension") ?? [];
var secrets = hostKeysToAdd.Union(systemKeysToAdd)
.Select(secretName => new SecretMapping(
secretName,
CreateSecretIfNotExists(builder.ApplicationBuilder, keyVault, secretName.Replace("_", "-"))
)).ToList();
return builder
.WithReference(keyVault)
.WithEnvironment("AzureWebJobsSecretStorageType", "ContainerApps")
.PublishAsAzureContainerApp((infra, app) => ConfigureFunctionsContainerApp(infra, app, builder.Resource, secrets));
}
private static void ConfigureFunctionsContainerApp(
AzureResourceInfrastructure infrastructure,
ContainerApp containerApp,
IResource resource,
List<SecretMapping> secrets)
{
const string volumeName = "functions-keys";
const string mountPath = "/run/secrets/functions-keys";
var appIdentityAnnotation = resource.Annotations.OfType<AppIdentityAnnotation>().Last();
var containerAppIdentityId = appIdentityAnnotation.IdentityResource.Id.AsProvisioningParameter(infrastructure);
var containerAppSecretsVolume = new ContainerAppVolume
{
Name = volumeName,
StorageType = ContainerAppStorageType.Secret
};
foreach (var mapping in secrets)
{
var secret = mapping.Reference.AsKeyVaultSecret(infrastructure);
containerApp.Configuration.Secrets.Add(new ContainerAppWritableSecret()
{
Name = mapping.Reference.SecretName.ToLowerInvariant(),
KeyVaultUri = secret.Properties.SecretUri,
Identity = containerAppIdentityId
});
containerAppSecretsVolume.Secrets.Add(new SecretVolumeItem
{
Path = mapping.OriginalName.Replace("-", "."),
SecretRef = mapping.Reference.SecretName.ToLowerInvariant()
});
}
containerApp.Template.Containers[0].Value!.VolumeMounts.Add(new ContainerAppVolumeMount
{
VolumeName = volumeName,
MountPath = mountPath
});
containerApp.Template.Volumes.Add(containerAppSecretsVolume);
}
public static IAzureKeyVaultSecretReference CreateSecretIfNotExists(
IDistributedApplicationBuilder builder,
IResourceBuilder<AzureKeyVaultResource> keyVault,
string secretName)
{
var secretParameter = ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"param-{secretName}", special: false);
builder.AddBicepTemplateString($"key-vault-key-{secretName}", """
param location string = resourceGroup().location
param keyVaultName string
param secretName string
@secure()
param secretValue string
// Reference the existing Key Vault
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: keyVaultName
}
// Deploy the secret only if it does not already exist
@onlyIfNotExists()
resource newSecret 'Microsoft.KeyVault/vaults/secrets@2023-07-01' = {
parent: keyVault
name: secretName
properties: {
value: secretValue
}
}
""")
.WithParameter("keyVaultName", keyVault.GetOutput("name"))
.WithParameter("secretName", secretName)
.WithParameter("secretValue", secretParameter);
return keyVault.GetSecret(secretName);
}
}
Du kan sedan använda denna metod i din AppHosts AppHost.cs fil:
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithHostStorage(storage)
.WithExternalHttpEndpoints()
.PublishWithContainerAppSecrets(systemKeyExtensionNames: ["mcp"]);
I det här exemplet används ett standardnyckelvalv som skapats av tilläggsmetoden. Det resulterar i en standardnyckel och en systemnyckel för användning med tillägget Model Context Protocol.
Om du vill använda dessa nycklar från klienter måste du hämta dem från nyckelvalvet.
Distribuera som funktionsapp
Note
Att distribuera som funktionsapp kräver Aspire Azure App Service-integrationen, som för närvarande är i förhandsvisning.
Du kan konfigurera Aspire att distribuera till en funktionsapp genom att använda Aspire Azure App Service-integrationen. Eftersom Aspire distribuerar Functions-projektet som en container måste hostingplanen för din funktionsapp stödja distribution av containeriserade applikationer.
För att distribuera ditt Aspire Functions-projekt som en funktionsapp, följ dessa steg:
- Från AppHost-katalogen, kör
aspire add Aspire.Hosting.Azure.AppServiceför att lägga till Aspire.Hosting.Azure. AppService NuGet-paketet. - I
AppHost.cs-filen anroparAddAzureAppServiceEnvironment()på dinIDistributedApplicationBuilder-instans för att skapa en App Service-plan. Observera att trots namnet etablerar detta inte en App Service Environment-resurs. - Anropa i Functions-projektresursen
.WithExternalHttpEndpoints(). Detta krävs för distribution med Aspire Azure App Service-integreringen. - På projektresursen för Functions anropar du
.PublishAsAzureAppServiceWebsite((infra, app) => app.Kind = "functionapp,linux")för att konfigurera projektet som en funktionsapp i planen.
Important
Kontrollera att du anger egenskapen app.Kind till "functionapp,linux". Den här inställningen säkerställer att resursen skapas som en funktionsapp, vilket påverkar funktioner för att arbeta med ditt program.
Följande exempel visar en minimal AppHost.cs fil som distribuerar ett Functions-projekt som en funktionsapp:
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureAppServiceEnvironment("functions-env");
builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
.WithExternalHttpEndpoints()
.PublishAsAzureAppServiceWebsite((infra, app) => app.Kind = "functionapp,linux");
builder.Build().Run();
Den här konfigurationen skapar en Premium V3-plan. När du använder en dedikerad App Service-plan-SKU är skalning inte händelsebaserad. I stället hanteras skalning via App Service-planinställningarna.
Överväganden och metodtips
Tänk på följande när du utvärderar integreringen av Azure Functions med Aspire:
Konfigurationen av utlösare och bindningar via Aspire är för närvarande begränsad till specifika integreringar. Mer information finns i Anslutningskonfiguration med Aspire i den här artikeln.
Funktionsprojektets
Program.csfil bör användaIHostApplicationBuilderversionen av uppstart av värdinstansen. Genom att användaIHostApplicationBuilderkan du anropabuilder.AddServiceDefaults()för att lägga till Aspire Service Defaults i ditt Functions-projekt.Aspire använder OpenTelemetry för övervakning. Du kan konfigurera Aspire för att exportera data till Azure Monitor via standardprojektet för tjänsten.
I många andra Azure Functions-kontexter kan du inkludera direkt integrering med Application Insights genom att registrera arbetstjänsten. Registrera inte en andra, direkt Application Insights-pipeline när du använder Aspire Service Defaults.
För Functions-projekt som ingår i en Aspire-orkestrering bör AppHost tillhandahålla de flesta applikationskonfigurationer. Du kan använda
local.settings.jsonför att köra Functions-projektet oberoende medfunc start. När Aspire kör projektet åsidosätter Aspire-injicerade miljövariabler värden med samma namn ilocal.settings.json.Undvik att starta en andra Azure Storage-emulator för anslutningar som AppHost hanterar. Samtidiga emulatorinstanser kan orsaka port- och lagringskonflikter.
För mer information, se Azure Functions runtime-konfiguration och Aspire-telemetri.