Serving OCI Helm Charts in Helm Chart Repositories
Posted: June 3rd, 2024 | Author: sabre1041 | Filed under: Technology | Tags: Charts, helm, oci | No Comments »The introduction of OCI registries as a medium for storing Helm charts brought a number of advantages as compared to traditional Helm repositories including the ability to leverage the same infrastructure and primitives as standard containers along with reducing the overall effort that it takes to serve Helm charts for others to consume. However, even as the adoption of OCI based Helm charts continues to increase, there are several limitations compared to their traditional Helm Chart repository counterparts. Examples of these limitations include the inability to organize multiple charts amongst each other or the ability to search for charts that are stored within OCI registries.
A recent discussion within the Helm project GitHub repository brought to light a new method for which OCI based Helm charts could be managed. Charts stored in Helm repositories make use of an Index file which defines not only the charts that are being served, but the remote source where they are located.
The following is an example of a Helm index file:
apiVersion: v1 entries: oci-artifacts-demo: - apiVersion: v2 appVersion: 1.16.0 created: "2024-05-31T11:50:24.431916-05:00" description: Sample Helm Chart digest: db5c00dcae815f35b4d0d18d507aeae98f648e849ec1786a0573111210e5f337 name: my-chart type: application urls: - https://example.com/charts/my-chart-0.1.1.tgz version: 0.1.1 - apiVersion: v2 appVersion: 1.16.0 created: "2024-05-31T11:50:24.431418-05:00" description: Sample Helm Chart digest: a59db5293c542bdbe5f3e85aff3f357d1d0501ae308f51407541644baf8bd32a name: my-chart type: application urls: - https://example.com/charts/my-chart-0.1.0.tgz version: 0.1.0 generated: "2024-05-31T11:50:24.43089-05:00"
As illustrated by the index file above, the urls field specifies the location of the packaged chart. While the majority of Helm chart repositories serve packaged charts alongside the index file, this is not a hard requirement and a packaged chart could be served by any accessible location.
Under the covers, Helm utilizes an interface (Getter) for accessing charts stored in remote locations. As one can expect, there are two implementations of the interface: accessing charts stored in Helm charts repositories as well as OCI registries. The determination of which method to use is determined by the protocol specified within the URL. URL’s specifying the http
or https
scheme access charts from traditional Helm repositories, while those with the oci
scheme access charts from OCI registries.
The mechanisms for which Helm retrieves remote chart content based on the specified protocol enables using a Helm index in new ways. Instead referencing the location of the packaged chart stored within an HTTP server, the chart could instead be stored in an OCI registry. All that needs to change is the location of the chart specified in the urls field. This reference needs to include the oci://
protocol so that the underlying functionality for retrieving OCI based charts is activated. Let’s see how we can accomplish this capability.
Enabling OCI Charts in Chart Repositories
First, create a new Helm chart called my-chart
:
helm create my-chart
Package up the chart
helm package my-chart
We will create a second version of the chart so that the chart index we will build includes multiple versions. To increment the chart version, use the yq utility which enables modifying YAML based content. If yq
is not currently installed on your machine, navigate to the project website and follow the steps to download and install in your machine.
Once yq
has been installed, update the version of the my-chart
Helm chart to version 0.1.1:
yq -i '.version = "0.1.1"' my-chart/Chart.yaml
Package the updated chart
helm package my-chart
At this point, there are two packaged charts in the current directory (versions 0.0.1
and 0.1.1
). Before publishing these charts to an OCI registry, set an environment variable called HELM_REGISTRY_REFERENCE
representing the reference of the remote registry where the charts will be stored (for example: myregistry.com/charts
).
export HELM_REGISTRY_REFERENCE=myregistry.com/charts
Now, push both charts to the remote registry
helm push my-chart-0.1.0.tgz oci://${HELM_REGISTRY_REFERENCE} helm push my-chart-0.1.1.tgz oci://${HELM_REGISTRY_REFERENCE}
Next, generate a Helm index file based on charts stored within the current directory
helm repo index .
With the index file generated, use yq
to dynamically update the URL within the index file to reference the location of the chart in the OCI registry instead of the default path generated by Helm.
yq eval -i '. |= .entries[][] |= .urls[0] = "oci://" + env(HELM_REGISTRY_REFERENCE) + "/" + .name + ":" + .version' index.yaml
View the contents of the index file and you will notice that each chart version utilizes an OCI based reference in the urls field, enabling the use of the charts stored in the OCI registry.
apiVersion: v1 entries: my-chart: - apiVersion: v2 appVersion: 1.16.0 created: "2024-06-01T12:31:02.734732-05:00" description: A Helm chart for Kubernetes digest: a7f05a380cc6ed45feab837b65b1f0a51f8737236105d7325b1b13953d7abb96 name: my-chart type: application urls: - oci://${HELM_REGISTRY_REFERENCE}/charts/my-chart:0.1.1 version: 0.1.1 - apiVersion: v2 appVersion: 1.16.0 created: "2024-06-01T12:31:02.734383-05:00" description: A Helm chart for Kubernetes digest: bbee6c6f09d1535bafdd4cb5c0c7344ed6812a0b23650e2afd005cb80450a89a name: my-chart type: application urls: - oci://${HELM_REGISTRY_REFERENCE}/charts/my-chart:0.1.0 version: 0.1.0 generated: "2024-06-01T12:31:02.733967-05:00"
NOTE: ${HELM_REGISTRY_REFERENCE}
in the example above will be rendered in your version
The index file can then be uploaded to an HTTP based web server for broader distribution and use by others. There are a number of options for which the index file can be hosted, including GitHub Pages. Otherwise, since the file only needs to be served briefly, we can use python to start a minimalistic web server locally.
Execute the following command to start the web server on port 8000 using the contents from the current directory.
python -m http.server
Confirm the index file is being served properly
curl http://localhost:8000/index.yaml
Now that the chart repository has been configured and confirmed to be accessible, add a new repository called repo-oci
and update the contents.
helm repo add repo-oci http://localhost:8000 helm repo update repo-oci
Verifying the Approach
With all of the steps now complete for leveraging OCI based charts within chart repositories including adding the associated repository to the local machine, you can begin to use it it similar to any other helm repository, including searching for all charts and versions available
helm search repo repo-oci/ --versions NAME CHART VERSION APP VERSION DESCRIPTION repo-oci/my-chart 0.1.1 1.16.0 A Helm chart for Kubernetes repo-oci/my-chart 0.1.0 1.16.0 A Helm chart for Kubernetes
Confirm that typical operations for for interacting with a chart can still be achieved, such as inspecting the contents of the Chart.yaml
file using the helm show chart
command:
helm show chart repo-oci/my-chart apiVersion: v2 appVersion: 1.16.0 description: A Helm chart for Kubernetes name: my-chart type: application version: 0.1.1
You can even choose to install one of these charts to a Kubernetes cluster using the helm install
or helm upgrade
commands. However, since
Capabilities surrounding the use of OCI artifacts continue to evolve both within the Helm project and in the OCI community. However, until new features become more readily available which offers an improved experience working with OCI based content, the ability to combine the use of Helm repositories and registries provides a suitable middleground in the meantime.
Recent Comments