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