Pulumi lets you manage cloud infrastructure using familiar programming languages, and when it comes to Kubernetes, that often means dealing with Helm charts.

Here’s a Helm chart deployment in Python, showing how Pulumi treats it like any other resource:

import pulumi
import pulumi_kubernetes as kubernetes

# Assume you have a Helm chart available locally or in a repository.
# For this example, let's assume it's a local chart in a directory named 'my-helm-chart'.
# If it's in a repo, you'd use `repo="https://charts.example.com/"` and `chart="my-chart"`.

helm_chart = kubernetes.helm.v3.Chart(
    "my-app-release",
    kubernetes.helm.v3.ChartArgs(
        chart="my-chart",  # The name of the chart within the repo or local directory
        version="1.2.3",   # Specify the chart version
        namespace="production", # The Kubernetes namespace to deploy into
        values={
            "replicaCount": 3,
            "image": {
                "repository": "nginx",
                "tag": "stable",
            },
            "service": {
                "type": "LoadBalancer",
            },
        },
        # If the chart is in a local directory:
        # pulumi.Config().require("chartPath") is a way to get this from config,
        # but for a direct example, we'll hardcode it.
        # If your chart is in a local directory, you'd typically point to it.
        # For remote charts, you'd use `repo` and `chart` as shown above.
        # Let's simulate a local chart path for demonstration:
        # chart_path="./my-helm-chart" # This would be used if chart is a local directory
    ),
    opts=pulumi.ResourceOptions(provider=kubernetes_provider) # Assuming kubernetes_provider is configured
)

# Export a relevant output, like the LoadBalancer IP if applicable
pulumi.export("app_service_ip", helm_chart.get_output("service.loadBalancer.ingress[0].ip"))

The most surprising thing about managing Helm charts with Pulumi is that you don’t actually run helm commands. Pulumi’s Kubernetes provider has a dedicated Helm module that understands Helm chart structures and values, translating them into Kubernetes API calls directly. It’s not a wrapper around the helm CLI; it’s a native integration.

When you define a kubernetes.helm.v3.Chart resource, Pulumi’s Kubernetes provider does the heavy lifting. It fetches the chart (either from a specified repository or a local path), renders the templates with your provided values, and then applies the resulting Kubernetes manifests to your cluster using the Kubernetes API. This means Pulumi has full visibility into the deployed resources, allowing it to track their state, handle updates, and manage their lifecycle just like any other Pulumi-managed resource.

This approach gives you several advantages. You can use Pulumi’s core features like state management, diffing, and programmatic control over your Helm deployments. You can also integrate Helm charts into larger infrastructure deployments, managing dependencies between Helm releases and other Kubernetes resources or cloud infrastructure managed by Pulumi.

Let’s break down the ChartArgs for more clarity:

  • chart: The name of the chart to deploy. If using a repository, this is the chart name (e.g., nginx for stable/nginx). If using a local chart, this is the name of the directory containing the Chart.yaml file.
  • version: The specific version of the chart to deploy. This is crucial for ensuring reproducible deployments.
  • namespace: The Kubernetes namespace where the chart will be installed. If it doesn’t exist, Pulumi can often create it for you (though explicit namespace resources are recommended for clarity).
  • values: A dictionary representing the values.yaml for the Helm chart. These are the configuration parameters you’d normally pass to helm install or helm upgrade using the -f flag or --set arguments. Pulumi handles this as a direct input.
  • repo: (For remote charts) The URL of the Helm repository containing the chart.
  • chart_path: (For local charts) The path to the directory containing the Helm chart.

The opts=pulumi.ResourceOptions(provider=kubernetes_provider) line is essential. It tells Pulumi which Kubernetes cluster and configuration to use for deploying the Helm chart. You’d typically configure your kubernetes_provider earlier in your Pulumi program to point to your desired cluster context.

Consider a scenario where you need to deploy a database Helm chart and then a web application that depends on it. Pulumi handles this naturally through resource dependencies.

# Assuming db_release is a pulumi.Resource representing the database Helm release
# and web_app_release is the web application Helm release.

web_app_release = kubernetes.helm.v3.Chart(
    "my-web-app",
    kubernetes.helm.v3.ChartArgs(
        chart="webapp",
        namespace="production",
        values={
            "databaseUrl": db_release.status.apply(lambda status: status.get("db_service_url")), # Example of referencing an output
            "replicaCount": 2,
        },
    ),
    opts=pulumi.ResourceOptions(provider=kubernetes_provider, depends_on=[db_release]) # Explicitly set dependency
)

By using depends_on=[db_release], Pulumi ensures that the database release is fully provisioned and ready before it attempts to deploy the web application. This is a fundamental benefit of managing infrastructure-as-code with Pulumi.

The one thing that often trips people up is how Pulumi fetches and processes the Helm chart. It doesn’t execute helm fetch or helm template and then kubectl apply. Instead, it uses a Go library (or equivalent in other languages) that directly interacts with Helm’s internal APIs. This means it understands Helm’s lifecycle hooks, dependencies, and templating logic without relying on the external helm binary. You can even use Pulumi configuration values to dynamically set Helm chart values.

This native integration allows Pulumi to provide detailed status and outputs from the Helm release, which can then be used to configure other resources or be exported as stack outputs.

The next step after deploying Helm charts might be to manage custom resources defined within those charts, or to integrate Pulumi’s secrets management with sensitive Helm chart values.

Want structured learning?

Take the full Pulumi course →