İçeriğe geç

Customize Azure resources

Bu içerik henüz dilinizde mevcut değil.

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.

The ConfigureInfrastructure API provides a strongly-typed, C#-based way to customize Azure resources. This is the recommended approach for most customizations.

All Azure resources in Aspire inherit from AzureProvisioningResource, which exposes the ConfigureInfrastructure method:

C# — AppHost.cs
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";
});
storage.ConfigureInfrastructure(infra =>
{
var account = infra.GetProvisionableResources()
.OfType<StorageAccount>()
.Single();
account.Sku = new StorageSku
{
Name = StorageSkuName.StandardGRS
};
account.Kind = StorageKind.StorageV2;
});
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"
});
});
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 }
}
};
});

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);
}
});

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);
});

For more complex scenarios or when you need full control, you can provide custom Bicep templates.

Create a custom Bicep file in your AppHost project:

custom-storage.bicep
@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:

C# — AppHost.cs
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);

You can combine ConfigureInfrastructure with custom Bicep for maximum flexibility:

// Start with Aspire's default
var storage = builder.AddAzureStorage("storage");
// Customize with ConfigureInfrastructure
storage.ConfigureInfrastructure(infra =>
{
var account = infra.GetProvisionableResources()
.OfType<StorageAccount>()
.Single();
account.Sku = new StorageSku { Name = StorageSkuName.PremiumLRS };
});
// Add custom resources via Bicep
var customResource = builder.AddAzureBicepResource(
name: "custom",
bicepFilePath: "./custom-resource.bicep");

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 maintainable
storage.ConfigureInfrastructure(infra =>
{
var account = infra.GetProvisionableResources()
.OfType<StorageAccount>()
.Single();
account.Sku = new StorageSku { Name = StorageSkuName.PremiumLRS };
});

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 place
var 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 };
});

After customization, you can inspect the generated Bicep:

  1. Run your AppHost locally
  2. Check the ./infra directory in your AppHost project
  3. Review the generated .bicep files

The generated files reflect all customizations made via ConfigureInfrastructure.

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}");
}
});

If a property isn’t available in the Azure.Provisioning types, you may need to:

  1. Update to the latest Aspire version
  2. Use custom Bicep for that specific property
  3. File an issue on the Aspire GitHub repository

Azure will validate your configuration during deployment. Common issues:

  • Invalid SKU names or combinations
  • Location mismatches
  • Naming convention violations
  • Missing required properties
Sor & YanıtlaİşbirliğiToplulukTartışİzle