Lab 06: Helm Charts
Objectives
- ✅ Understand Helm chart structure
- ✅ Create a Helm chart from scratch
- ✅ Template values and iterate through loops
- ✅ Deploy with Helm
- ✅ Upgrade and rollback releases
- ✅ Manage dependencies
Prerequisites
- Lab 05 complete
- Helm CLI installed
- ~2 hours
Step 1: Create Chart from Scratch
# Create new chart
helm create myapp-chart
# Explore structure
cd myapp-chart
tree
# Should show:
# ├── Chart.yaml
# ├── values.yaml
# ├── templates/
# │ ├── deployment.yaml
# │ ├── service.yaml
# │ └── ...
Step 2: Edit Chart Metadata
Edit Chart.yaml:
apiVersion: v2
name: myapp
description: Sample app for learning Helm
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
- microservices
- kubernetes
- helm
maintainers:
- name: DevOps Team
email: devops@example.com
Step 3: Customize values.yaml
Edit values.yaml:
replicaCount: 3
image:
repository: YOUR_USERNAME/myapp
tag: "1.0.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 5000
ingress:
enabled: false
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
autoscaling:
enabled: false
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
config:
logLevel: INFO
environment: development
Step 4: Template deployment.yaml
Edit templates/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-api
labels:
app: {{ .Chart.Name }}
version: {{ .Chart.Version }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
labels:
app: {{ .Chart.Name }}
spec:
containers:
- name: api
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
env:
- name: LOG_LEVEL
value: {{ .Values.config.logLevel }}
- name: ENVIRONMENT
value: {{ .Values.config.environment }}
resources:
requests:
memory: "{{ .Values.resources.requests.memory }}"
cpu: "{{ .Values.resources.requests.cpu }}"
limits:
memory: "{{ .Values.resources.limits.memory }}"
cpu: "{{ .Values.resources.limits.cpu }}"
livenessProbe:
httpGet:
path: /health
port: {{ .Values.service.targetPort }}
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: {{ .Values.service.targetPort }}
initialDelaySeconds: 5
periodSeconds: 10
Step 5: Template service.yaml
Edit templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-api
spec:
type: {{ .Values.service.type }}
selector:
app: {{ .Chart.Name }}
ports:
- protocol: TCP
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
Step 6: Template YAML Preview
# See generated manifests before deploying
helm template myapp-release ./myapp-chart
# Validate syntax
helm lint ./myapp-chart
# Should show: 1 chart(s) linted, 0 error(s)
Step 7: Install Release
# Install with default values
helm install my-app ./myapp-chart
# Or with overrides
helm install my-app ./myapp-chart \
--set replicaCount=5 \
--set image.tag=2.0.0
# List releases
helm list
# Get release values
helm get values my-app
# Get generated manifests
helm get manifest my-app
Step 8: Upgrade Release
# Update image version
helm upgrade my-app ./myapp-chart --set image.tag=2.0.0
# Check status
helm status my-app
# View release history
helm history my-app
Step 9: Rollback Release
# Rollback to previous version
helm rollback my-app
# Or to specific revision
helm rollback my-app 1
# Verify
helm status my-app
Step 10: Environment-Specific Values
Create values-prod.yaml:
replicaCount: 10
image:
tag: "1.0.0"
resources:
requests:
memory: "512Mi"
cpu: "200m"
limits:
memory: "1Gi"
cpu: "1000m"
autoscaling:
enabled: true
maxReplicas: 30
config:
logLevel: ERROR
environment: production
Deploy with prod values:
helm install my-app ./myapp-chart -f values-prod.yaml
# Verify
kubectl get deployment my-app-api
# Should have 10 replicas
Validation
# Release exists and is deployed
helm list
# my-app should be DEPLOYED
# Pods running with correct image
kubectl get pods -o jsonpath='{.items[*].spec.containers[0].image}'
# Should show YOUR_USERNAME/myapp:1.0.0
# Service created
kubectl get svc my-app-api
# Upgrade worked
helm history my-app
# Should show multiple revisions
Challenge (Optional)
Add chart dependencies:
Create requirements.yaml (Helm 2) or Chart.yaml (Helm 3):
dependencies:
- name: postgresql
version: "11.x.x"
repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled
# Update dependencies
helm dependency update ./myapp-chart
# Now your chart includes PostgreSQL
helm install my-app ./myapp-chart \
--set postgresql.enabled=true \
--set postgresql.auth.password=mysecret
Cleanup
helm uninstall my-app
rm -rf myapp-chart/