| 1 | --- |
| 2 | title: Helm charts |
| 3 | description: Install Helm charts with Kubernetes.HelmChart. Covers repository, OCI, and local charts, values, release names, namespaces, CRDs, hooks, and how Alchemy owns the rendered objects instead of a Helm release. |
| 4 | --- |
| 5 | |
| 6 | [`Kubernetes.HelmChart`](/providers/kubernetes/helmchart) installs a |
| 7 | Helm chart as one resource. Alchemy renders the chart with the local |
| 8 | `helm` CLI (`helm template`) and applies the rendered objects with |
| 9 | the same server-side apply machinery as a |
| 10 | [Manifest](/kubernetes/objects/manifests). |
| 11 | |
| 12 | ```typescript |
| 13 | const metricsServer = yield* Kubernetes.HelmChart("MetricsServer", { |
| 14 | cluster, |
| 15 | chart: "metrics-server", |
| 16 | repo: "https://kubernetes-sigs.github.io/metrics-server/", |
| 17 | version: "3.14.0", |
| 18 | releaseName: "metrics-server", |
| 19 | namespace: "kube-system", |
| 20 | values: { replicas: 2 }, |
| 21 | }); |
| 22 | ``` |
| 23 | |
| 24 | ## Requirements |
| 25 | |
| 26 | Install [`helm`](https://helm.sh/docs/intro/install/) on every |
| 27 | machine that deploys, including CI runners. Set `HELM_BIN` to use a |
| 28 | binary that isn't on `PATH`. Helm never connects to the cluster. |
| 29 | Rendering is local, and Alchemy does the applying. |
| 30 | |
| 31 | ## Chart sources |
| 32 | |
| 33 | - **Classic repository.** Set `chart` to the chart name, for example |
| 34 | `"metrics-server"`. Also set `repo` and `version`. |
| 35 | - **OCI registry.** Set `chart` to an `oci://` reference, for |
| 36 | example `"oci://ghcr.io/stefanprodan/charts/podinfo"`. Also set |
| 37 | `version`. |
| 38 | - **Local directory.** Set `chart` to a path such as |
| 39 | `"./charts/app"`. |
| 40 | |
| 41 | Pin `version` for repository and OCI charts. Without it, Helm |
| 42 | renders the newest version on each deploy, and what's applied changes |
| 43 | whenever the chart publishes. Local charts are hashed file by file, |
| 44 | so editing a template triggers an update on the next deploy. |
| 45 | |
| 46 | ## Values |
| 47 | |
| 48 | `values` is a literal object in the shape of the chart's |
| 49 | `values.yaml`: |
| 50 | |
| 51 | ```typescript |
| 52 | const podinfo = yield* Kubernetes.HelmChart("Podinfo", { |
| 53 | cluster, |
| 54 | chart: "oci://ghcr.io/stefanprodan/charts/podinfo", |
| 55 | version: "6.15.0", |
| 56 | releaseName: "podinfo", |
| 57 | namespace: ns.name, |
| 58 | values: { |
| 59 | replicaCount: 2, |
| 60 | ui: { message: "rendered by Alchemy" }, |
| 61 | redis: { enabled: true }, |
| 62 | }, |
| 63 | }); |
| 64 | ``` |
| 65 | |
| 66 | Values can include Outputs from other resources. Any change to the |
| 67 | values, chart, version, or release name re-renders the chart on the |
| 68 | next deploy. |
| 69 | |
| 70 | ## Release name and namespace |
| 71 | |
| 72 | The release name is what the chart's templates see as |
| 73 | `.Release.Name`, and most charts name their objects after it. Without |
| 74 | `releaseName`, Alchemy generates one from the stack, stage, and |
| 75 | logical ID. The generated name is at most 53 characters, which is |
| 76 | Helm's limit. Set it explicitly when you want predictable object |
| 77 | names. |
| 78 | |
| 79 | `namespace` (default `default`) is `.Release.Namespace`, and Alchemy |
| 80 | also sets it on any namespaced object the chart leaves without one. |
| 81 | The namespace must exist, or set `createNamespace: true` to have the |
| 82 | resource create and own the Namespace object. |
| 83 | |
| 84 | Changing `releaseName`, `namespace`, or `cluster` replaces the chart. |
| 85 | Alchemy applies the new render, then deletes every object from the |
| 86 | old one. |
| 87 | |
| 88 | :::caution[Objects with fixed names] |
| 89 | Some charts give objects names that don't include the release name. |
| 90 | Examples are metrics-server's `v1beta1.metrics.k8s.io` APIService, |
| 91 | CRDs, and webhook configurations. When a replacement renders those |
| 92 | same objects again, deleting the old render removes them. Choose |
| 93 | `releaseName` and `namespace` before the first deploy. If you do |
| 94 | change them, run `alchemy deploy --force` afterwards to apply the |
| 95 | missing objects again. |
| 96 | ::: |
| 97 | |
| 98 | ## CRDs |
| 99 | |
| 100 | Objects in the chart's `crds/` directory are rendered too |
| 101 | (`includeCrds` defaults to `true`). Alchemy applies Namespaces first, |
| 102 | then CRDs, then everything else, so a chart's own custom resources |
| 103 | find their definitions. Set `includeCrds: false` when the CRDs are |
| 104 | managed elsewhere. |
| 105 | |
| 106 | ## Hooks aren't run |
| 107 | |
| 108 | The chart is rendered with `--no-hooks`. Objects annotated with |
| 109 | `helm.sh/hook` are neither applied nor run. These include install |
| 110 | and upgrade Jobs and test pods. Some charts depend on hooks to work |
| 111 | correctly, for example to run database migrations or generate |
| 112 | certificates. Install those charts with Helm itself. |
| 113 | |
| 114 | ## No Helm release |
| 115 | |
| 116 | Alchemy doesn't create a Helm release. `helm list` won't show the |
| 117 | chart, and `helm upgrade` or `helm rollback` don't apply. Alchemy |
| 118 | records every object it applied and, on each update: |
| 119 | |
| 120 | - applies the new render, |
| 121 | - deletes objects that were in the previous render but not in the |
| 122 | new one, |
| 123 | - on destroy, deletes every object it applied. |
| 124 | |
| 125 | To move a chart that's currently installed with `helm install` under |
| 126 | Alchemy, run `helm uninstall` first, then deploy the `HelmChart`. |
| 127 | |
| 128 | ## Attributes |
| 129 | |
| 130 | - `releaseName` is the release name the chart rendered with. |
| 131 | - `namespace` is the namespace the chart rendered into. |
| 132 | - `chart` is the chart reference. |
| 133 | - `version` is the pinned version, if any. |
| 134 | - `objects` holds references to every applied object. |
| 135 | - `connection` is the cluster connection. |
| 136 | |
| 137 | ## Where next |
| 138 | |
| 139 | - **[Tutorial part 4](/kubernetes/tutorial/part-4).** Install |
| 140 | metrics-server on a kind cluster. |
| 141 | - **[How objects are managed](/kubernetes/workloads/object-lifecycle).** |
| 142 | Apply order, pruning, and drift. |
| 143 | - **[`HelmChart` reference](/providers/kubernetes/helmchart).** Every |
| 144 | prop and attribute. |