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 | |
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 | |
| ingress.hosts | List of hostnames to be used in the Ingress resource | |
| ingress.tls | Configuration for TLS termination in the Ingress resource | |
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 | |
Defines a Role with specific permissions in a namespace |
| rbac/rolebinding.yaml | |
Binds a Role to a ServiceAccount in a namespace |
| rbac/clusterrole.yaml | |
Defines a ClusterRole with permissions across all namespaces |
| rbac/clusterrolebinding.yaml | |
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 | |
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 |
|
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.