Skip to content

Support existing Azure Kubernetes environments - #20921

Open
Mitch Denny (mitchdenny) wants to merge 8 commits into
mainfrom
mitchdenny-existing-aks-environments
Open

Mitch Denny (mitchdenny) wants to merge 8 commits into
mainfrom
mitchdenny-existing-aks-environments

Conversation

@mitchdenny

@mitchdenny Mitch Denny (mitchdenny) commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Description

Allow Aspire applications to deploy to a pre-provisioned AKS cluster using the shared Azure AsExisting APIs, following the Azure Container Apps and App Service approach.

Existing clusters are referenced without reconfiguring their node pools, networking, or add-ons. Aspire does not create or implicitly select a workload node pool for them. Supporting infrastructure remains in the application's resource group, while deployment credentials and workload cleanup target the cluster's actual identity. OIDC is only required when workloads use workload identity.

The implementation reuses existing API signatures and introduces no dependencies. The README documents prerequisites and warns that the cluster must be outside the application's resource group to survive aspire destroy.

Fixes #17711

User-facing usage

AsExisting

Use an existing cluster in the current subscription scope. Pass a resource-group parameter, or null to use the application's resource group.

var clusterName = builder.AddParameter("cluster-name");
var resourceGroup = builder.AddParameter("cluster-resource-group");

var aks = builder.AddAzureKubernetesEnvironment("aks")
    .AsExisting(clusterName, resourceGroup);

builder.AddProject<Projects.MyService>("myservice")
    .WithComputeEnvironment(aks);

AsExistingInResourceGroup

Use an existing cluster with an explicit resource group and subscription.

var clusterName = builder.AddParameter("cluster-name");
var resourceGroup = builder.AddParameter("cluster-resource-group");
var subscription = builder.AddParameter("cluster-subscription");

var aks = builder.AddAzureKubernetesEnvironment("aks")
    .AsExistingInResourceGroup(clusterName, resourceGroup, subscription);

builder.AddProject<Projects.MyService>("myservice")
    .WithComputeEnvironment(aks);

Validation

  • dotnet test --project tests/Aspire.Hosting.Azure.Kubernetes.Tests/Aspire.Hosting.Azure.Kubernetes.Tests.csproj --no-launch-profile -- --filter-not-trait 'quarantined=true' --filter-not-trait 'outerloop=true' - passed, 126 tests.
  • dotnet test --project tests/Aspire.Hosting.Azure.Tests/Aspire.Hosting.Azure.Tests.csproj --no-launch-profile -- --filter-class '*.BicepUtilitiesTests' --filter-class '*.AzureBicepProvisionerTests' --filter-class '*.AzureBicepResourceTests' --filter-class '*.AzureProvisioningResourceTests' --filter-class '*.AzureBicepResourceScopeTests' --filter-not-trait 'quarantined=true' --filter-not-trait 'outerloop=true' - passed, 175 tests.
  • dotnet build tests/Aspire.Deployment.EndToEnd.Tests/Aspire.Deployment.EndToEnd.Tests.csproj --no-restore - passed, no warnings or errors.
  • gh workflow run deployment-tests.yml --repo microsoft/aspire --ref mitchdenny-existing-aks-environments -f test_filter=AksExistingClusterDeploymentTests - passed, including the full CI build and live deployment test on commit 225b03c23ca9e170b7a749a2ff1c04cdd5605e19 (1 passed, 0 skipped).

The new E2E test creates an AKS cluster with Azure CLI and passes its complete resource ID as a deployment parameter. It verifies the deployed API response, unchanged cluster configuration, and absence of a second cluster in the application's resource group. It then runs aspire destroy, verifies that workloads are removed and the existing cluster survives, and requests cleanup of both test-owned resource groups.

The bootstrap explicitly verifies that OIDC and workload identity are disabled. It uses Kubernetes 1.33 with AKS Long-Term Support because newly created 1.34+ clusters enable OIDC by default and cannot disable it afterward. Regression coverage also verifies subscription inheritance for resource-group-only existing references, preview API selection for existing clusters with ALB, and preservation of annotation-based module scope for Sandbox groups and Foundry projects.

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 20921

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 20921"

@aspire-repo-bot
aspire-repo-bot Bot requested a balanced review from Copilot October 12, 2026 10:27
@github-actions github-actions Bot added the area-integrations Issues pertaining to Aspire Integrations packages label Oct 12, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Existing clusters without OIDC can fail because the generated Bicep still reads the optional OIDC issuer output.

1 open finding
What changed in this PR

Adds deployment support for pre-provisioned AKS clusters while preserving cluster-owned configuration and cleanup boundaries.

Changes:

  • References existing AKS clusters through shared Azure existing-resource APIs.
  • Corrects provisioning scope, credential acquisition, and destroy behavior.
  • Adds unit, snapshot, and live deployment coverage plus documentation.
File Description
tests/​Aspire.Hosting.Azure.Tests/​BicepUtilitiesTests.cs Tests compute-environment module scope behavior.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​Snapshots/​AzureKubernetesInfrastructureTests.ExistingCluster_PreservesWorkloadIdentity.verified.bicep Captures existing-cluster workload identity infrastructure.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​Snapshots/​AzureKubernetesEnvironmentExtensionsTests.AsExisting_GeneratesExistingCluster_crossResourceGroup=True.verified.bicep Captures cross-resource-group AKS references.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​Snapshots/​AzureKubernetesEnvironmentExtensionsTests.AsExisting_GeneratesExistingCluster_crossResourceGroup=False.verified.bicep Captures same-scope AKS references.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​Snapshots/​AzureKubernetesEnvironmentExtensionsTests.AddAsExistingResource_ReusesReference_existing=True.verified.bicep Verifies existing reference reuse.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​Snapshots/​AzureKubernetesEnvironmentExtensionsTests.AddAsExistingResource_ReusesReference_existing=False.verified.bicep Verifies provisioned-cluster reference reuse.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​AzureKubernetesInfrastructureTests.cs Tests node pools, identity, credentials, and destroy behavior.
tests/​Aspire.Hosting.Azure.Kubernetes.Tests/​AzureKubernetesEnvironmentExtensionsTests.cs Tests existing-resource APIs and generated Bicep.
tests/​Aspire.Deployment.EndToEnd.Tests/​AksExistingClusterDeploymentTests.cs Exercises deployment and cleanup against a live existing cluster.
src/​Aspire.Hosting.Azure/​Provisioning/​BicepUtilities.cs Keeps supporting infrastructure in the module scope.
src/​Aspire.Hosting.Azure.Kubernetes/​README.md Documents existing-cluster usage and prerequisites.
src/​Aspire.Hosting.Azure.Kubernetes/​AzureKubernetesEnvironmentResource.cs Adds reusable existing AKS references.
src/​Aspire.Hosting.Azure.Kubernetes/​AzureKubernetesEnvironmentResource.AksPipeline.cs Adjusts node-pool, credential, and destroy handling.
src/​Aspire.Hosting.Azure.Kubernetes/​AzureKubernetesEnvironmentExtensions.cs Emits existing rather than newly provisioned AKS resources.

🧠 Review effort: Balanced

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found 2 correctness issues: partial existing-cluster scope resolution can target the wrong subscription, and existing clusters with an ALB retain a stable API version that cannot expose the required controller identity. Both were reproduced with focused regression probes. Validation: 92 AKS tests and 31 BicepUtilities tests passed; three unchanged snapshot tests failed due to local CRLF line endings. Confirmed the PR live deployment run passed on the reviewed commit, but it does not cover these edge cases.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The ownership, scoping, credential, and cleanup paths are consistently implemented and covered by focused and live deployment tests.

0 open findings

1 resolved since last review

🧠 Review effort: Balanced

…sion

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The broad scope bypass breaks some existing cross-resource-group compute environments, and the new E2E test uses a collision-prone fixed port.

1 open finding
Previously missed (1)

In code that hasn't changed since last review

Medium severity Use an available port instead of fixed port 18080 in deployment test

tests/​Aspire.Deployment.EndToEnd.Tests/​AksExistingClusterDeploymentTests.cs:124

The fixed local port makes this deployment test fail whenever port 18080 is already occupied, which is a known flaky-test pattern in this repository. Allocate an available port and pass it to both kubectl port-forward and curl; AksPersistentVolumeDeploymentTests.GetAvailablePort() demonstrates the existing approach.

🧠 Review effort: Balanced

Comment thread src/Aspire.Hosting.Azure/Provisioning/BicepUtilities.cs Outdated
…-scoped references

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 14f4e734-0b32-464c-8c0c-37babdc5349c

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Core scoping, credentials, cleanup, and no-OIDC behavior have focused tests and successful live validation; the remaining README gap is non-blocking.

0 open findings

2 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Low severity Add TypeScript example for existing-cluster API usage

src/​Aspire.Hosting.Azure.Kubernetes/​README.md:52

This new usage section documents an API that is exported to TypeScript, but only provides the C# form. Add the equivalent TypeScript example so polyglot AppHost users can discover the existing-cluster path, consistent with the two-language usage example above.

🧠 Review effort: Balanced

This branch was successfully deployed

1 active deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-integrations Issues pertaining to Aspire Integrations packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add AsExisting(...) support for AddAzureKubernetesEnviroment (ACR parity)

4 participants