Skip to content

Helm charts

Kubernetes.HelmChart installs a Helm chart as one resource. Alchemy renders the chart with the local helm CLI (helm template) and applies the rendered objects with the same server-side apply machinery as a Manifest.

const metricsServer = yield* Kubernetes.HelmChart("MetricsServer", {
cluster,
chart: "metrics-server",
repo: "https://kubernetes-sigs.github.io/metrics-server/",
version: "3.14.0",
releaseName: "metrics-server",
namespace: "kube-system",
values: { replicas: 2 },
});

Install helm on every machine that deploys, including CI runners. Set HELM_BIN to use a binary that isn’t on PATH. Helm never connects to the cluster. Rendering is local, and Alchemy does the applying.

  • Classic repository. Set chart to the chart name, for example "metrics-server". Also set repo and version.
  • OCI registry. Set chart to an oci:// reference, for example "oci://ghcr.io/stefanprodan/charts/podinfo". Also set version.
  • Local directory. Set chart to a path such as "./charts/app".

Pin version for repository and OCI charts. Without it, Helm renders the newest version on each deploy, and what’s applied changes whenever the chart publishes. Local charts are hashed file by file, so editing a template triggers an update on the next deploy.

values is a literal object in the shape of the chart’s values.yaml:

const podinfo = yield* Kubernetes.HelmChart("Podinfo", {
cluster,
chart: "oci://ghcr.io/stefanprodan/charts/podinfo",
version: "6.15.0",
releaseName: "podinfo",
namespace: ns.name,
values: {
replicaCount: 2,
ui: { message: "rendered by Alchemy" },
redis: { enabled: true },
},
});

Values can include Outputs from other resources. Any change to the values, chart, version, or release name re-renders the chart on the next deploy.

The release name is what the chart’s templates see as .Release.Name, and most charts name their objects after it. Without releaseName, Alchemy generates one from the stack, stage, and logical ID. The generated name is at most 53 characters, which is Helm’s limit. Set it explicitly when you want predictable object names.

namespace (default default) is .Release.Namespace, and Alchemy also sets it on any namespaced object the chart leaves without one. The namespace must exist, or set createNamespace: true to have the resource create and own the Namespace object.

Changing releaseName, namespace, or cluster replaces the chart. Alchemy applies the new render, then deletes every object from the old one.

Objects in the chart’s crds/ directory are rendered too (includeCrds defaults to true). Alchemy applies Namespaces first, then CRDs, then everything else, so a chart’s own custom resources find their definitions. Set includeCrds: false when the CRDs are managed elsewhere.

The chart is rendered with --no-hooks. Objects annotated with helm.sh/hook are neither applied nor run. These include install and upgrade Jobs and test pods. Some charts depend on hooks to work correctly, for example to run database migrations or generate certificates. Install those charts with Helm itself.

Alchemy doesn’t create a Helm release. helm list won’t show the chart, and helm upgrade or helm rollback don’t apply. Alchemy records every object it applied and, on each update:

  • applies the new render,
  • deletes objects that were in the previous render but not in the new one,
  • on destroy, deletes every object it applied.

To move a chart that’s currently installed with helm install under Alchemy, run helm uninstall first, then deploy the HelmChart.

  • releaseName is the release name the chart rendered with.
  • namespace is the namespace the chart rendered into.
  • chart is the chart reference.
  • version is the pinned version, if any.
  • objects holds references to every applied object.
  • connection is the cluster connection.