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