Customize Azure resources
Dette indhold er ikke tilgængeligt i dit sprog endnu.
When working with Azure integrations in Aspire, you often need to customize the generated infrastructure beyond the default settings. Aspire provides two main approaches for customizing Azure resources: using the ConfigureInfrastructure API and creating custom Bicep templates.
Azure.Provisioning customization
Section titled “Azure.Provisioning customization”The ConfigureInfrastructure API provides a strongly-typed, C#-based way to customize Azure resources. This is the recommended approach for most customizations.
Basic infrastructure customization
Section titled “Basic infrastructure customization”All Azure resources in Aspire inherit from AzureProvisioningResource, which exposes the ConfigureInfrastructure method:
var builder = DistributedApplication.CreateBuilder(args);
var storage = builder.AddAzureStorage("storage");
storage.ConfigureInfrastructure(infra =>{ // Get the storage account resource var storageAccount = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single();
// Customize the SKU storageAccount.Sku = new StorageSku { Name = StorageSkuName.PremiumLRS };
// Add tags storageAccount.Tags["Environment"] = "Development"; storageAccount.Tags["CostCenter"] = "Engineering";});Common customization scenarios
Section titled “Common customization scenarios”Configure SKUs and tiers
Section titled “Configure SKUs and tiers”storage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single();
account.Sku = new StorageSku { Name = StorageSkuName.StandardGRS }; account.Kind = StorageKind.StorageV2;});serviceBus.ConfigureInfrastructure(infra =>{ var ns = infra.GetProvisionableResources() .OfType<ServiceBusNamespace>() .Single();
ns.Sku = new ServiceBusSku { Name = ServiceBusSkuName.Premium, Capacity = 2 };});redis.ConfigureInfrastructure(infra =>{ var cache = infra.GetProvisionableResources() .OfType<RedisCache>() .Single();
cache.Sku = new RedisCacheSku { Name = RedisCacheSkuName.Premium, Family = RedisCacheSkuFamily.P, Capacity = 1 };});Configure networking
Section titled “Configure networking”storage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single();
// Enable firewall account.NetworkRuleSet = new StorageAccountNetworkRuleSet { DefaultAction = StorageNetworkDefaultAction.Deny, Bypass = "AzureServices" };
// Allow specific IP account.NetworkRuleSet.IpRules.Add(new StorageAccountIPRule { IPAddressOrRange = "203.0.113.0/24", Action = "Allow" });});Configure security and compliance
Section titled “Configure security and compliance”storage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single();
// Require HTTPS account.EnableHttpsTrafficOnly = true;
// Configure TLS version account.MinimumTlsVersion = StorageMinimumTlsVersion.Tls1_2;
// Enable blob encryption account.Encryption = new StorageAccountEncryption { KeySource = StorageAccountKeySource.MicrosoftStorage, Services = new StorageAccountEncryptionServices { Blob = new StorageEncryptionService { Enabled = true }, File = new StorageEncryptionService { Enabled = true } } };});Working with multiple resources
Section titled “Working with multiple resources”When an integration creates multiple resources, you can customize each one:
var servicebus = builder.AddAzureServiceBus("messaging");var queue = servicebus.AddQueue("orders");
servicebus.ConfigureInfrastructure(infra =>{ // Customize the namespace var ns = infra.GetProvisionableResources() .OfType<ServiceBusNamespace>() .Single(); ns.Sku = new ServiceBusSku { Name = ServiceBusSkuName.Standard };
// Customize the queue var queueResource = infra.GetProvisionableResources() .OfType<ServiceBusQueue>() .FirstOrDefault(q => q.Name.Contains("orders"));
if (queueResource != null) { queueResource.MaxDeliveryCount = 5; queueResource.DefaultMessageTimeToLive = TimeSpan.FromHours(24); }});Adding Azure resources
Section titled “Adding Azure resources”You can add additional Azure resources to the infrastructure:
storage.ConfigureInfrastructure(infra =>{ // Add a private endpoint var privateEndpoint = new PrivateEndpoint("storagepe") { Location = "eastus", Subnet = new SubnetReference { Id = "/subscriptions/.../subnets/mysubnet" } };
infra.Add(privateEndpoint);});Custom Bicep templates
Section titled “Custom Bicep templates”For more complex scenarios or when you need full control, you can provide custom Bicep templates.
Using custom Bicep files
Section titled “Using custom Bicep files”Create a custom Bicep file in your AppHost project:
@description('Storage account name')param storageAccountName string
@description('Location')param location string = resourceGroup().location
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = { name: storageAccountName location: location sku: { name: 'Premium_LRS' } kind: 'BlockBlobStorage' properties: { minimumTlsVersion: 'TLS1_2' allowBlobPublicAccess: false networkAcls: { defaultAction: 'Deny' bypass: 'AzureServices' } }}
output connectionString string = 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};...'Reference it in your AppHost:
var builder = DistributedApplication.CreateBuilder(args);
var storage = builder.AddAzureBicepResource( name: "storage", bicepFilePath: "./custom-storage.bicep") .WithParameter("storageAccountName", "mystorageaccount");
builder.AddProject<Projects.WebApp>("webapp") .WithReference(storage);Combining approaches
Section titled “Combining approaches”You can combine ConfigureInfrastructure with custom Bicep for maximum flexibility:
// Start with Aspire's defaultvar storage = builder.AddAzureStorage("storage");
// Customize with ConfigureInfrastructurestorage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single(); account.Sku = new StorageSku { Name = StorageSkuName.PremiumLRS };});
// Add custom resources via Bicepvar customResource = builder.AddAzureBicepResource( name: "custom", bicepFilePath: "./custom-resource.bicep");Best practices
Section titled “Best practices”Use ConfigureInfrastructure for standard customizations
Section titled “Use ConfigureInfrastructure for standard customizations”For common property changes like SKUs, tags, and basic configuration, prefer ConfigureInfrastructure:
// ✅ Good - Simple and maintainablestorage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single(); account.Sku = new StorageSku { Name = StorageSkuName.PremiumLRS };});Use custom Bicep for complex scenarios
Section titled “Use custom Bicep for complex scenarios”Use custom Bicep when you need:
- Complex networking configurations
- Multiple interconnected resources
- Custom resource types not in Azure.Provisioning
- Advanced policy configurations
Keep infrastructure code close to application code
Section titled “Keep infrastructure code close to application code”Define infrastructure customizations in your AppHost alongside resource declarations:
// All storage configuration in one placevar storage = builder.AddAzureStorage("storage") .ConfigureInfrastructure(infra => { // Customizations here });Use configuration for environment-specific values
Section titled “Use configuration for environment-specific values”Don’t hard-code environment-specific values:
var skuName = builder.Configuration["Azure:Storage:Sku"] ?? "Standard_LRS";
storage.ConfigureInfrastructure(infra =>{ var account = infra.GetProvisionableResources() .OfType<StorageAccount>() .Single(); account.Sku = new StorageSku { Name = skuName };});Generated Bicep inspection
Section titled “Generated Bicep inspection”After customization, you can inspect the generated Bicep:
- Run your AppHost locally
- Check the
./infradirectory in your AppHost project - Review the generated
.bicepfiles
The generated files reflect all customizations made via ConfigureInfrastructure.
Troubleshooting
Section titled “Troubleshooting”Finding resource types
Section titled “Finding resource types”If you’re unsure what resource type to use:
storage.ConfigureInfrastructure(infra =>{ // List all resources var resources = infra.GetProvisionableResources(); foreach (var resource in resources) { Console.WriteLine($"Type: {resource.GetType().Name}"); }});Property not available
Section titled “Property not available”If a property isn’t available in the Azure.Provisioning types, you may need to:
- Update to the latest Aspire version
- Use custom Bicep for that specific property
- File an issue on the Aspire GitHub repository
Validation errors
Section titled “Validation errors”Azure will validate your configuration during deployment. Common issues:
- Invalid SKU names or combinations
- Location mismatches
- Naming convention violations
- Missing required properties