Session 2: Creating and Hosting Custom Helm Charts
π― Session 2: Creating and Hosting Custom Helm Charts
In this session, you’ll learn to:
- β Create your own Helm charts from scratch
- β Customize templates and use values effectively
- β
Understand and use
_helpers.tpl - β Host charts on GitHub as a Helm repository
- β Apply real-world scenarios (Ingress, ConfigMap, HPA)
π οΈ Step 1: Create a Custom Chart
helm create nginx-demo
cd nginx-demoThis creates the following structure:
nginx-demo/
βββ charts/
βββ Chart.yaml
βββ templates/
β βββ deployment.yaml
β βββ _helpers.tpl
β βββ hpa.yaml
β βββ ingress.yaml
β βββ service.yaml
β βββ configmap.yaml
β βββ tests/
βββ values.yamlπ What is _helpers.tpl?
_helpers.tpl is a special file used to define reusable template snippets using Go’s template syntax. It’s where you can define helper functions like naming conventions or labels, which you can include in other templates using {{ include "name" . }}.
β
Example: _helpers.tpl
{{- define "nginx-demo.name" -}}
nginx
{{- end }}
{{- define "nginx-demo.fullname" -}}
{{ .Release.Name }}-nginx
{{- end }}
{{- define "nginx-demo.labels" -}}
app.kubernetes.io/name: {{ include "nginx-demo.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "nginx-demo.serviceAccountName" -}}
{{- if .Values.serviceAccount.name }}
{{ .Values.serviceAccount.name }}
{{- else }}
{{ include "nginx-demo.fullname" . }}
{{- end }}
{{- end }}π Usage in Other Templates
metadata:
name: {{ include "nginx-demo.fullname" . }}
labels:
{{- include "nginx-demo.labels" . | nindent 4 }}This avoids duplication and keeps your chart DRY (Don’t Repeat Yourself).
π¦ Custom values.yaml
replicaCount: 2
image:
repository: nginx
pullPolicy: IfNotPresent
tag: "1.25.2"
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: "nginx"
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
hosts:
- host: nginx.local
paths:
- path: /
pathType: Prefix
config:
message: "Welcome to Helm-powered NGINX!"
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
targetCPUUtilizationPercentage: 70
resources: {}
nodeSelector: {}
tolerations: []
affinity: {}βοΈ Templates Overview
πΈ deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "nginx-demo.fullname" . }}
labels:
{{- include "nginx-demo.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ include "nginx-demo.name" . }}
template:
metadata:
labels:
app: {{ include "nginx-demo.name" . }}
spec:
containers:
- name: nginx
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 80
env:
- name: APP_MESSAGE
valueFrom:
configMapKeyRef:
name: {{ include "nginx-demo.fullname" . }}
key: appMessageπΈ service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "nginx-demo.fullname" . }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: 80
selector:
app: {{ include "nginx-demo.name" . }}πΈ configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "nginx-demo.fullname" . }}
data:
appMessage: {{ .Values.config.message | quote }}πΈ ingress.yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "nginx-demo.fullname" . }}
annotations:
{{- range $key, $value := .Values.ingress.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
ingressClassName: {{ .Values.ingress.className }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "nginx-demo.fullname" $ }}
port:
number: {{ $.Values.service.port }}
{{- end }}
{{- end }}
{{- end }}πΈ hpa.yaml
{{- if .Values.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "nginx-demo.fullname" . }}
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "nginx-demo.fullname" . }}
minReplicas: {{ .Values.autoscaling.minReplicas }}
maxReplicas: {{ .Values.autoscaling.maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}π§ͺ Run the Chart
helm install my-nginx ./nginx-demo
helm test my-nginxπ Host Helm Charts on GitHub
Step 1: Create and Package
mkdir helm-registry && cd helm-registry
helm create order
helm create delivery
helm package order
helm package delivery
helm repo index .Step 2: Push to GitHub
git init
git remote add origin https://github.com/<your-username>/helm-registry.git
git add .
git commit -m "Add Order and Delivery Charts"
git push -u origin mainEnable GitHub Pages on the repository (Settings β Pages).
Step 3: Add and Use Repo
helm repo add teamcharts https://<your-username>.github.io/helm-registry
helm repo update
helm install order-app teamcharts/order
helm install delivery-app teamcharts/deliveryβ Summary
| Topic | Description |
|---|---|
_helpers.tpl | Defines reusable template logic (naming, labels, etc.) |
values.yaml | Central place for all configuration values |
| Templates | Refer to values and helpers using Go templating |
| Hosting | GitHub Pages serves .tgz charts and index.yaml as a repo |
| Real-World Additions | ConfigMap, Ingress, Autoscaling (HPA) support |