Helm Dependencies: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 10: Line 10:
=Overview=
=Overview=
{{Note|<center>Revised for Helm 3</center>}}
{{Note|<center>Revised for Helm 3</center>}}
All applications, maybe with the exception of the most trivial, usually depend on other runtime components, such as web servers, caches, databases, etc. Helm provides a mechanisms to formally specify, manage and deploy these dependencies as part of a [[Helm Concepts#Release|release]]. A Helm chart may declared dependencies, which are other Helm charts published in external repositories, conveniently packaged by people who presumably know the respective components well.
All applications, maybe with the exception of the most trivial, usually depend on other runtime components, such as web servers, caches, databases, etc. Helm supports modularization via a dependency mechanism, which allows to formally specify, manage and deploy dependencies as part of a [[Helm Concepts#Release|release]]. A Helm chart may declared dependencies, which are other Helm charts published in external repositories, conveniently packaged by people who presumably know the respective components well. The simples possible example is a chart A - the dependent - that declared its reliance on a chart B - the dependency - by specifying chart’s B “coordinates” (name, version and repository URL) as part of its own metadata. The exact way in which the dependencies are declared has evolved across Helm releases. For Helm 2 charts, the dependencies are declared in a dedicated requirements.yaml file, while for Helm 3 chart, the dependencies are declared as part of the chart manifest Chart.yaml. However, the way the dependencies are processed during installation has remained the same.
 
At installation time, Helm becomes aware of the direct dependencies of the chart being installed, insures that those direct dependencies are available and uses them in the installation process. In reality, the actual sequence is more complicated, involving an intermediate “chart/” subdirectory and a “helm dependency update” command, but these are operational details, not relevant at this level. It is worth noting that unlike Maven, which actively walks the transitive dependency tree, Helm does not. This behavior is mitigated by the fact a properly built chart embeds its entire dependency tree, and this is possible and practical just because the chart metadata, and the dependency trees, are small.


=How Helm Dependencies Work=
=How Helm Dependencies Work=

Revision as of 23:15, 11 March 2020

External

Internal

Overview


Revised for Helm 3


All applications, maybe with the exception of the most trivial, usually depend on other runtime components, such as web servers, caches, databases, etc. Helm supports modularization via a dependency mechanism, which allows to formally specify, manage and deploy dependencies as part of a release. A Helm chart may declared dependencies, which are other Helm charts published in external repositories, conveniently packaged by people who presumably know the respective components well. The simples possible example is a chart A - the dependent - that declared its reliance on a chart B - the dependency - by specifying chart’s B “coordinates” (name, version and repository URL) as part of its own metadata. The exact way in which the dependencies are declared has evolved across Helm releases. For Helm 2 charts, the dependencies are declared in a dedicated requirements.yaml file, while for Helm 3 chart, the dependencies are declared as part of the chart manifest Chart.yaml. However, the way the dependencies are processed during installation has remained the same.

At installation time, Helm becomes aware of the direct dependencies of the chart being installed, insures that those direct dependencies are available and uses them in the installation process. In reality, the actual sequence is more complicated, involving an intermediate “chart/” subdirectory and a “helm dependency update” command, but these are operational details, not relevant at this level. It is worth noting that unlike Maven, which actively walks the transitive dependency tree, Helm does not. This behavior is mitigated by the fact a properly built chart embeds its entire dependency tree, and this is possible and practical just because the chart metadata, and the dependency trees, are small.

How Helm Dependencies Work

During the installation or upgrade process, the Helm client looks into the ./charts sub-directory of the chart being installed, and installs/upgrades the charts whose chart archives are found in that subdirectory. The content of the charts/ subdirectory is the one and only source of truth on dependencies to be installed or upgraded. If a dependency chart is not present in the charts/ subdirectory at the time of installation/upgrade, it is not installed/upgraded. All charts present in the charts/ subdirectory at the time of installation/upgraded are installed/upgraded.

The "dependencies" element of Chart.yaml is a convenience feature that allows specifying the dependency list in a synthetic manner, by "coordinates": name, version and repository URL. However, listing the dependency coordinates in Chart.yaml is not sufficient, additional manual steps need to be performed: helm dependency update, which is a step that downloads dependencies in charts/ based on their Chart.yaml "dependencies" specifications.


This charts/ content management functionality (helm dependency) must be explicitly invoked and it is NOT automatically triggered during the installation or update process. However, some sanity checks are performed by helm install, which fails if dependencies are declared in Chart.yaml but not present in charts/.

When Helm installs or updates a chart that has dependencies, it will aggregate all Kubernetes objects declared by the chart and dependencies in a single set. sort the object by types, then by name, and create/update in that order. Also see Installation and De-Installation Order. If a dependency is present in the charts/ subdirectory but not in the "dependencies" list from Chart.yaml, it will be considered a manually-managed dependency and it will be installed.

Helm does not automatically handle transitive dependencies, in the same manner as Maven, for example, does: it is not possible to specify that chart "a" depends on chart "b", only specify the chart "b" "coordinates" (name, version and repository URL) and expect Helm to automatically pull "b" during the installation process. In this situation. Maven would contact the dependency's repository and pull the artifact. If that artifact had its own dependencies, specified by coordinates, Maven would recursively pull those as well, contacting as many repositories as necessary. This is known as what Maven friends refer to as "downloading the Internet".

Helm behaves differently. It expects instead a chart to embed all dependencies it needs, recursively. This decision was probably taken because the chart metadata is really small, especially when compressed. and the chart transitive dependency graphs are not large, so embedding the whole graph in an archive is feasible, which would not be in Maven's case. Indeed, for a situation where an "a" chart depends on a "b" chart, and the "b" chart depends on a "c" chart, the structure of the "a"'s chart archive is;

a
├── Chart.yaml
├── charts
│   └── b
│       ├── Chart.yaml
│       ├── charts
│       │   └── c
│       │       ├── Chart.yaml
│       │       ├── templates
│       │       │   └── pod.yaml
│       │       └── values.yaml
│       ├── templates
│       │   └── pod.yaml
│       └── values.yaml
├── templates
│   └── pod.yaml
└── values.yaml

The enforcement of presence of dependencies happens when the chart is packaged with helm package command. If a chart is packaged manually, and its dependencies are omitted while building the chart archive, the chart archive cannot be installed. An attempt to install a chart archive that does not embed dependencies produces:

Error: found in Chart.yaml, but missing in charts/ directory: some-dependency-chart

For more details on how to package a chart with its dependencies, see:

Packaging and Dependencies

Subcharts

The charts stored in the "charts/" subdirectory are also known as "subcharts".

Dependency Declaration

Dependencies are declared in Chart.yaml 'dependencies' section.

...
dependencies:
  - name: # The name of the dependency
    version: # The version of the dependency
    repository: # Repository URL
    condition: # See Dependency Selective Installation below
    tags: # See Dependency Selective Installation below
     - tag1
     - tag2
...

Example:

...
# 'a' Chart.yaml
dependencies:
  - name: b
    version: 1.0.0
    repository: http://helm-example.com/charts
    condition: b.enabled, global.b.enabled
    tags:
      - front-end
      - b

...

Note that simply declaring the dependency in Chart.yaml is not sufficient. The dependency needs to be physically downloaded and placed in the charts/ subdirectory with:

helm dependency update

Elements

name

version

repository

This specifies the URL of the Helm repository to pull the chart from. The repository does not have configured locally to publish the chart.

aliases

Each element of the "dependencies" list allows for an optional "alias" attribute.

Packaging and Dependencies

Packaging and Dependencies

Dependencies and Values

Dependency configuration values should be specified in the top chart values.yaml, and should be prefixed with the dependency name. It is recommended to only override values in the top level chart, and not in any subchart.

TODO:

  • Example

Relative Repository URLs

A chart may declare one or more of its dependencies using a relative URL, for the case where both the dependent chart and the dependency chart are unpacked and live on the same filesystem. This is often the case when two or more interdependent charts are developed and maintained in the same GitHub repository. The syntax in that case is:

dependencies:
  - name: b
    version: 1.0.0
    repository: file://../b

Relative Repository URL and version Field

Note that even if it seems unnecessary, as an unpacked chart can have just one and only one version, the "version" information in the dependent's chart is actually required, and it is matched against ../b/Chart.yaml.

If the dependency declaration does not contain version, helm dependency update fails with:

helm dependency update ./a
[...]
Saving 1 charts
Save error occurred:  dependency b has an invalid version/constraint format: improper constraint:
Deleting newly downloaded charts, restoring pre-update state
Error: dependency b has an invalid version/constraint format: improper constraint:

If the dependency declaration contains a version declaration that does not match the version advertised by ../b/Chart.yaml, helm dependency update fails with:

helm dependency update ./a
[...]
Saving 1 charts
Save error occurred:  can't get a valid version for dependency b
Deleting newly downloaded charts, restoring pre-update state
Error: can't get a valid version for dependency b

Dependency Selective Installation

https://helm.sh/docs/topics/charts/#tags-and-condition-fields-in-dependencies

All dependencies present in charts/ are installed by default. However, tags and conditions can be used to perform selective installation.

Conditions are YAML paths specified in values.yaml that can be declared to be 'true' or 'false'.

Tags are list of labels associated with a specific dependency. The tags can be enabled or disabled in values.yaml by specifying the tag and a boolean value. Also, the helm install --set parameter can be used to alter tag and condition values at installation time.

Conditions or tags should be added to any dependencies that are optional.

Dependency Operations