Skip to main content

Creating Template Files

1. Understanding Template Syntax

Feature Description Example
Template Actions Control flow and variable interpolation in templates {{ .Values.key }}
Template Functions Functions to manipulate data within templates {{ .Values.key | upper }}
Template Comments Comments in templates that are not rendered {{/* This is a comment */}}

Example: Basic Template Syntax

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-config
data:
  config.yaml: |
    server:
      port: {{ .Values.server.port }}
      host: {{ .Values.server.host }}

Example: Using Template Functions

apiVersion: v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
Note: Template syntax uses Go template engine. All values are accessed via .Values, and release information is available through .Release.

2. Creating Deployment Template

Property Value Description
apiVersion apps/v1 Kubernetes API version for Deployment resource
kind Deployment Type of Kubernetes resource
metadata.name {{ include "myapp.fullname" . }} Unique name for the deployment
spec.replicas {{ .Values.replicaCount }} Number of pod replicas to run
spec.selector.matchLabels {app.kubernetes.io/name: {{ include "myapp.name" . }}, app.kubernetes.io/instance: {{ .Release.Name }}} Labels used to identify pods managed by this deployment
spec.template.metadata.labels {app.kubernetes.io/name: {{ include "myapp.name" . }}, app.kubernetes.io/instance: {{ .Release.Name }}} Labels applied to pods created by this deployment
spec.template.spec.containers[0].name {{ include "myapp.name" . }} Name of the container inside pod
spec.template.spec.containers[0].image {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }} Container image to use for the pod
spec.template.spec.containers[0].ports.containerPort {{ .Values.service.port }} Port exposed by the container

Example: Basic Deployment Template

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ include "myapp.name" . }}
      app.kubernetes.io/instance: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "myapp.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
    spec:
      containers:
        - name: {{ include "myapp.name" . }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          ports:
            - containerPort: {{ .Values.service.port }}

3. Creating Service Template

Field Description Example
apiVersion API version of the Service resource v1
kind Kind of the Kubernetes resource Service
metadata.name Name of the Service {{ include "myapp.fullname" . }}
spec.type Type of the Service (ClusterIP, NodePort, LoadBalancer) ClusterIP
spec.selector Labels used to select pods "app.kubernetes.io/name": {{ include "myapp.name" . }}
spec.ports.port Port number to expose 80
spec.ports.targetPort Target port on the pod 8080

Example: Basic Service Template

apiVersion: v1
kind: Service
metadata:
  name: {{ include "myapp.fullname" . }}
spec:
  type: ClusterIP
  selector:
    app.kubernetes.io/name: {{ include "myapp.name" . }}
  ports:
    - port: 80
      targetPort: 8080
Note: The include function is used to reference values defined in values.yaml.

4. Creating ConfigMap Template

Field Description Example
apiVersion API version of the ConfigMap resource v1
kind Kind of the Kubernetes resource ConfigMap
metadata.name Name of the ConfigMap app-config
data Key-value pairs of configuration data
key1: value1
key2: value2

Example: Basic ConfigMap Template

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "myapp.fullname" . }}
data:
  config.yaml: |
    database:
      host: {{ .Values.database.host }}
      port: {{ .Values.database.port }}
Note: The data field supports both string values and multiline YAML/JSON content using the | syntax.

5. Creating Secret Template

Field Description Example
apiVersion API version of the Secret resource v1
kind Kind of the Kubernetes resource Secret
metadata.name Name of the secret my-secret
type Type of the secret (e.g., Opaque, kubernetes.io/tls) Opaque
data Map of key-value pairs for secret data (base64 encoded) { "password": "cGFzc3dvcmQ=" }

Example: Creating a Secret Template

apiVersion: v1
kind: Secret
metadata:
  name: {{ .Values.secretName }}
type: Opaque
data:
  password: {{ .Values.password | b64enc }}
Note: Secret data must be base64 encoded before being stored.

6. Creating Ingress Template

Field Description Example
ingress.enabled Enables or disables the creation of an Ingress resource false
ingress.annotations Annotations to be added to the Ingress resource
{
  "kubernetes.io/ingress.class": "nginx",
  "nginx.ingress.kubernetes.io/rewrite-target": "/"
}
ingress.hosts List of hostnames to be used in the Ingress resource
[
  {
    "host": "myapp.example.com",
    "paths": [
      {
        "path": "/",
        "pathType": "Prefix"
      }
    ]
  }
]
ingress.tls Configuration for TLS termination in the Ingress resource
[
  {
    "secretName": "myapp-tls",
    "hosts": ["myapp.example.com"]
  }
]

Example: Ingress Template

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "myapp.fullname" . }}
  annotations:
    {{- toYaml .Values.ingress.annotations | nindent 4 }}
spec:
  ingressClassName: {{ .Values.ingress.className }}
  rules:
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ .path }}
            pathType: {{ .pathType }}
            backend:
              service:
                name: {{ include "myapp.fullname" $ }}
                port:
                  number: {{ $.Values.service.port }}
          {{- end }}
    {{- end }}
  {{- if .Values.ingress.tls }}
  tls:
    {{- toYaml .Values.ingress.tls | nindent 4 }}
  {{- end }}

7. Creating ServiceAccount Template

Property Value Description
apiVersion v1 API version of the ServiceAccount resource
kind ServiceAccount Kind of the Kubernetes resource
metadata.name {{ include "myapp.fullname" . }} Name of the ServiceAccount, typically derived from the chart name
metadata.namespace {{ .Release.Namespace }} Namespace where the ServiceAccount will be created
metadata.labels {{ include "myapp.labels" . }} Labels to apply to the ServiceAccount

Example: ServiceAccount Template

apiVersion: v1
kind: ServiceAccount
metadata:
  name: {{ include "myapp.fullname" . }}
  namespace: {{ .Release.Namespace }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
Note: The ServiceAccount is often used in conjunction with Role or ClusterRole to define permissions for pods or controllers.

8. Creating RBAC Templates

Template File Content Description
rbac/role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: {{ .Values.namespace }}
  name: {{ .Values.role.name }}
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
Defines a Role with specific permissions in a namespace
rbac/rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: {{ .Values.roleBinding.name }}
  namespace: {{ .Values.namespace }}
subjects:
- kind: ServiceAccount
  name: {{ .Values.serviceAccount.name }}
  namespace: {{ .Values.namespace }}
roleRef:
  kind: Role
  name: {{ .Values.role.name }}
  apiGroup: rbac.authorization.k8s.io
Binds a Role to a ServiceAccount in a namespace
rbac/clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: {{ .Values.clusterRole.name }}
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]
Defines a ClusterRole with permissions across all namespaces
rbac/clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: {{ .Values.clusterRoleBinding.name }}
subjects:
- kind: ServiceAccount
  name: {{ .Values.serviceAccount.name }}
  namespace: {{ .Values.namespace }}
roleRef:
  kind: ClusterRole
  name: {{ .Values.clusterRole.name }}
  apiGroup: rbac.authorization.k8s.io
Binds a ClusterRole to a ServiceAccount across all namespaces

Example: RBAC Configuration in values.yaml

namespace: production
role:
  name: pod-reader
serviceAccount:
  name: app-sa
clusterRole:
  name: node-reader
clusterRoleBinding:
  name: node-reader-binding
Note: RBAC templates should be customized according to the specific permissions required by your application.

9. Creating PersistentVolumeClaim Template

Field Description Example
apiVersion API version of the PersistentVolumeClaim resource v1
kind Kind of the Kubernetes resource PersistentVolumeClaim
metadata.name Name of the PersistentVolumeClaim data-pvc
spec.accessModes Access mode for the volume ["ReadWriteOnce"]
spec.resources.requests.storage Storage size requested 10Gi
spec.storageClassName StorageClass to use for dynamic provisioning standard

Example: PersistentVolumeClaim Template

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ .Values.persistence.name }}
spec:
  accessModes:
    - {{ .Values.persistence.accessMode }}
  resources:
    requests:
      storage: {{ .Values.persistence.size }}
  {{- if .Values.persistence.storageClass }}
  storageClassName: {{ .Values.persistence.storageClass }}
  {{- end }}

10. Using Template Comments ({{/* */}})

Template comments in Helm charts are used to add explanatory notes or disable parts of a template without affecting the rendered output. These comments are not included in the final rendered Kubernetes manifests.

Feature Description Example
Template Comment Syntax Used to write comments in Helm templates {{/* This is a comment */}}
Usage Comments are ignored during rendering
{{/* This comment will not appear in the output */}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-config

Example: Using Template Comments

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "myapp.fullname" . }}
  labels:
    {{- include "myapp.labels" . | nindent 4 }}
{{/* This comment explains the purpose of the following section */}}
data:
  config.yaml: |
    database:
      host: {{ .Values.database.host }}
      port: {{ .Values.database.port }}
{{/* End of config section */}}

11. Using Multi-Document Templates

Helm charts can contain multiple Kubernetes resource files in a single template file, allowing for more complex deployments. These multi-document templates are defined using the --- separator between each document.

Template Type Description Usage
Multi-document YAML Multiple Kubernetes resources defined in a single file using --- separators
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - port: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app

Example: Multi-Document Template Usage

apiVersion: v1
kind: Service
metadata:
  name: {{ include "myapp.fullname" . }}
spec:
  selector:
    app: {{ include "myapp.name" . }}
  ports:
    - port: 80
      targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ include "myapp.name" . }}
  template:
    metadata:
      labels:
        app: {{ include "myapp.name" . }}
    spec:
      containers:
        - name: {{ include "myapp.name" . }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: 8080
Note: When using multi-document templates, ensure that each document is valid YAML and properly separated by --- lines. Helm will process each document independently.
Warning: Be cautious when using multi-document templates with complex logic or conditional rendering, as it can make debugging more difficult.

Was this article helpful?