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