github.com/amy/helm@v2.7.2+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.tpl`, then 22 lowercases the result, then wraps that in double quotes. 23 24 ```yaml 25 value: {{include "mytpl.tpl" . | 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 together with the `include` 138 function to ensure a deployments template section is updated if another 139 spec changes: 140 141 ```yaml 142 kind: Deployment 143 spec: 144 template: 145 metadata: 146 annotations: 147 checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} 148 [...] 149 ``` 150 151 ## Tell Tiller Not To Delete a Resource 152 153 Sometimes there are resources that should not be deleted when Helm runs a 154 `helm delete`. Chart developers can add an annotation to a resource to prevent 155 it from being deleted. 156 157 ```yaml 158 kind: Secret 159 metadata: 160 annotations: 161 "helm.sh/resource-policy": keep 162 [...] 163 ``` 164 165 (Quotation marks are required) 166 167 The annotation `"helm.sh/resource-policy": keep` instructs Tiller to skip this 168 resource during a `helm delete` operation. _However_, this resource becomes 169 orphaned. Helm will no longer manage it in any way. This can lead to problems 170 if using `helm install --replace` on a release that has already been deleted, but 171 has kept resources. 172 173 ## Using "Partials" and Template Includes 174 175 Sometimes you want to create some reusable parts in your chart, whether 176 they're blocks or template partials. And often, it's cleaner to keep 177 these in their own files. 178 179 In the `templates/` directory, any file that begins with an 180 underscore(`_`) is not expected to output a Kubernetes manifest file. So 181 by convention, helper templates and partials are placed in a 182 `_helpers.tpl` file. 183 184 ## Complex Charts with Many Dependencies 185 186 Many of the charts in the [official charts repository](https://github.com/kubernetes/charts) 187 are "building blocks" for creating more advanced applications. But charts may be 188 used to create instances of large-scale applications. In such cases, a single 189 umbrella chart may have multiple subcharts, each of which functions as a piece 190 of the whole. 191 192 The current best practice for composing a complex application from discrete parts 193 is to create a top-level umbrella chart that 194 exposes the global configurations, and then use the `charts/` subdirectory to 195 embed each of the components. 196 197 Two strong design patterns are illustrated by these projects: 198 199 **SAP's [OpenStack chart](https://github.com/sapcc/openstack-helm):** This chart 200 installs a full OpenStack IaaS on Kubernetes. All of the charts are collected 201 together in one GitHub repository. 202 203 **Deis's [Workflow](https://github.com/deis/workflow/tree/master/charts/workflow):** 204 This chart exposes the entire Deis PaaS system with one chart. But it's different 205 from the SAP chart in that this master chart is built from each component, and 206 each component is tracked in a different Git repository. Check out the 207 `requirements.yaml` file to see how this chart is composed by their CI/CD 208 pipeline. 209 210 Both of these charts illustrate proven techniques for standing up complex environments 211 using Helm. 212 213 ## YAML is a Superset of JSON 214 215 According to the YAML specification, YAML is a superset of JSON. That 216 means that any valid JSON structure ought to be valid in YAML. 217 218 This has an advantage: Sometimes template developers may find it easier 219 to express a datastructure with a JSON-like syntax rather than deal with 220 YAML's whitespace sensitivity. 221 222 As a best practice, templates should follow a YAML-like syntax _unless_ 223 the JSON syntax substantially reduces the risk of a formatting issue. 224 225 ## Be Careful with Generating Random Values 226 227 There are functions in Helm that allow you to generate random data, 228 cryptographic keys, and so on. These are fine to use. But be aware that 229 during upgrades, templates are re-executed. When a template run 230 generates data that differs from the last run, that will trigger an 231 update of that resource.