Skip to content
Docs Try Aspire
Docs Try

Deploy to Kubernetes clusters

Deploy your Aspire application to any existing Kubernetes cluster. Aspire generates a complete Helm chart from your application model, and you can either apply it yourself or let aspire deploy install it directly using your current kubectl context.

For hosting integration setup and configuration, see Kubernetes integration.

Add the Kubernetes hosting integration to your AppHost and configure a Kubernetes environment:

Aspire CLI — Add Kubernetes
aspire add kubernetes

The Aspire CLI adds the 📦 Aspire.Hosting.Kubernetes integration to your AppHost.

Then add the Kubernetes environment in your AppHost:

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var k8s = builder.AddKubernetesEnvironment("k8s");
var api = builder.AddProject<Projects.MyApi>("api");
builder.Build().Run();

When a Kubernetes environment is present, all compute resources are automatically published as Kubernetes workloads — no additional opt-in is required.

Unlike managed targets such as AKS, a vanilla Kubernetes cluster doesn’t know which container registry to use for your application images. Without a registry, Aspire has no way to make your locally-built images available to cluster nodes. You must provide a container registry that is accessible from both your local machine (to push images) and from the cluster (to pull images):

AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var registry = builder.AddContainerRegistry("registry", "myregistry.example.com:5000");
builder.AddKubernetesEnvironment("k8s").WithContainerRegistry(registry);
var api = builder.AddProject<Projects.MyApi>("api");
builder.Build().Run();

The registry endpoint must be reachable from both your local machine and from the Kubernetes cluster nodes. When you run aspire deploy, Aspire builds your container images, pushes them to this registry, and configures the Helm chart to pull from it.

To generate Kubernetes deployment artifacts without deploying, use aspire publish:

Generate Kubernetes artifacts
aspire publish -o k8s-artifacts

This command analyzes your application model and produces a complete Helm chart in the specified output directory:

  • Directoryk8s-artifacts/
    • Chart.yaml Chart metadata (name, version, etc.)
    • values.yaml Configurable values for the chart
    • Directorytemplates/
      • Directory<resource>/
        • deployment.yaml Deployment or StatefulSet
        • service.yaml Service for connectivity
        • config.yaml Configuration data (ConfigMap)

The publisher generates the following Kubernetes resources from your application model:

  • Deployments or StatefulSets for your application services
  • Services for network connectivity between resources
  • ConfigMaps for application configuration, connection strings, and environment variables

You can then deploy these artifacts using helm, kubectl, or your existing GitOps workflow.

To deploy directly to your current Kubernetes cluster, use aspire deploy:

Deploy to Kubernetes
aspire deploy

aspire deploy uses your current kubectl context and deploys the application using helm install. Aspire builds container images, generates the Helm chart, and installs it to the cluster in a single command.

For subsequent deployments, aspire deploy automatically upgrades the existing Helm release.

If you prefer to publish first and deploy separately — for example, in a CI/CD pipeline — use Helm to install the generated chart:

  1. Install the chart to your cluster:

    Install with Helm
    helm install my-app ./k8s-artifacts
  2. For subsequent deployments, upgrade the existing release:

    Upgrade with Helm
    helm upgrade my-app ./k8s-artifacts
  3. Override default values using --set flags or a custom values file:

    Override values
    helm upgrade my-app ./k8s-artifacts \
    --set api.image.repository=myregistry.azurecr.io/api \
    --set api.image.tag=v1.2.0

    Alternatively, create a custom values file for your environment:

    values.production.yaml
    api:
    image:
    repository: myregistry.azurecr.io/api
    tag: v1.2.0
    Deploy with custom values file
    helm upgrade my-app ./k8s-artifacts -f values.production.yaml

Use WithHelm to configure Helm chart settings such as namespace, release name, and chart version:

AppHost.cs
builder.AddKubernetesEnvironment("k8s")
.WithHelm(helm =>
{
helm.WithNamespace("my-namespace");
helm.WithReleaseName("my-release");
helm.WithChartVersion("1.0.0");
});

Helm is the default deployment engine. Call WithHelm only when you need to customize the defaults.

Use AddNodePool to reference an existing node pool in your cluster, then WithNodePool to schedule specific workloads on it:

AppHost.cs
var k8s = builder.AddKubernetesEnvironment("k8s");
var gpuPool = k8s.AddNodePool("gpu");
builder.AddContainer("ml-worker", "my-ml-image")
.WithNodePool(gpuPool);

Use PublishAsKubernetesService to modify the generated Kubernetes resources for individual services:

AppHost.cs
using Aspire.Hosting.Kubernetes.Resources;
builder.AddContainer("service", "nginx")
.WithEnvironment("MY_ENV", "value")
.PublishAsKubernetesService(resource =>
{
// Scale to 3 replicas
if (resource.Workload is Deployment deployment)
{
deployment.Spec.Replicas = 3;
}
});

The publisher generates parameterized Helm values for container image references. If you haven’t specified custom container images, the generated values.yaml contains placeholders that you override at deployment time using --set or a custom values file.

Resource names in Kubernetes must follow DNS naming conventions. The integration automatically normalizes Aspire resource names by:

  • Converting to lowercase
  • Replacing invalid characters with hyphens
  • Ensuring names don’t start or end with hyphens

Use external parameters to configure values that differ between development and production environments.

In Kubernetes, services discover each other using the cluster’s built-in DNS. A service named api is reachable at api.<namespace>.svc.cluster.local. The generated Helm charts configure service references automatically using Kubernetes-native DNS resolution.

If your application can’t find connection strings at runtime, verify that the generated ConfigMaps and Secrets are correctly mounted as environment variables in your pod specifications. Check that the resource names in your Helm values match the expected connection string names.

Kubernetes Secrets store values as base64-encoded strings. Verify that your Secrets are properly encoded and that the generated templates reference them correctly. Use kubectl get secret <name> -o yaml to inspect Secret contents.