https://github.com/mgoltzsche/khelm
A Helm chart templating CLI, kustomize plugin and containerized kustomize/kpt KRM function
https://github.com/mgoltzsche/khelm
declarative-workflows helm helm-chart helm-charts helm-charts-as-code k8s kpt kubernetes kustomize kustomize-plugin
Last synced: about 2 months ago
JSON representation
A Helm chart templating CLI, kustomize plugin and containerized kustomize/kpt KRM function
- Host: GitHub
- URL: https://github.com/mgoltzsche/khelm
- Owner: mgoltzsche
- License: apache-2.0
- Created: 2019-07-29T23:15:37.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2025-03-18T21:20:23.000Z (3 months ago)
- Last Synced: 2025-03-28T12:07:36.157Z (2 months ago)
- Topics: declarative-workflows, helm, helm-chart, helm-charts, helm-charts-as-code, k8s, kpt, kubernetes, kustomize, kustomize-plugin
- Language: Go
- Homepage:
- Size: 4.7 MB
- Stars: 122
- Watchers: 4
- Forks: 11
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# khelm  [](https://goreportcard.com/report/github.com/mgoltzsche/khelm)
A [Helm](https://github.com/helm/helm) chart templating CLI, helm to kustomize converter, [kpt](https://github.com/GoogleContainerTools/kpt) function and [kustomize](https://github.com/kubernetes-sigs/kustomize/) plugin.
Formerly known as "helm-kustomize-plugin".
## Motivation / History
[Helm](https://github.com/helm/helm) _charts_ provide a great way to share and reuse [Kubernetes](https://github.com/kubernetes/kubernetes) applications and there is a lot of them.
However writing helm templates is cumbersome and you cannot reuse a chart properly if it does not yet support a particular parameter/value.[Kustomize](https://github.com/kubernetes-sigs/kustomize/) solves these issues declaratively by merging Kubernetes API objects which grants users of a _kustomization_ the freedom to change anything.
However kustomize neither supports lifecycle management nor templating with externally passed in values (which is sometimes still required).To overcome the gap between helm and kustomize initially this repository provided a kustomize plugin and [k8spkg](https://github.com/mgoltzsche/k8spkg) was used for lifecycle management.
Since [kpt](https://github.com/GoogleContainerTools/kpt) is [published](https://opensource.googleblog.com/2020/03/kpt-packaging-up-your-kubernetes.html) helm and kustomize can be run as (chained) kpt functions supporting declarative, GitOps-based workflows. kpt also supports dynamic modification of static (rendered) manifests with externally passed in values using [setters](https://googlecontainertools.github.io/kpt/guides/consumer/set/) as well as [dependency](https://googlecontainertools.github.io/kpt/reference/pkg/) and [lifecycle management](https://googlecontainertools.github.io/kpt/reference/live/).## Features
* Templates/renders a Helm chart
* Builds local charts automatically when templating
* Automatically fetches and updates required repository index files when needed
* Allows to automatically reload dependencies when lock file is out of sync
* Allows to use any repository without registering it in repositories.yaml
* Allows to exclude certain resources from the Helm chart output
* Allows to enforce namespace-scoped resources within the template output
* Allows to enforce a namespace on all resources
* Allows to convert a chart's output into a kustomization## Supported interfaces
khelm can be used as:
* [kpt function](#kpt-function)
* [kustomize exec plugin](#kustomize-exec-plugin)
* [kustomize Containerized KRM Function](#kustomize-containerized-krm-function)
* [CLI](#cli)
* [Go API](#go-api)Usage examples can be found in the [example](example) and [e2e](e2e) directories.
### kpt function
khelm can be used as a containerized KRM function with [kpt](https://github.com/GoogleContainerTools/kpt).
The khelm function templates a chart and returns the output as single manifest file or kustomization directory (when `outputPath` ends with `/`) that kpt writes to disk.In opposite to the kustomize plugin approach, kpt function outputs can be audited reliably when committed to a git repository, a kpt function does not depend on particular plugin binaries on the host and CD pipelines can run without dependencies to rendering technologies and chart servers since they just apply static manifests to a cluster (e.g. using `kpt live apply`).
#### kpt function usage example
When using the khelm image directly with [kpt](https://github.com/GoogleContainerTools/kpt), it must be invoked as an [imperative function](https://kpt.dev/book/04-using-functions/02-imperative-function-execution) since it requires a chart to be mounted or network access to fetch a chart.
This is shown as follows:
```sh
cat - > fn-config.yaml <<-EOF
apiVersion: khelm.mgoltzsche.github.com/v2
kind: ChartRenderer
metadata:
name: cert-manager-manifest-generator-config
repository: https://charts.jetstack.io
chart: cert-manager
version: 0.9.x
name: myrelease
namespace: cert-manager
values:
webhook:
enabled: false
outputPath: output-manifest.yaml
EOF
kpt fn eval --image mgoltzsche/khelm:latest --fn-config fn-config.yaml --network .
```
_For all available fields see the [table](#configuration-options) below._To use a local chart or values file, the source must be mounted to the function container using e.g. `kpt fn eval --mount="type=bind,src=$(pwd),dst=/source,rw=true" --image mgoltzsche/khelm --fn-config fn-config.yaml .`.
The [kpt examples](example/kpt) and corresponding [e2e tests](e2e/kpt-function-test.sh) show how to do that.To use khelm as a [declarative function](https://kpt.dev/book/04-using-functions/01-declarative-function-execution), you could distribute a container image that includes both khelm and your chart as shown in the [declarative example](example/kpt/declarative).
kpt can also be leveraged to sync charts from other git repositories into your own repository using the `kpt pkg get` and `kpt pkg update` [commands](https://kpt.dev/reference/cli/pkg/) (with a corresponding dependency set up) before running the khelm function.
#### Caching Helm Charts and repository index files
When external Helm Charts are used the download of their repositories' index files and of the charts itself can take a significant amount of time that adds up when running multiple functions or calling a function frequently during development.
To speed this up caching can be enabled by mounting a host directory into the container at `/helm`, e.g. `kpt fn run --mount "type=bind,src=$HOME/.khelm,dst=/helm,rw=true" .`.
_Please be aware that the presence of `/helm/repository/repositories.yaml` enables a strict repository policy by default (see [repository configuration](#repository-configuration))._
_Therefore, to be independent of existing Helm 2 installations, a host's `~/.helm` directory should not be mounted to `/helm` in most cases but the `~/.helm/cache` subdirectory into `/helm/cache`._### kustomize exec plugin
khelm can be used as [kustomize](https://github.com/kubernetes-sigs/kustomize) [exec plugin](https://kubectl.docs.kubernetes.io/guides/extending_kustomize/exec_plugins/).
Though plugin support in kustomize is still an alpha feature and may be slated to be deprecated in a future version (see [KEP 2953](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2953-kustomize-plugin-graduation)).#### Plugin installation
Install using curl (on OSX or Linux):
```sh
OS=$(uname | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')
mkdir -p $HOME/.config/kustomize/plugin/khelm.mgoltzsche.github.com/v2/chartrenderer
curl -fsSL https://github.com/mgoltzsche/khelm/releases/latest/download/khelm-${OS}-${ARCH} > $HOME/.config/kustomize/plugin/khelm.mgoltzsche.github.com/v2/chartrenderer/ChartRenderer
chmod +x $HOME/.config/kustomize/plugin/khelm.mgoltzsche.github.com/v2/chartrenderer/ChartRenderer
```
or using `go`:
```sh
go get github.com/mgoltzsche/khelm/v2/cmd/khelm
mkdir -p $HOME/.config/kustomize/plugin/khelm.mgoltzsche.github.com/v2/chartrenderer
mv $GOPATH/bin/khelm $HOME/.config/kustomize/plugin/khelm.mgoltzsche.github.com/v2/chartrenderer/ChartRenderer
```#### Plugin usage example
A _plugin descriptor_ specifies the helm repository, chart, version and values that should be used in a kubernetes-style resource can be referenced in the `generators` section of a `kustomization.yaml` and can look as follows:
```yaml
apiVersion: khelm.mgoltzsche.github.com/v2
kind: ChartRenderer
metadata:
name: cert-manager # fallback for `name`
namespace: cert-manager # fallback for `namespace`
repository: https://charts.jetstack.io
chart: cert-manager
version: 0.9.x
values:
webhook:
enabled: false
```
_For all available fields see the [table](#configuration-options) below._More complete examples can be found within the [example](example) directory.
For instance `cert-manager` can be rendered like this:
```sh
kustomize build --enable-alpha-plugins github.com/mgoltzsche/khelm/example/cert-manager
```
_When using kustomize 3 the option is called `--enable_alpha_plugins`._### kustomize Containerized KRM Function
Similar to the kpt function approach, khelm can be used as [Containerized KRM Function](https://kubectl.docs.kubernetes.io/guides/extending_kustomize/containerized_krm_functions/) [kustomize](https://github.com/kubernetes-sigs/kustomize) plugin.
Though plugin support in kustomize is still an alpha feature, this form of extension seems destined to be graduated out of alpha (see [KEP 2953](https://github.com/kubernetes/enhancements/tree/master/keps/sig-cli/2953-kustomize-plugin-graduation)).This approach only works with kustomize>=v4.1.0.
Unlike the [exec plugin strategy](#kustomize-exec-plugin), this method does not require installation.
#### kustomize containerized KRM function usage example
A _plugin descriptor_ specifies the helm repository, chart, version and values that should be used in a kubernetes-style resource can be referenced in the `generators` section of a `kustomization.yaml` and can look as follows:
```yaml
apiVersion: khelm.mgoltzsche.github.com/v2
kind: ChartRenderer
metadata:
name: cert-manager
namespace: cert-manager
annotations:
config.kubernetes.io/function: |
container:
image: mgoltzsche/khelm:latest
network: true
repository: https://charts.jetstack.io
chart: cert-manager
name: my-cert-manager-release
namespace: cert-manager
version: 0.9.x
values:
webhook:
enabled: false
```_For all available fields see the [table](#configuration-options) below._
More complete examples can be found within the [`example/kustomize-krm`](example/kustomize-krm/) directory.
For instance `cert-manager` can be rendered like this:
```sh
kustomize build --enable-alpha-plugins --network github.com/mgoltzsche/khelm/example/kustomize-krm/cert-manager
```### CLI
khelm also supports a helm-like `template` CLI.
#### Binary installation
```sh
OS=$(uname | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/')
curl -fsSL https://github.com/mgoltzsche/khelm/releases/latest/download/khelm-${OS}-${ARCH} > khelm
chmod +x khelm
sudo mv khelm /usr/local/bin/khelm
```#### Binary usage example
```sh
khelm template cert-manager --version=0.9.x --repo=https://charts.jetstack.io
```
_For all available options see the [table](#configuration-options) below._#### Docker usage example
```sh
docker run mgoltzsche/khelm:latest template cert-manager --version=0.9.x --repo=https://charts.jetstack.io
```### Go API
The khelm Go API `github.com/mgoltzsche/khelm/v2/pkg/helm` provides a simple templating interface on top of the Helm Go API.
It exposes a `Helm` struct that provides a `Render()` function that returns the rendered resources as `kyaml` objects.## Configuration options
| Field | CLI | Description |
| ----- | ---------- | ----------- |
| `chart` | ARGUMENT | Chart file (if `repository` not set) or name. |
| `version` | `--version` | Chart version. Latest version is used if not specified. |
| `repository` | `--repo` | URL to the repository the chart should be loaded from. |
| `valueFiles` | `-f` | Locations of values files.
| `values` | `--set` | Set values object or in CLI `key1=val1,key2=val2`. |
| `apiVersions` | `--api-versions` | Kubernetes api versions used for Capabilities.APIVersions. |
| `kubeVersion` | `--kube-version` | Kubernetes version used for Capabilities.KubeVersion. |
| `name` | `--name` | Release name used to render the chart. |
| `verify` | `--verify` | If enabled verifies the signature of all charts using the `keyring` (see [Helm 3 provenance and integrity](https://helm.sh/docs/topics/provenance/)). |
| `keyring` | `--keyring` | GnuPG keyring file (default `~/.gnupg/pubring.gpg`). |
| `replaceLockFile` | `--replace-lock-file` | Remove requirements.lock and reload charts when it is out of sync. |
| `include` | | List of resource selectors that include matching resources from the output. If no selector specified all resources are included. Fails if a selector doesn't match any resource. Inclusions precede exclusions. |
| `include[].apiVersion` | | Includes resources by apiVersion. |
| `include[].kind` | | Includes resources by kind. |
| `include[].namespace` | | Includes resources by namespace. |
| `include[].name` | | Includes resources by name. |
| `exclude` | | List of resource selectors that exclude matching resources from the output. Fails if a selector doesn't match any resource. |
| `exclude[].apiVersion` | | Excludes resources by apiVersion. |
| `exclude[].kind` | | Excludes resources by kind. |
| `exclude[].namespace` | | Excludes resources by namespace. |
| `exclude[].name` | | Excludes resources by name. |
| `excludeCRDs` | `--skip-crds` | If true Custom Resource Definitions are excluded from the output. |
| `excludeHooks` | `--no-hooks` | If enabled excludes chart hooks from the output. |
| `namespace` | `--namespace` | Set the namespace used by Helm templates. |
| `namespacedOnly` | `--namespaced-only` | If enabled fail on known cluster-scoped resources and those of unknown kinds. |
| `forceNamespace` | `--force-namespace` | Set namespace on all namespaced resources (and those of unknown kinds). |
| `outputPath` | `--output` | Path to write the output to. If it ends with `/` a kustomization is generated. (Not supported by the kustomize plugin.) |
| `outputPathMapping[].outputPath` | | output path to which all resources should be written that match `resourceSelectors`. (Only supported by the kpt function.) |
| `outputPathMapping[].selectors[].apiVersion` | | Selects resources by apiVersion. |
| `outputPathMapping[].selectors[].kind` | | Selects resources by kind. |
| `outputPathMapping[].selectors[].namespace` | | Selects resources by namespace. |
| `outputPathMapping[].selectors[].name` | | Selects resources by name. |
| | `--output-replace` | If enabled replace the output directory or file (CLI-only). |
| | `--trust-any-repo` | If enabled repositories that are not registered within `repositories.yaml` can be used as well (env var `KHELM_TRUST_ANY_REPO`). Within the kpt function this behaviour can be disabled by mounting `/helm/repository/repositories.yaml` or disabling network access. |
| `debug` | `--debug` | Enables debug log and provides a stack trace on error. |### Repository configuration
Repository credentials can be configured using Helm's `repositories.yaml` which can be passed through as `Secret` to generic build jobs. khelm downloads the corresponding repo index files when needed.
When running khelm as kpt function or within a container the `repositories.yaml` should be mounted to `/helm/repository/repositories.yaml`.
Unlike Helm khelm allows usage of any repository when `repositories.yaml` is not present or `--trust-any-repo` (env var `KHELM_TRUST_ANY_REPO`) is enabled.
### Loading a chart from an OCI registry
Using Helm, you can store a Helm chart as OCI image within a container registry.
To load a chart from an OCI registry using khelm, you can specify the OCI registry within the `repository` field, prefixed with `oci://`.
The complete OCI image name is constructed from the `repository` and the `chart` field values, separated by `/`.
For an example, see [here](./example/oci-image/generator.yaml) and [here](./example/oci-dependency/Chart.yaml).When using a chart from an OCI registry, Helm's `repository.yaml` configuration is not used.
Instead, Docker's `config.json` is used to read private registry credentials from, if any.## Helm support
* Helm 2 is supported by the `v1` module version.
* Helm 3 is supported by the `v2` module version.## Build and test
Build and test the khelm binary (requires Go 1.13) as well as the container image:
```sh
make clean khelm test check image e2e-test
```
_The binary is written to `build/bin/khelm`_.Install the binary on your host at `/usr/local/bin/khelm`:
```sh
sudo make install
```