github.com/umeshredd/helm@v3.0.0-alpha.1+incompatible/docs/charts_tips_and_tricks.md (about)

     1  # Chart Development Tips and Tricks
     2  
     3  This guide covers some of the tips and tricks Helm chart developers have
     4  learned while building production-quality charts.
     5  
     6  ## Know Your Template Functions
     7  
     8  Helm uses [Go templates](https://godoc.org/text/template) for templating
     9  your resource files. While Go ships several built-in functions, we have
    10  added many others.
    11  
    12  First, we added all of the functions in the
    13  [Sprig library](https://godoc.org/github.com/Masterminds/sprig).
    14  
    15  We also added two special template functions: `include` and `required`. The `include`
    16  function allows you to bring in another template, and then pass the results to other
    17  template functions.
    18  
    19  For example, this template snippet includes a template called `mytpl`, then
    20  lowercases the result, then wraps that in double quotes.
    21  
    22  ```yaml
    23  value: {{include "mytpl" . | lower | quote}}
    24  ```
    25  
    26  The `required` function allows you to declare a particular
    27  values entry as required for template rendering.  If the value is empty, the template
    28  rendering will fail with a user submitted error message.
    29  
    30  The following example of the `required` function declares an entry for .Values.who
    31  is required, and will print an error message when that entry is missing:
    32  
    33  ```yaml
    34  value: {{required "A valid .Values.who entry required!" .Values.who }}
    35  ```
    36  
    37  ## Quote Strings, Don't Quote Integers
    38  
    39  When you are working with string data, you are always safer quoting the
    40  strings than leaving them as bare words:
    41  
    42  ```
    43  name: {{.Values.MyName | quote }}
    44  ```
    45  
    46  But when working with integers _do not quote the values._ That can, in
    47  many cases, cause parsing errors inside of Kubernetes.
    48  
    49  ```
    50  port: {{ .Values.Port }}
    51  ```
    52  
    53  This remark does not apply to env variables values which are expected to be string, even if they represent integers:
    54  
    55  ```
    56  env:
    57    -name: HOST
    58      value: "http://host"
    59    -name: PORT
    60      value: "1234"
    61  ```
    62  
    63  ## Using the 'include' Function
    64  
    65  Go provides a way of including one template in another using a built-in
    66  `template` directive. However, the built-in function cannot be used in
    67  Go template pipelines.
    68  
    69  To make it possible to include a template, and then perform an operation
    70  on that template's output, Helm has a special `include` function:
    71  
    72  ```
    73  {{ include "toYaml" $value | indent 2 }}
    74  ```
    75  
    76  The above includes a template called `toYaml`, passes it `$value`, and
    77  then passes the output of that template to the `indent` function.
    78  
    79  Because YAML ascribes significance to indentation levels and whitespace,
    80  this is one great way to include snippets of code, but handle
    81  indentation in a relevant context.
    82  
    83  ## Using the 'required' function
    84  
    85  Go provides a way for setting template options to control behavior
    86  when a map is indexed with a key that's not present in the map. This
    87  is typically set with template.Options("missingkey=option"), where option
    88  can be default, zero, or error. While setting this option to error will
    89  stop execution with an error, this would apply to every missing key in the
    90  map. There may be situations where a chart developer wants to enforce this
    91  behavior for select values in the values.yml file.
    92  
    93  The `required` function gives developers the ability to declare a value entry
    94  as required for template rendering. If the entry is empty in values.yml, the
    95  template will not render and will return an error message supplied by the
    96  developer.
    97  
    98  For example:
    99  
   100  ```
   101  {{ required "A valid foo is required!" .Values.foo }}
   102  ```
   103  
   104  The above will render the template when .Values.foo is defined, but will fail
   105  to render and exit when .Values.foo is undefined.
   106  
   107  ## Creating Image Pull Secrets
   108  Image pull secrets are essentially a combination of _registry_, _username_, and _password_.  You may need them in an application you are deploying, but to create them requires running _base64_ a couple of times.  We can write a helper template to compose the Docker configuration file for use as the Secret's payload.  Here is an example:
   109  
   110  First, assume that the credentials are defined in the `values.yaml` file like so:
   111  ```
   112  imageCredentials:
   113    registry: quay.io
   114    username: someone
   115    password: sillyness
   116  ```  
   117  
   118  We then define our helper template as follows:
   119  ```
   120  {{- define "imagePullSecret" }}
   121  {{- printf "{\"auths\": {\"%s\": {\"auth\": \"%s\"}}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }}
   122  {{- end }}
   123  ```
   124  
   125  Finally, we use the helper template in a larger template to create the Secret manifest:
   126  ```
   127  apiVersion: v1
   128  kind: Secret
   129  metadata:
   130    name: myregistrykey
   131  type: kubernetes.io/dockerconfigjson
   132  data:
   133    .dockerconfigjson: {{ template "imagePullSecret" . }}
   134  ```
   135  
   136  ## Automatically Roll Deployments When ConfigMaps or Secrets change
   137  
   138  Often times configmaps or secrets are injected as configuration
   139  files in containers.
   140  Depending on the application a restart may be required should those
   141  be updated with a subsequent `helm upgrade`, but if the
   142  deployment spec itself didn't change the application keeps running
   143  with the old configuration resulting in an inconsistent deployment.
   144  
   145  The `sha256sum` function can be used to ensure a deployment's
   146  annotation section is updated if another file changes: 
   147  
   148  ```yaml
   149  kind: Deployment
   150  spec:
   151    template:
   152      metadata:
   153        annotations:
   154          checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
   155  [...]
   156  ```
   157  
   158  See also the `helm upgrade --recreate-pods` flag for a slightly
   159  different way of addressing this issue.
   160  
   161  ## Tell Helm Not To Uninstall a Resource
   162  
   163  Sometimes there are resources that should not be uninstalled when Helm runs a
   164  `helm uninstall`. Chart developers can add an annotation to a resource to prevent
   165  it from being uninstalled.
   166  
   167  ```yaml
   168  kind: Secret
   169  metadata:
   170    annotations:
   171      "helm.sh/resource-policy": keep
   172  [...]
   173  ```
   174  
   175  (Quotation marks are required)
   176  
   177  The annotation `"helm.sh/resource-policy": keep` instructs Helm to skip this
   178  resource during a `helm uninstall` operation. _However_, this resource becomes
   179  orphaned. Helm will no longer manage it in any way. This can lead to problems
   180  if using `helm install --replace` on a release that has already been uninstalled, but
   181  has kept resources.
   182  
   183  ## Using "Partials" and Template Includes
   184  
   185  Sometimes you want to create some reusable parts in your chart, whether
   186  they're blocks or template partials. And often, it's cleaner to keep
   187  these in their own files.
   188  
   189  In the `templates/` directory, any file that begins with an
   190  underscore(`_`) is not expected to output a Kubernetes manifest file. So
   191  by convention, helper templates and partials are placed in a
   192  `_helpers.tpl` file.
   193  
   194  ## Complex Charts with Many Dependencies
   195  
   196  Many of the charts in the [official charts repository](https://github.com/helm/charts)
   197  are "building blocks" for creating more advanced applications. But charts may be
   198  used to create instances of large-scale applications. In such cases, a single
   199  umbrella chart may have multiple subcharts, each of which functions as a piece
   200  of the whole.
   201  
   202  The current best practice for composing a complex application from discrete parts
   203  is to create a top-level umbrella chart that
   204  exposes the global configurations, and then use the `charts/` subdirectory to
   205  embed each of the components.
   206  
   207  Two strong design patterns are illustrated by these projects:
   208  
   209  **SAP's [OpenStack chart](https://github.com/sapcc/openstack-helm):** This chart
   210  installs a full OpenStack IaaS on Kubernetes. All of the charts are collected
   211  together in one GitHub repository.
   212  
   213  **Deis's [Workflow](https://github.com/deis/workflow/tree/master/charts/workflow):**
   214  This chart exposes the entire Deis PaaS system with one chart. But it's different
   215  from the SAP chart in that this umbrella chart is built from each component, and
   216  each component is tracked in a different Git repository. Check out the
   217  `requirements.yaml` file to see how this chart is composed by their CI/CD
   218  pipeline.
   219  
   220  Both of these charts illustrate proven techniques for standing up complex environments
   221  using Helm.
   222  
   223  ## YAML is a Superset of JSON
   224  
   225  According to the YAML specification, YAML is a superset of JSON. That
   226  means that any valid JSON structure ought to be valid in YAML.
   227  
   228  This has an advantage: Sometimes template developers may find it easier
   229  to express a datastructure with a JSON-like syntax rather than deal with
   230  YAML's whitespace sensitivity.
   231  
   232  As a best practice, templates should follow a YAML-like syntax _unless_
   233  the JSON syntax substantially reduces the risk of a formatting issue.
   234  
   235  ## Be Careful with Generating Random Values
   236  
   237  There are functions in Helm that allow you to generate random data,
   238  cryptographic keys, and so on. These are fine to use. But be aware that
   239  during upgrades, templates are re-executed. When a template run
   240  generates data that differs from the last run, that will trigger an
   241  update of that resource.
   242  
   243  ## Upgrade a release idempotently
   244  
   245  In order to use the same command when installing and upgrading a release, use the following command:
   246  ```shell
   247  helm upgrade --install <release name> --values <values file> <chart directory>
   248  ```