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 ```