1# Common: The Helm Helper Chart
2
3This chart is designed to make it easier for you to build and maintain Helm
4charts.
5
6It provides utilities that reflect best practices of Kubernetes chart development,
7making it faster for you to write charts.
8
9## Tips
10
11A few tips for working with Common:
12
13- Be careful when using functions that generate random data (like `common.fullname.unique`).
14  They may trigger unwanted upgrades or have other side effects.
15
16In this document, we use `RELEASE-NAME` as the name of the release.
17
18## Resource Kinds
19
20Kubernetes defines a variety of resource kinds, from `Secret` to `StatefulSet`.
21We define some of the most common kinds in a way that lets you easily work with
22them.
23
24The resource kind templates are designed to make it much faster for you to
25define _basic_ versions of these resources. They allow you to extend and modify
26just what you need, without having to copy around lots of boilerplate.
27
28To make use of these templates you must define a template that will extend the
29base template (though it can be empty). The name of this template is then passed
30to the base template, for example:
31
32```yaml
33{{- template "common.service" (list . "mychart.service") -}}
34{{- define "mychart.service" -}}
35## Define overrides for your Service resource here, e.g.
36# metadata:
37#   labels:
38#     custom: label
39# spec:
40#   ports:
41#   - port: 8080
42{{- end -}}
43```
44
45Note that the `common.service` template defines two parameters:
46
47  - The root context (usually `.`)
48  - A template name containing the service definition overrides
49
50A limitation of the Go template library is that a template can only take a
51single argument. The `list` function is used to workaround this by constructing
52a list or array of arguments that is passed to the template.
53
54The `common.service` template is responsible for rendering the templates with
55the root context and merging any overrides. As you can see, this makes it very
56easy to create a basic `Service` resource without having to copy around the
57standard metadata and labels.
58
59Each implemented base resource is described in greater detail below.
60
61### `common.service`
62
63The `common.service` template creates a basic `Service` resource with the
64following defaults:
65
66- Service type (ClusterIP, NodePort, LoadBalancer) made configurable by `.Values.service.type`
67- Named port `http` configured on port 80
68- Selector set to `app.kubernetes.io/name: {{ template "common.name" }}, app.kubernetes.io/instance: {{ .Release.Name | quote }}` to match the default used in the `Deployment` resource
69
70Example template:
71
72```yaml
73{{- template "common.service" (list . "mychart.mail.service") -}}
74{{- define "mychart.mail.service" -}}
75metadata:
76  name: {{ template "common.fullname" . }}-mail # overrides the default name to add a suffix
77  labels:                                       # appended to the labels section
78    protocol: mail
79spec:
80  ports:                                        # composes the `ports` section of the service definition.
81  - name: smtp
82    port: 25
83    targetPort: 25
84  - name: imaps
85    port: 993
86    targetPort: 993
87  selector:                                     # this is appended to the default selector
88    protocol: mail
89{{- end -}}
90---
91{{ template "common.service" (list . "mychart.web.service") -}}
92{{- define "mychart.web.service" -}}
93metadata:
94  name: {{ template "common.fullname" . }}-www  # overrides the default name to add a suffix
95  labels:                                       # appended to the labels section
96    protocol: www
97spec:
98  ports:                                        # composes the `ports` section of the service definition.
99  - name: www
100    port: 80
101    targetPort: 8080
102{{- end -}}
103```
104
105The above template defines _two_ services: a web service and a mail service.
106
107The most important part of a service definition is the `ports` object, which
108defines the ports that this service will listen on. Most of the time,
109`selector` is computed for you. But you can replace it or add to it.
110
111The output of the example above is:
112
113```yaml
114apiVersion: v1
115kind: Service
116metadata:
117  labels:
118    app.kubernetes.io/name: service
119    helm.sh/chart: service-0.1.0
120    app.kubernetes.io/managed-by: Helm
121    protocol: mail
122    app.kubernetes.io/instance: release-name
123  name: release-name-service-mail
124spec:
125  ports:
126  - name: smtp
127    port: 25
128    targetPort: 25
129  - name: imaps
130    port: 993
131    targetPort: 993
132  selector:
133    app.kubernetes.io/name: service
134    app.kubernetes.io/instance: release-name
135    protocol: mail
136  type: ClusterIP
137---
138apiVersion: v1
139kind: Service
140metadata:
141  labels:
142    app.kubernetes.io/name: service
143    helm.sh/chart: service-0.1.0
144    app.kubernetes.io/managed-by: Helm
145    protocol: www
146    app.kubernetes.io/instance: release-name
147  name: release-name-service-www
148spec:
149  ports:
150  - name: www
151    port: 80
152    targetPort: 8080
153  type: ClusterIP
154```
155
156## `common.deployment`
157
158The `common.deployment` template defines a basic `Deployment`. Underneath the
159hood, it uses `common.container` (see next section).
160
161By default, the pod template within the deployment defines the labels `app: {{ template "common.name" . }}`
162and `release: {{ .Release.Name | quote }` as this is also used as the selector. The
163standard set of labels are not used as some of these can change during upgrades,
164which causes the replica sets and pods to not correctly match.
165
166Example use:
167
168```yaml
169{{- template "common.deployment" (list . "mychart.deployment") -}}
170{{- define "mychart.deployment" -}}
171## Define overrides for your Deployment resource here, e.g.
172spec:
173  replicas: {{ .Values.replicaCount }}
174{{- end -}}
175```
176
177## `common.container`
178
179The `common.container` template creates a basic `Container` spec to be used
180within a `Deployment` or `ReplicaSet`. It holds the following defaults:
181
182- The name is set to the chart name
183- Uses `.Values.image` to describe the image to run, with the following spec:
184  ```yaml
185  image:
186    repository: nginx
187    tag: stable
188    pullPolicy: IfNotPresent
189  ```
190- Exposes the named port `http` as port 80
191- Lays out the compute resources using `.Values.resources`
192
193Example use:
194
195```yaml
196{{- template "common.deployment" (list . "mychart.deployment") -}}
197{{- define "mychart.deployment" -}}
198## Define overrides for your Deployment resource here, e.g.
199spec:
200  template:
201    spec:
202      containers:
203      - {{ template "common.container" (list . "mychart.deployment.container") }}
204{{- end -}}
205{{- define "mychart.deployment.container" -}}
206## Define overrides for your Container here, e.g.
207livenessProbe:
208  httpGet:
209    path: /
210    port: 80
211readinessProbe:
212  httpGet:
213    path: /
214    port: 80
215{{- end -}}
216```
217
218The above example creates a `Deployment` resource which makes use of the
219`common.container` template to populate the PodSpec's container list. The usage
220of this template is similar to the other resources, you must define and
221reference a template that contains overrides for the container object.
222
223The most important part of a container definition is the image you want to run.
224As mentioned above, this is derived from `.Values.image` by default. It is a
225best practice to define the image, tag and pull policy in your charts' values as
226this makes it easy for an operator to change the image registry, or use a
227specific tag or version. Another example of configuration that should be exposed
228to chart operators is the container's required compute resources, as this is
229also very specific to an operators environment. An example `values.yaml` for
230your chart could look like:
231
232```yaml
233image:
234  repository: nginx
235  tag: stable
236  pullPolicy: IfNotPresent
237resources:
238  limits:
239    cpu: 100m
240    memory: 128Mi
241  requests:
242    cpu: 100m
243    memory: 128Mi
244```
245
246The output of running the above values through the earlier template is:
247
248```yaml
249apiVersion: extensions/v1beta1
250kind: Deployment
251metadata:
252  labels:
253    app.kubernetes.io/name: deployment
254    helm.sh/chart: deployment-0.1.0
255    app.kubernetes.io/managed-by: Helm
256    app.kubernetes.io/instance: release-name
257  name: release-name-deployment
258spec:
259  template:
260    metadata:
261      labels:
262        app.kubernetes.io/name: deployment
263    spec:
264      containers:
265      - image: nginx:stable
266        imagePullPolicy: IfNotPresent
267        livenessProbe:
268          httpGet:
269            path: /
270            port: 80
271        name: deployment
272        ports:
273        - containerPort: 80
274          name: http
275        readinessProbe:
276          httpGet:
277            path: /
278            port: 80
279        resources:
280          limits:
281            cpu: 100m
282            memory: 128Mi
283          requests:
284            cpu: 100m
285            memory: 128Mi
286```
287
288## `common.configmap`
289
290The `common.configmap` template creates an empty `ConfigMap` resource that you
291can override with your configuration.
292
293Example use:
294
295```yaml
296{{- template "common.configmap" (list . "mychart.configmap") -}}
297{{- define "mychart.configmap" -}}
298data:
299  zeus: cat
300  athena: cat
301  julius: cat
302  one: |-
303    {{ .Files.Get "file1.txt" }}
304{{- end -}}
305```
306
307Output:
308
309```yaml
310apiVersion: v1
311data:
312  athena: cat
313  julius: cat
314  one: This is a file.
315  zeus: cat
316kind: ConfigMap
317metadata:
318  labels:
319    app.kubernetes.io/name: configmap
320    helm.sh/chart: configmap-0.1.0
321    app.kubernetes.io/managed-by: Helm
322    app.kubernetes.io/instance: release-name
323  name: release-name-configmap
324```
325
326## `common.secret`
327
328The `common.secret` template creates an empty `Secret` resource that you
329can override with your secrets.
330
331Example use:
332
333```yaml
334{{- template "common.secret" (list . "mychart.secret") -}}
335{{- define "mychart.secret" -}}
336data:
337  zeus: {{ print "cat" | b64enc }}
338  athena: {{ print "cat" | b64enc }}
339  julius: {{ print "cat" | b64enc }}
340  one: |-
341    {{ .Files.Get "file1.txt" | b64enc }}
342{{- end -}}
343```
344
345Output:
346
347```yaml
348apiVersion: v1
349data:
350  athena: Y2F0
351  julius: Y2F0
352  one: VGhpcyBpcyBhIGZpbGUuCg==
353  zeus: Y2F0
354kind: Secret
355metadata:
356  labels:
357    app.kubernetes.io/name: secret
358    helm.sh/chart: secret-0.1.0
359    app.kubernetes.io/managed-by: Helm
360    app.kubernetes.io/instance: release-name
361  name: release-name-secret
362type: Opaque
363```
364
365## `common.ingress`
366
367The `common.ingress` template is designed to give you a well-defined `Ingress`
368resource, that can be configured using `.Values.ingress`. An example values file
369that can be used to configure the `Ingress` resource is:
370
371```yaml
372ingress:
373  hosts:
374  - chart-example.local
375  annotations:
376    kubernetes.io/ingress.class: nginx
377    kubernetes.io/tls-acme: "true"
378  tls:
379  - secretName: chart-example-tls
380    hosts:
381    - chart-example.local
382```
383
384Example use:
385
386```yaml
387{{- template "common.ingress" (list . "mychart.ingress") -}}
388{{- define "mychart.ingress" -}}
389{{- end -}}
390```
391
392Output:
393
394```yaml
395apiVersion: extensions/v1beta1
396kind: Ingress
397metadata:
398  annotations:
399    kubernetes.io/ingress.class: nginx
400    kubernetes.io/tls-acme: "true"
401  labels:
402    app.kubernetes.io/name: ingress
403    helm.sh/chart: ingress-0.1.0
404    app.kubernetes.io/managed-by: Helm
405    app.kubernetes.io/instance: release-name
406  name: release-name-ingress
407spec:
408  rules:
409  - host: chart-example.local
410    http:
411      paths:
412      - backend:
413          serviceName: release-name-ingress
414          servicePort: 80
415        path: /
416  tls:
417  - hosts:
418    - chart-example.local
419    secretName: chart-example-tls
420```
421
422## `common.persistentvolumeclaim`
423
424`common.persistentvolumeclaim` can be used to easily add a
425`PersistentVolumeClaim` resource to your chart that can be configured using
426`.Values.persistence`:
427
428|           Value           |                                               Description                                               |
429| ------------------------- | ------------------------------------------------------------------------------------------------------- |
430| persistence.enabled       | Whether or not to claim a persistent volume. If false, `common.volume.pvc` will use an emptyDir instead |
431| persistence.storageClass  | `StorageClass` name                                                                                     |
432| persistence.accessMode    | Access mode for persistent volume                                                                       |
433| persistence.size          | Size of persistent volume                                                                               |
434| persistence.existingClaim | If defined, `PersistentVolumeClaim` is not created and `common.volume.pvc` helper uses this claim       |
435
436An example values file that can be used to configure the
437`PersistentVolumeClaim` resource is:
438
439```yaml
440persistence:
441  enabled: true
442  storageClass: fast
443  accessMode: ReadWriteOnce
444  size: 8Gi
445```
446
447Example use:
448
449```yaml
450{{- template "common.persistentvolumeclaim" (list . "mychart.persistentvolumeclaim") -}}
451{{- define "mychart.persistentvolumeclaim" -}}
452{{- end -}}
453```
454
455Output:
456
457```yaml
458apiVersion: v1
459kind: PersistentVolumeClaim
460metadata:
461  labels:
462    app.kubernetes.io/name: persistentvolumeclaim
463    helm.sh/chart: persistentvolumeclaim-0.1.0
464    app.kubernetes.io/managed-by: Helm
465    app.kubernetes.io/instance: release-name
466  name: release-name-persistentvolumeclaim
467spec:
468  accessModes:
469  - ReadWriteOnce
470  resources:
471    requests:
472      storage: 8Gi
473  storageClassName: "fast"
474```
475
476## Partial API Objects
477
478When writing Kubernetes resources, you may find the following helpers useful to
479construct parts of the spec.
480
481### EnvVar
482
483Use the EnvVar helpers within a container spec to simplify specifying key-value
484environment variables or referencing secrets as values.
485
486Example Use:
487
488```yaml
489{{- template "common.deployment" (list . "mychart.deployment") -}}
490{{- define "mychart.deployment" -}}
491spec:
492  template:
493    spec:
494      containers:
495      - {{ template "common.container" (list . "mychart.deployment.container") }}
496{{- end -}}
497{{- define "mychart.deployment.container" -}}
498{{- $fullname := include "common.fullname" . -}}
499env:
500- {{ template "common.envvar.value" (list "ZEUS" "cat") }}
501- {{ template "common.envvar.secret" (list "ATHENA" "secret-name" "athena") }}
502{{- end -}}
503```
504
505Output:
506
507```yaml
508...
509    spec:
510      containers:
511      - env:
512        - name: ZEUS
513          value: cat
514        - name: ATHENA
515          valueFrom:
516            secretKeyRef:
517              key: athena
518              name: secret-name
519...
520```
521
522### Volume
523
524Use the Volume helpers within a `Deployment` spec to help define ConfigMap and
525PersistentVolumeClaim volumes.
526
527Example Use:
528
529```yaml
530{{- template "common.deployment" (list . "mychart.deployment") -}}
531{{- define "mychart.deployment" -}}
532spec:
533  template:
534    spec:
535      volumes:
536      - {{ template "common.volume.configMap" (list "config" "configmap-name") }}
537      - {{ template "common.volume.pvc" (list "data" "pvc-name" .Values.persistence) }}
538{{- end -}}
539```
540
541Output:
542
543```yaml
544...
545    spec:
546      volumes:
547      - configMap:
548          name: configmap-name
549        name: config
550      - name: data
551        persistentVolumeClaim:
552          claimName: pvc-name
553...
554```
555
556The `common.volume.pvc` helper uses the following configuration from the `.Values.persistence` object:
557
558|           Value           |                      Description                      |
559| ------------------------- | ----------------------------------------------------- |
560| persistence.enabled       | If false, creates an `emptyDir` instead               |
561| persistence.existingClaim | If set, uses this instead of the passed in claim name |
562
563## Utilities
564
565### `common.fullname`
566
567The `common.fullname` template generates a name suitable for the `name:` field
568in Kubernetes metadata. It is used like this:
569
570```yaml
571name: {{ template "common.fullname" . }}
572```
573
574The following different values can influence it:
575
576```yaml
577# By default, fullname uses '{{ .Release.Name }}-{{ .Chart.Name }}'. This
578# overrides that and uses the given string instead.
579fullnameOverride: "some-name"
580
581# This adds a prefix
582fullnamePrefix: "pre-"
583# This appends a suffix
584fullnameSuffix: "-suf"
585
586# Global versions of the above
587global:
588  fullnamePrefix: "pp-"
589  fullnameSuffix: "-ps"
590```
591
592Example output:
593
594```yaml
595---
596# with the values above
597name: pp-pre-some-name-suf-ps
598
599---
600# the default, for release "happy-panda" and chart "wordpress"
601name: happy-panda-wordpress
602```
603
604Output of this function is truncated at 54 characters, which leaves 9 additional
605characters for customized overriding. Thus you can easily extend this name
606in your own charts:
607
608```yaml
609{{- define "my.fullname" -}}
610  {{ template "common.fullname" . }}-my-stuff
611{{- end -}}
612```
613
614### `common.fullname.unique`
615
616The `common.fullname.unique` variant of fullname appends a unique seven-character
617sequence to the end of the common name field.
618
619This takes all of the same parameters as `common.fullname`
620
621Example template:
622
623```yaml
624uniqueName: {{ template "common.fullname.unique" . }}
625```
626
627Example output:
628
629```yaml
630uniqueName: release-name-fullname-jl0dbwx
631```
632
633It is also impacted by the prefix and suffix definitions, as well as by
634`.Values.fullnameOverride`
635
636Note that the effective maximum length of this function is 63 characters, not 54.
637
638### `common.name`
639
640The `common.name` template generates a name suitable for the `app` label. It is used like this:
641
642```yaml
643app: {{ template "common.name" . }}
644```
645
646The following different values can influence it:
647
648```yaml
649# By default, name uses '{{ .Chart.Name }}'. This
650# overrides that and uses the given string instead.
651nameOverride: "some-name"
652
653# This adds a prefix
654namePrefix: "pre-"
655# This appends a suffix
656nameSuffix: "-suf"
657
658# Global versions of the above
659global:
660  namePrefix: "pp-"
661  nameSuffix: "-ps"
662```
663
664Example output:
665
666```yaml
667---
668# with the values above
669name: pp-pre-some-name-suf-ps
670
671---
672# the default, for chart "wordpress"
673name: wordpress
674```
675
676Output of this function is truncated at 54 characters, which leaves 9 additional
677characters for customized overriding. Thus you can easily extend this name
678in your own charts:
679
680```yaml
681{{- define "my.name" -}}
682  {{ template "common.name" . }}-my-stuff
683{{- end -}}
684```
685
686### `common.metadata`
687
688The `common.metadata` helper generates the `metadata:` section of a Kubernetes
689resource.
690
691This takes three objects:
692  - .top: top context
693  - .fullnameOverride: override the fullname with this name
694  - .metadata
695    - .labels: key/value list of labels
696    - .annotations: key/value list of annotations
697    - .hook: name(s) of hook(s)
698
699It generates standard labels, annotations, hooks, and a name field.
700
701Example template:
702
703```yaml
704{{ template "common.metadata" (dict "top" . "metadata" .Values.bio) }}
705---
706{{ template "common.metadata" (dict "top" . "metadata" .Values.pet "fullnameOverride" .Values.pet.fullnameOverride) }}
707```
708
709Example values:
710
711```yaml
712bio:
713  name: example
714  labels:
715    first: matt
716    last: butcher
717    nick: technosophos
718  annotations:
719    format: bio
720    destination: archive
721  hook: pre-install
722
723pet:
724  fullnameOverride: Zeus
725
726```
727
728Example output:
729
730```yaml
731metadata:
732  name: release-name-metadata
733  labels:
734    app.kubernetes.io/name: metadata
735    app.kubernetes.io/managed-by: "Helm"
736    app.kubernetes.io/instance: "RELEASE-NAME"
737    helm.sh/chart: metadata-0.1.0
738    first: "matt"
739    last: "butcher"
740    nick: "technosophos"
741  annotations:
742    "destination": "archive"
743    "format": "bio"
744    "helm.sh/hook": "pre-install"
745---
746metadata:
747  name: Zeus
748  labels:
749    app.kubernetes.io/name: metadata
750    app.kubernetes.io/managed-by: "Helm"
751    app.kubernetes.io/instance: "RELEASE-NAME"
752    helm.sh/chart: metadata-0.1.0
753  annotations:
754```
755
756Most of the common templates that define a resource type (e.g. `common.configmap`
757or `common.job`) use this to generate the metadata, which means they inherit
758the same `labels`, `annotations`, `nameOverride`, and `hook` fields.
759
760### `common.labelize`
761
762`common.labelize` turns a map into a set of labels.
763
764Example template:
765
766```yaml
767{{- $map := dict "first" "1" "second" "2" "third" "3" -}}
768{{- template "common.labelize" $map -}}
769```
770
771Example output:
772
773```yaml
774first: "1"
775second: "2"
776third: "3"
777```
778
779### `common.labels.standard`
780
781`common.labels.standard` prints the standard set of labels.
782
783Example usage:
784
785```
786{{ template "common.labels.standard" . }}
787```
788
789Example output:
790
791```yaml
792app.kubernetes.io/name: labelizer
793app.kubernetes.io/managed-by: "Tiller"
794app.kubernetes.io/instance: "RELEASE-NAME"
795helm.sh/chart: labelizer-0.1.0
796```
797
798### `common.hook`
799
800The `common.hook` template is a convenience for defining hooks.
801
802Example template:
803
804```yaml
805{{ template "common.hook" "pre-install,post-install" }}
806```
807
808Example output:
809
810```yaml
811"helm.sh/hook": "pre-install,post-install"
812```
813
814### `common.chartref`
815
816The `common.chartref` helper prints the chart name and version, escaped to be
817legal in a Kubernetes label field.
818
819Example template:
820
821```yaml
822chartref: {{ template "common.chartref" . }}
823```
824
825For the chart `foo` with version `1.2.3-beta.55+1234`, this will render:
826
827```yaml
828chartref: foo-1.2.3-beta.55_1234
829```
830
831(Note that `+` is an illegal character in label values)
832