github.com/zoumo/helm@v2.5.0+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 ## Automatically Roll Deployments When ConfigMaps or Secrets change 100 101 Often times configmaps or secrets are injected as configuration 102 files in containers. 103 Depending on the application a restart may be required should those 104 be updated with a subsequent `helm upgrade`, but if the 105 deployment spec itself didn't change the application keeps running 106 with the old configuration resulting in an inconsistent deployment. 107 108 The `sha256sum` function can be used together with the `include` 109 function to ensure a deployments template section is updated if another 110 spec changes: 111 112 ```yaml 113 kind: Deployment 114 spec: 115 template: 116 metadata: 117 annotations: 118 checksum/config: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} 119 [...] 120 ``` 121 122 ## Tell Tiller Not To Delete a Resource 123 124 Sometimes there are resources that should not be deleted when Helm runs a 125 `helm delete`. Chart developers can add an annotation to a resource to prevent 126 it from being deleted. 127 128 ```yaml 129 kind: Secret 130 metadata: 131 annotations: 132 "helm.sh/resource-policy": keep 133 [...] 134 ``` 135 136 (Quotation marks are required) 137 138 The annotation `"helm.sh/resource-policy": keep` instructs Tiller to skip this 139 resource during a `helm delete` operation. _However_, this resource becomes 140 orphaned. Helm will no longer manage it in any way. This can lead to problems 141 if using `helm install --replace` on a release that has already been deleted, but 142 has kept resources. 143 144 ## Using "Partials" and Template Includes 145 146 Sometimes you want to create some reusable parts in your chart, whether 147 they're blocks or template partials. And often, it's cleaner to keep 148 these in their own files. 149 150 In the `templates/` directory, any file that begins with an 151 underscore(`_`) is not expected to output a Kubernetes manifest file. So 152 by convention, helper templates and partials are placed in a 153 `_helpers.tpl` file. 154 155 ## Complex Charts with Many Dependencies 156 157 Many of the charts in the [official charts repository](https://github.com/kubernetes/charts) 158 are "building blocks" for creating more advanced applications. But charts may be 159 used to create instances of large-scale applications. In such cases, a single 160 umbrella chart may have multiple subcharts, each of which functions as a piece 161 of the whole. 162 163 The current best practice for composing a complex application from discrete parts 164 is to create a top-level umbrella chart that 165 exposes the global configurations, and then use the `charts/` subdirectory to 166 embed each of the components. 167 168 Two strong design patterns are illustrated by these projects: 169 170 **SAP's [OpenStack chart](https://github.com/sapcc/openstack-helm):** This chart 171 installs a full OpenStack IaaS on Kubernetes. All of the charts are collected 172 together in one GitHub repository. 173 174 **Deis's [Workflow](https://github.com/deis/workflow/tree/master/charts/workflow):** 175 This chart exposes the entire Deis PaaS system with one chart. But it's different 176 from the SAP chart in that this master chart is built from each component, and 177 each component is tracked in a different Git repository. Check out the 178 `requirements.yaml` file to see how this chart is composed by their CI/CD 179 pipeline. 180 181 Both of these charts illustrate proven techniques for standing up complex environments 182 using Helm. 183 184 ## YAML is a Superset of JSON 185 186 According to the YAML specification, YAML is a superset of JSON. That 187 means that any valid JSON structure ought to be valid in YAML. 188 189 This has an advantage: Sometimes template developers may find it easier 190 to express a datastructure with a JSON-like syntax rather than deal with 191 YAML's whitespace sensitivity. 192 193 As a best practice, templates should follow a YAML-like syntax _unless_ 194 the JSON syntax substantially reduces the risk of a formatting issue. 195 196 ## Be Careful with Generating Random Values 197 198 There are functions in Helm that allow you to generate random data, 199 cryptographic keys, and so on. These are fine to use. But be aware that 200 during upgrades, templates are re-executed. When a template run 201 generates data that differs from the last run, that will trigger an 202 update of that resource.