Charts

Helm uses a packaging format called charts. A chart is a collection of filesthat describe a related set of Kubernetes resources. A single chartmight be used to deploy something simple, like a memcached pod, orsomething complex, like a full web app stack with HTTP servers,databases, caches, and so on.

Charts are created as files laid out in a particular directory tree,then they can be packaged into versioned archives to be deployed.

This document explains the chart format, and provides basic guidance forbuilding charts with Helm.

The Chart File Structure

A chart is organized as a collection of files inside of a directory. Thedirectory name is the name of the chart (without versioning information). Thus,a chart describing WordPress would be stored in the wordpress/ directory.

Inside of this directory, Helm will expect a structure that matches this:

  1. wordpress/
  2. Chart.yaml # A YAML file containing information about the chart
  3. LICENSE # OPTIONAL: A plain text file containing the license for the chart
  4. README.md # OPTIONAL: A human-readable README file
  5. requirements.yaml # OPTIONAL: A YAML file listing dependencies for the chart
  6. values.yaml # The default configuration values for this chart
  7. charts/ # A directory containing any charts upon which this chart depends.
  8. templates/ # A directory of templates that, when combined with values,
  9. # will generate valid Kubernetes manifest files.
  10. templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes

Helm reserves use of the charts/ and templates/ directories, and ofthe listed file names. Other files will be left as they are.

The Chart.yaml File

The Chart.yaml file is required for a chart. It contains the following fields:

  1. apiVersion: The chart API version, always "v1" (required)
  2. name: The name of the chart (required)
  3. version: A SemVer 2 version (required)
  4. kubeVersion: A SemVer range of compatible Kubernetes versions (optional)
  5. description: A single-sentence description of this project (optional)
  6. keywords:
  7. - A list of keywords about this project (optional)
  8. home: The URL of this project's home page (optional)
  9. sources:
  10. - A list of URLs to source code for this project (optional)
  11. maintainers: # (optional)
  12. - name: The maintainer's name (required for each maintainer)
  13. email: The maintainer's email (optional for each maintainer)
  14. url: A URL for the maintainer (optional for each maintainer)
  15. engine: gotpl # The name of the template engine (optional, defaults to gotpl)
  16. icon: A URL to an SVG or PNG image to be used as an icon (optional).
  17. appVersion: The version of the app that this contains (optional). This needn't be SemVer.
  18. deprecated: Whether this chart is deprecated (optional, boolean)
  19. tillerVersion: The version of Tiller that this chart requires. This should be expressed as a SemVer range: ">2.0.0" (optional)

If you are familiar with the Chart.yaml file format for Helm Classic, you willnotice that fields specifying dependencies have been removed. That is becausethe new Chart format expresses dependencies using the charts/ directory.

Other fields will be silently ignored.

Charts and Versioning

Every chart must have a version number. A version must follow theSemVer 2 standard. Unlike Helm Classic, KubernetesHelm uses version numbers as release markers. Packages in repositoriesare identified by name plus version.

For example, an nginx chart whose version field is set to version: 1.2.3 will be named:

  1. nginx-1.2.3.tgz

More complex SemVer 2 names are also supported, such asversion: 1.2.3-alpha.1+ef365. But non-SemVer names are explicitlydisallowed by the system.

NOTE: Whereas Helm Classic and Deployment Manager were bothvery GitHub oriented when it came to charts, Kubernetes Helm does notrely upon or require GitHub or even Git. Consequently, it does not useGit SHAs for versioning at all.

The version field inside of the Chart.yaml is used by many of theHelm tools, including the CLI and the Tiller server. When generating apackage, the helm package command will use the version that it findsin the Chart.yaml as a token in the package name. The system assumesthat the version number in the chart package name matches the version number inthe Chart.yaml. Failure to meet this assumption will cause an error.

The appVersion field

Note that the appVersion field is not related to the version field. It isa way of specifying the version of the application. For example, the drupalchart may have an appVersion: 8.2.1, indicating that the version of Drupalincluded in the chart (by default) is 8.2.1. This field is informational, andhas no impact on chart version calculations.

Deprecating Charts

When managing charts in a Chart Repository, it is sometimes necessary todeprecate a chart. The optional deprecated field in Chart.yaml can be usedto mark a chart as deprecated. If the latest version of a chart in therepository is marked as deprecated, then the chart as a whole is considered tobe deprecated. The chart name can later be reused by publishing a newer versionthat is not marked as deprecated. The workflow for deprecating charts, asfollowed by the helm/chartsproject is:

  • Update chart's Chart.yaml to mark the chart as deprecated, bumping the version
  • Release the new chart version in the Chart Repository
  • Remove the chart from the source repository (e.g. git)

Chart LICENSE, README and NOTES

Charts can also contain files that describe the installation, configuration, usage and license of achart.

A LICENSE is a plain text file containing the licensefor the chart. The chart can contain a license as it may have programming logic in the templates andwould therefore not be configuration only. There can also be separate license(s) for the applicationinstalled by the chart, if required.

A README for a chart should be formatted in Markdown (README.md), and should generallycontain:

  • A description of the application or service the chart provides
  • Any prerequisites or requirements to run the chart
  • Descriptions of options in values.yaml and default values
  • Any other information that may be relevant to the installation or configuration of the chartThe chart can also contain a short plain text templates/NOTES.txt file that will be printed outafter installation, and when viewing the status of a release. This file is evaluated as atemplate, and can be used to display usage notes, next steps, or any otherinformation relevant to a release of the chart. For example, instructions could be provided forconnecting to a database, or accessing a web UI. Since this file is printed to STDOUT when runninghelm install or helm status, it is recommended to keep the content brief and point to the READMEfor greater detail.

Chart Dependencies

In Helm, one chart may depend on any number of other charts.These dependencies can be dynamically linked through the requirements.yamlfile or brought in to the charts/ directory and managed manually.

Although manually managing your dependencies has a few advantages some teams need,the preferred method of declaring dependencies is by using arequirements.yaml file inside of your chart.

Note: The dependencies: section of the Chart.yaml from HelmClassic has been completely removed.

Managing Dependencies with requirements.yaml

A requirements.yaml file is a simple file for listing yourdependencies.

  1. dependencies:
  2. - name: apache
  3. version: 1.2.3
  4. repository: http://example.com/charts
  5. - name: mysql
  6. version: 3.2.1
  7. repository: http://another.example.com/charts
  • The name field is the name of the chart you want.
  • The version field is the version of the chart you want.
  • The repository field is the full URL to the chart repository. Notethat you must also use helm repo add to add that repo locally.Once you have a dependencies file, you can run helm dependency updateand it will use your dependency file to download all the specifiedcharts into your charts/ directory for you.
  1. $ helm dep up foochart
  2. Hang tight while we grab the latest from your chart repositories...
  3. ...Successfully got an update from the "local" chart repository
  4. ...Successfully got an update from the "stable" chart repository
  5. ...Successfully got an update from the "example" chart repository
  6. ...Successfully got an update from the "another" chart repository
  7. Update Complete.
  8. Saving 2 charts
  9. Downloading apache from repo http://example.com/charts
  10. Downloading mysql from repo http://another.example.com/charts

When helm dependency update retrieves charts, it will store them aschart archives in the charts/ directory. So for the example above, onewould expect to see the following files in the charts directory:

  1. charts/
  2. apache-1.2.3.tgz
  3. mysql-3.2.1.tgz

Managing charts with requirements.yaml is a good way to easily keepcharts updated, and also share requirements information throughout ateam.

Alias field in requirements.yaml

In addition to the other fields above, each requirements entry may containthe optional field alias.

Adding an alias for a dependency chart would puta chart in dependencies using alias as name of new dependency.

One can use alias in cases where they need to access a chartwith other name(s).

  1. # parentchart/requirements.yaml
  2. dependencies:
  3. - name: subchart
  4. repository: http://localhost:10191
  5. version: 0.1.0
  6. alias: new-subchart-1
  7. - name: subchart
  8. repository: http://localhost:10191
  9. version: 0.1.0
  10. alias: new-subchart-2
  11. - name: subchart
  12. repository: http://localhost:10191
  13. version: 0.1.0

In the above example we will get 3 dependencies in all for parentchart

  1. subchart
  2. new-subchart-1
  3. new-subchart-2

The manual way of achieving this is by copy/pasting the same chart in thecharts/ directory multiple times with different names.

Tags and Condition fields in requirements.yaml

In addition to the other fields above, each requirements entry may containthe optional fields tags and condition.

All charts are loaded by default. If tags or condition fields are present,they will be evaluated and used to control loading for the chart(s) they are applied to.

Condition - The condition field holds one or more YAML paths (delimited by commas).If this path exists in the top parent's values and resolves to a boolean value,the chart will be enabled or disabled based on that boolean value. Only the firstvalid path found in the list is evaluated and if no paths exist then the condition has no effect.

Tags - The tags field is a YAML list of labels to associate with this chart.In the top parent's values, all charts with tags can be enabled or disabled byspecifying the tag and a boolean value.

  1. # parentchart/requirements.yaml
  2. dependencies:
  3. - name: subchart1
  4. repository: http://localhost:10191
  5. version: 0.1.0
  6. condition: subchart1.enabled,global.subchart1.enabled
  7. tags:
  8. - front-end
  9. - subchart1
  10.  
  11. - name: subchart2
  12. repository: http://localhost:10191
  13. version: 0.1.0
  14. condition: subchart2.enabled,global.subchart2.enabled
  15. tags:
  16. - back-end
  17. - subchart2
  1. # parentchart/values.yaml
  2.  
  3. subchart1:
  4. enabled: true
  5. tags:
  6. front-end: false
  7. back-end: true

In the above example all charts with the tag front-end would be disabled but since thesubchart1.enabled path evaluates to 'true' in the parent's values, the condition will override thefront-end tag and subchart1 will be enabled.

Since subchart2 is tagged with back-end and that tag evaluates to true, subchart2 will beenabled. Also note that although subchart2 has a condition specified in requirements.yaml, thereis no corresponding path and value in the parent's values so that condition has no effect.

Using the CLI with Tags and Conditions

The —set parameter can be used as usual to alter tag and condition values.

  1. helm install --set tags.front-end=true --set subchart2.enabled=false
Tags and Condition Resolution
  • Conditions (when set in values) always override tags.
  • The first condition path that exists wins and subsequent ones for that chart are ignored.
  • Tags are evaluated as 'if any of the chart's tags are true then enable the chart'.
  • Tags and conditions values must be set in the top parent's values.
  • The tags: key in values must be a top level key. Globals and nested tags: tablesare not currently supported.

Importing Child Values via requirements.yaml

In some cases it is desirable to allow a child chart's values to propagate to the parent chart and beshared as common defaults. An additional benefit of using the exports format is that it will enable futuretooling to introspect user-settable values.

The keys containing the values to be imported can be specified in the parent chart's requirements.yaml fileusing a YAML list. Each item in the list is a key which is imported from the child chart's exports field.

To import values not contained in the exports key, use the child-parent format.Examples of both formats are described below.

Using the exports format

If a child chart's values.yaml file contains an exports field at the root, its contents may be importeddirectly into the parent's values by specifying the keys to import as in the example below:

  1. # parent's requirements.yaml file
  2. ...
  3. import-values:
  4. - data
  1. # child's values.yaml file
  2. ...
  3. exports:
  4. data:
  5. myint: 99

Since we are specifying the key data in our import list, Helm looks in the exports field of the childchart for data key and imports its contents.

The final parent values would contain our exported field:

  1. # parent's values file
  2. ...
  3. myint: 99

Please note the parent key data is not contained in the parent's final values. If you need to specify theparent key, use the 'child-parent' format.

Using the child-parent format

To access values that are not contained in the exports key of the child chart's values, you will need tospecify the source key of the values to be imported (child) and the destination path in the parent chart'svalues (parent).

The import-values in the example below instructs Helm to take any values found at child: path and copy themto the parent's values at the path specified in parent:

  1. # parent's requirements.yaml file
  2. dependencies:
  3. - name: subchart1
  4. repository: http://localhost:10191
  5. version: 0.1.0
  6. ...
  7. import-values:
  8. - child: default.data
  9. parent: myimports

In the above example, values found at default.data in the subchart1's values will be importedto the myimports key in the parent chart's values as detailed below:

  1. # parent's values.yaml file
  2.  
  3. myimports:
  4. myint: 0
  5. mybool: false
  6. mystring: "helm rocks!"
  1. # subchart1's values.yaml file
  2.  
  3. default:
  4. data:
  5. myint: 999
  6. mybool: true

The parent chart's resulting values would be:

  1. # parent's final values
  2.  
  3. myimports:
  4. myint: 999
  5. mybool: true
  6. mystring: "helm rocks!"

The parent's final values now contains the myint and mybool fields imported from subchart1.

Managing Dependencies manually via the charts/ directory

If more control over dependencies is desired, these dependencies canbe expressed explicitly by copying the dependency charts into thecharts/ directory.

A dependency can be either a chart archive (foo-1.2.3.tgz) or anunpacked chart directory. But its name cannot start with _ or ..Such files are ignored by the chart loader.

For example, if the WordPress chart depends on the Apache chart, theApache chart (of the correct version) is supplied in the WordPresschart's charts/ directory:

  1. wordpress:
  2. Chart.yaml
  3. requirements.yaml
  4. # ...
  5. charts/
  6. apache/
  7. Chart.yaml
  8. # ...
  9. mysql/
  10. Chart.yaml
  11. # ...

The example above shows how the WordPress chart expresses its dependencyon Apache and MySQL by including those charts inside of its charts/directory.

TIP:To drop a dependency into your charts/ directory, use thehelm fetch command

Operational aspects of using dependencies

The above sections explain how to specify chart dependencies, but how does this affectchart installation using helm install and helm upgrade?

Suppose that a chart named "A" creates the following Kubernetes objects

  • namespace "A-Namespace"
  • statefulset "A-StatefulSet"
  • service "A-Service"Furthermore, A is dependent on chart B that creates objects

  • namespace "B-Namespace"

  • replicaset "B-ReplicaSet"
  • service "B-Service"After installation/upgrade of chart A, a single Helm release is created/modified. The release willcreate/update all of the above Kubernetes objects in the following order:

  • A-Namespace

  • B-Namespace
  • A-StatefulSet
  • B-ReplicaSet
  • A-Service
  • B-ServiceThis is because when Helm installs/upgrades charts,the Kubernetes objects from the charts and all its dependencies are

  • aggregated into a single set; then

  • sorted by type followed by name; and then
  • created/updated in that order.Hence a single release is created with all the objects for the chart and its dependencies.

The install order of Kubernetes types is given by the enumeration InstallOrder in kind_sorter.go(see the Helm source file).

Templates and Values

Helm Chart templates are written in theGo template language, with theaddition of 50 or so add-on templatefunctions from the Sprig library and afew other specialized functions.

All template files are stored in a chart's templates/ folder. WhenHelm renders the charts, it will pass every file in that directorythrough the template engine.

Values for the templates are supplied two ways:

  • Chart developers may supply a file called values.yaml inside of achart. This file can contain default values.
  • Chart users may supply a YAML file that contains values. This can beprovided on the command line with helm install.When a user supplies custom values, these values will override thevalues in the chart's values.yaml file.

Template Files

Template files follow the standard conventions for writing Go templates(see the text/template Go package documentationfor details).An example template file might look something like this:

  1. apiVersion: v1
  2. kind: ReplicationController
  3. metadata:
  4. name: deis-database
  5. namespace: deis
  6. labels:
  7. app.kubernetes.io/managed-by: deis
  8. spec:
  9. replicas: 1
  10. selector:
  11. app.kubernetes.io/name: deis-database
  12. template:
  13. metadata:
  14. labels:
  15. app.kubernetes.io/name: deis-database
  16. spec:
  17. serviceAccount: deis-database
  18. containers:
  19. - name: deis-database
  20. image: {{.Values.imageRegistry}}/postgres:{{.Values.dockerTag}}
  21. imagePullPolicy: {{.Values.pullPolicy}}
  22. ports:
  23. - containerPort: 5432
  24. env:
  25. - name: DATABASE_STORAGE
  26. value: {{default "minio" .Values.storage}}

The above example, based loosely on https://github.com/deis/charts, is a template for a Kubernetes replication controller.It can use the following four template values (usually defined in avalues.yaml file):

  • imageRegistry: The source registry for the Docker image.
  • dockerTag: The tag for the docker image.
  • pullPolicy: The Kubernetes pull policy.
  • storage: The storage backend, whose default is set to "minio"All of these values are defined by the template author. Helm does notrequire or dictate parameters.

To see many working charts, check out the Helm Chartsproject

Predefined Values

Values that are supplied via a values.yaml file (or via the —setflag) are accessible from the .Values object in a template. But thereare other pre-defined pieces of data you can access in your templates.

The following values are pre-defined, are available to every template, andcannot be overridden. As with all values, the names are casesensitive.

  • Release.Name: The name of the release (not the chart)
  • Release.Time: The time the chart release was last updated. This willmatch the Last Released time on a Release object.
  • Release.Namespace: The namespace the chart was released to.
  • Release.Service: The service that conducted the release. Usuallythis is Tiller.
  • Release.IsUpgrade: This is set to true if the current operation is an upgrade or rollback.
  • Release.IsInstall: This is set to true if the current operation is aninstall.
  • Release.Revision: The revision number. It begins at 1, and increments witheach helm upgrade.
  • Chart: The contents of the Chart.yaml. Thus, the chart version isobtainable as Chart.Version and the maintainers are inChart.Maintainers.
  • Files: A map-like object containing all non-special files in the chart. Thiswill not give you access to templates, but will give you access to additionalfiles that are present (unless they are excluded using .helmignore). Files can beaccessed using {{index .Files "file.name"}} or using the {{.Files.Get name}} or{{.Files.GetString name}} functions. You can also access the contents of the fileas []byte using {{.Files.GetBytes}}
  • Capabilities: A map-like object that contains information about the versionsof Kubernetes ({{.Capabilities.KubeVersion}}, Tiller({{.Capabilities.TillerVersion}}, and the supported Kubernetes API versions({{.Capabilities.APIVersions.Has "batch/v1")NOTE: Any unknown Chart.yaml fields will be dropped. They will notbe accessible inside of the Chart object. Thus, Chart.yaml cannot beused to pass arbitrarily structured data into the template. The valuesfile can be used for that, though.

Values files

Considering the template in the previous section, a values.yaml filethat supplies the necessary values would look like this:

  1. imageRegistry: "quay.io/deis"
  2. dockerTag: "latest"
  3. pullPolicy: "Always"
  4. storage: "s3"

A values file is formatted in YAML. A chart may include a defaultvalues.yaml file. The Helm install command allows a user to overridevalues by supplying additional YAML values:

  1. $ helm install --values=myvals.yaml wordpress

When values are passed in this way, they will be merged into the defaultvalues file. For example, consider a myvals.yaml file that looks likethis:

  1. storage: "gcs"

When this is merged with the values.yaml in the chart, the resultinggenerated content will be:

  1. imageRegistry: "quay.io/deis"
  2. dockerTag: "latest"
  3. pullPolicy: "Always"
  4. storage: "gcs"

Note that only the last field was overridden.

NOTE: The default values file included inside of a chart must be namedvalues.yaml. But files specified on the command line can be namedanything.

NOTE: If the —set flag is used on helm install or helm upgrade, thosevalues are simply converted to YAML on the client side.

NOTE: If any required entries in the values file exist, they can be declaredas required in the chart template by using the 'required' function

Any of these values are then accessible inside of templates using the.Values object:

  1. apiVersion: v1
  2. kind: ReplicationController
  3. metadata:
  4. name: deis-database
  5. namespace: deis
  6. labels:
  7. app.kubernetes.io/managed-by: deis
  8. spec:
  9. replicas: 1
  10. selector:
  11. app.kubernetes.io/name: deis-database
  12. template:
  13. metadata:
  14. labels:
  15. app.kubernetes.io/name: deis-database
  16. spec:
  17. serviceAccount: deis-database
  18. containers:
  19. - name: deis-database
  20. image: {{.Values.imageRegistry}}/postgres:{{.Values.dockerTag}}
  21. imagePullPolicy: {{.Values.pullPolicy}}
  22. ports:
  23. - containerPort: 5432
  24. env:
  25. - name: DATABASE_STORAGE
  26. value: {{default "minio" .Values.storage}}

Scope, Dependencies, and Values

Values files can declare values for the top-level chart, as well as forany of the charts that are included in that chart's charts/ directory.Or, to phrase it differently, a values file can supply values to thechart as well as to any of its dependencies. For example, thedemonstration WordPress chart above has both mysql and apache asdependencies. The values file could supply values to all of thesecomponents:

  1. title: "My WordPress Site" # Sent to the WordPress template
  2.  
  3. mysql:
  4. max_connections: 100 # Sent to MySQL
  5. password: "secret"
  6.  
  7. apache:
  8. port: 8080 # Passed to Apache

Charts at a higher level have access to all of the variables definedbeneath. So the WordPress chart can access the MySQL password as.Values.mysql.password. But lower level charts cannot access things inparent charts, so MySQL will not be able to access the title property. Nor,for that matter, can it access apache.port.

Values are namespaced, but namespaces are pruned. So for the WordPresschart, it can access the MySQL password field as .Values.mysql.password. Butfor the MySQL chart, the scope of the values has been reduced and thenamespace prefix removed, so it will see the password field simply as.Values.password.

Global Values

As of 2.0.0-Alpha.2, Helm supports special "global" value. Considerthis modified version of the previous example:

  1. title: "My WordPress Site" # Sent to the WordPress template
  2.  
  3. global:
  4. app: MyWordPress
  5.  
  6. mysql:
  7. max_connections: 100 # Sent to MySQL
  8. password: "secret"
  9.  
  10. apache:
  11. port: 8080 # Passed to Apache

The above adds a global section with the value app: MyWordPress.This value is available to all charts as .Values.global.app.

For example, the mysql templates may access app as {{.Values.global.app}}, andso can the apache chart. Effectively, the values file above isregenerated like this:

  1. title: "My WordPress Site" # Sent to the WordPress template
  2.  
  3. global:
  4. app: MyWordPress
  5.  
  6. mysql:
  7. global:
  8. app: MyWordPress
  9. max_connections: 100 # Sent to MySQL
  10. password: "secret"
  11.  
  12. apache:
  13. global:
  14. app: MyWordPress
  15. port: 8080 # Passed to Apache

This provides a way of sharing one top-level variable with allsubcharts, which is useful for things like setting metadata propertieslike labels.

If a subchart declares a global variable, that global will be passeddownward (to the subchart's subcharts), but not upward to the parentchart. There is no way for a subchart to influence the values of theparent chart.

Also, global variables of parent charts take precedence over the global variables from subcharts.

References

When it comes to writing templates and values files, there are severalstandard references that will help you out.

Using Helm to Manage Charts

The helm tool has several commands for working with charts.

It can create a new chart for you:

  1. $ helm create mychart
  2. Created mychart/

Once you have edited a chart, helm can package it into a chart archivefor you:

  1. $ helm package mychart
  2. Archived mychart-0.1.-.tgz

You can also use helm to help you find issues with your chart'sformatting or information:

  1. $ helm lint mychart
  2. No issues found

Chart Repositories

A chart repository is an HTTP server that houses one or more packagedcharts. While helm can be used to manage local chart directories, whenit comes to sharing charts, the preferred mechanism is a chartrepository.

Any HTTP server that can serve YAML files and tar files and can answerGET requests can be used as a repository server.

Helm comes with built-in package server for developer testing (helm serve). The Helm team has tested other servers, including Google CloudStorage with website mode enabled, and S3 with website mode enabled.

A repository is characterized primarily by the presence of a specialfile called index.yaml that has a list of all of the packages suppliedby the repository, together with metadata that allows retrieving andverifying those packages.

On the client side, repositories are managed with the helm repocommands. However, Helm does not provide tools for uploading charts toremote repository servers. This is because doing so would addsubstantial requirements to an implementing server, and thus raise thebarrier for setting up a repository.

Chart Starter Packs

The helm create command takes an optional —starter option that lets youspecify a "starter chart".

Starters are just regular charts, but are located in $HELM_HOME/starters.As a chart developer, you may author charts that are specifically designedto be used as starters. Such charts should be designed with the followingconsiderations in mind:

  • The Chart.yaml will be overwritten by the generator.
  • Users will expect to modify such a chart's contents, so documentationshould indicate how users can do so.
  • All occurrences of <CHARTNAME> in files within the templates directorywill be replaced with the specified chart name so that starter charts can beused as templates. Additionally, occurrences of <CHARTNAME> invalues.yaml will also be replaced.Currently the only way to add a chart to $HELM_HOME/starters is to manuallycopy it there. In your chart's documentation, you may want to explain thatprocess.