| File: AppHost.cs | Web Access |
| Project: src\playground\AksDemo\AksDemo.AppHost\AksDemo.AppHost.csproj (AksDemo.AppHost) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma warning disable ASPIREAZURE003 // AddSubnet / AzureSubnetResource are evaluation-only var builder = DistributedApplication.CreateBuilder(args); // VNet layout: // 10.100.0.0/16 - vnet (chosen to avoid the AKS default service CIDR 10.0.0.0/16) // 10.100.0.0/22 - aks node pool subnet (1024 IPs - room for pods/nodes) // 10.100.4.0/24 - public AGC frontend subnet (delegated to ServiceNetworking by AddLoadBalancer) // 10.100.5.0/24 - admin AGC frontend subnet // // AGC requires the ALB frontend subnet to be /24 or larger and to be delegated to // Microsoft.ServiceNetworking/trafficControllers. AddLoadBalancer applies the delegation // for us; we just need to make sure the AKS subnet and ALB subnets do not overlap. var vnet = builder.AddAzureVirtualNetwork("vnet", "10.100.0.0/16"); var aksSubnet = vnet.AddSubnet("aks-nodes", "10.100.0.0/22"); var publicSubnet = vnet.AddSubnet("alb-public", "10.100.4.0/24"); var adminSubnet = vnet.AddSubnet("alb-admin", "10.100.5.0/24"); var aks = builder.AddAzureKubernetesEnvironment("aks") .WithSubnet(aksSubnet) // Use the same AMD-based SKU as our AKS deployment E2E tests so this // playground deploys consistently across regions and quotas. .WithSystemNodePool("Standard_D2as_v5"); aks.AddNodePool("workload", "Standard_D2as_v5", minCount: 1, maxCount: 3); // Two AGC ApplicationLoadBalancers. Each AGC ALB caps at 5 frontends, so production apps // often need to spread Gateways/Ingresses across multiple LBs. This playground uses two // just to exercise the multi-LB code path. var publicLb = aks.AddLoadBalancer("public", publicSubnet); var adminLb = aks.AddLoadBalancer("admin", adminSubnet); var api = builder.AddProject<Projects.AksDemo_ApiService>("api") .WithExternalHttpEndpoints(); // Public gateway: serves /api -> the api service, attached to the public AGC ALB. // WithLoadBalancer attaches the alb.networking.azure.io association annotations and // defaults the gatewayClassName to "azure-alb-external". // // WithTls() (no hostname) creates an HTTPS listener that gets its hostname patched in // by Aspire's tls-fqdn-discovery pipeline step once AGC assigns the gateway its // <random>.fz<n>.alb.azure.com FQDN. The cert-manager.io/cluster-issuer annotation // then triggers cert-manager to issue a real Let's Encrypt cert via HTTP-01 against // that FQDN. A `letsencrypt-prod` ClusterIssuer needs to exist in the cluster. aks.AddGateway("storefront-gw") .WithLoadBalancer(publicLb) .WithRoute("/api", api.GetEndpoint("http")) .WithTls() .WithGatewayAnnotation("cert-manager.io/cluster-issuer", "letsencrypt-prod"); // Admin gateway: serves the same backend but on a separate AGC ALB so a different set of // network policies, frontends, or DNS names can hang off it. aks.AddGateway("admin-gw") .WithLoadBalancer(adminLb) .WithRoute("/admin", api.GetEndpoint("http")); // cert-manager installed via Helm so we can issue Let's Encrypt certificates for the AGC // gateways via the HTTP-01 challenge. Gateway API support is enabled so cert-manager will // watch Gateway listeners for TLS configuration and auto-issue Certificates. // // WithForceConflicts is needed because AKS clusters with the Azure Policy add-on (or // Deployment Safeguards) install an `admissionsenforcer` field manager that mutates the // cert-manager ValidatingWebhookConfiguration after the first install. Helm's SSA then // fails the next upgrade with a conflict on .webhooks[*].namespaceSelector. // WithForceConflicts adds --force-conflicts which tells SSA to take over the conflicting // field non-destructively (no resources recreated). aks.AddHelmChart("cert-manager", "oci://quay.io/jetstack/charts/cert-manager", "v1.18.2") .WithHelmValue("crds.enabled", "true") .WithHelmValue("config.apiVersion", "controller.config.cert-manager.io/v1alpha1") .WithHelmValue("config.kind", "ControllerConfiguration") .WithHelmValue("config.enableGatewayAPI", "true") .WithForceConflicts() .WithDestroy(); builder.Build().Run();