Helm Deployment Guide
Helm provides a simple, template-based approach to deploying Greenfield Cluster. It's ideal for quick deployments and parameter-driven configuration management.
Overview
Helm is the package manager for Kubernetes, allowing you to define, install, and upgrade Kubernetes applications using charts.
Why Helm?
- ✅ Simple Configuration: Value-based parameter override
- ✅ One Command Deployment: Install everything at once
- ✅ Release Management: Built-in versioning and rollback
- ✅ Templating: Reusable chart templates
- ✅ Package Distribution: Easy sharing and distribution
Prerequisites
- Kubernetes cluster (v1.24+)
- Helm 3.0+ installed
- kubectl configured
- At least 8 CPU cores, 16GB RAM
Installing Helm
# macOS
brew install helm
# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Windows
choco install kubernetes-helm
# Verify installation
helm version
Quick Start
Basic Installation
Install Greenfield Cluster with default values:
Installation with Custom Values
Create a custom values file:
# my-values.yaml
redis:
replicas: 2
resources:
requests:
memory: "1Gi"
cpu: "500m"
postgres:
replicas: 3
storage:
size: "50Gi"
fastapi:
replicas: 5
image:
tag: "v2.0.0"
Install with custom values:
helm install greenfield helm/greenfield-cluster \
--namespace greenfield \
--create-namespace \
--values my-values.yaml
Installation with Inline Values
Override specific values inline:
helm install greenfield helm/greenfield-cluster \
--namespace greenfield \
--create-namespace \
--set redis.replicas=3 \
--set postgres.storage.size=100Gi \
--set fastapi.image.tag=v2.0.0
Chart Structure
helm/greenfield-cluster/
├── Chart.yaml # Chart metadata
├── values.yaml # Default values
├── values-dev.yaml # Development values
├── values-staging.yaml # Staging values
├── values-prod.yaml # Production values
├── templates/ # Template files
│ ├── NOTES.txt # Post-install notes
│ ├── _helpers.tpl # Template helpers
│ ├── namespace.yaml
│ ├── redis/
│ │ ├── deployment.yaml
│ │ ├── service.yaml
│ │ └── configmap.yaml
│ ├── postgres/
│ ├── mysql/
│ ├── mongodb/
│ ├── kafka/
│ ├── istio/
│ ├── otel-collector/
│ ├── jaeger/
│ ├── prometheus/
│ ├── grafana/
│ └── fastapi-app/
└── charts/ # Subchart dependencies
Configuration
Default Values
The values.yaml file contains all configurable parameters:
# Global settings
global:
namespace: greenfield
imageRegistry: docker.io
storageClass: standard
# Component enablement
components:
redis: true
postgres: true
mysql: true
mongodb: true
kafka: true
istio: true
otel: true
jaeger: true
prometheus: true
grafana: true
fastapi: true
# Redis configuration
redis:
enabled: true
replicas: 1
image:
repository: redis
tag: "7-alpine"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
persistence:
enabled: true
size: "10Gi"
# PostgreSQL configuration
postgres:
enabled: true
replicas: 1
image:
repository: postgres
tag: "15-alpine"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
storage:
size: "20Gi"
database: "myapp"
username: "appuser"
# FastAPI application
fastapi:
enabled: true
replicas: 2
image:
repository: fastapi-example
tag: "latest"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8000
ingress:
enabled: false
host: "api.example.com"
tls:
enabled: false
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "1000m"
Environment-Specific Values
Development Values
values-dev.yaml:
# Minimal resources for development
redis:
replicas: 1
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "250m"
postgres:
replicas: 1
storage:
size: "10Gi"
fastapi:
replicas: 1
ingress:
enabled: false
Staging Values
values-staging.yaml:
# Production-like configuration
redis:
replicas: 2
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
postgres:
replicas: 2
storage:
size: "50Gi"
fastapi:
replicas: 3
ingress:
enabled: true
host: "staging-api.example.com"
tls:
enabled: true
Production Values
values-prod.yaml:
# High availability configuration
redis:
replicas: 3
resources:
requests:
memory: "1Gi"
cpu: "1000m"
limits:
memory: "2Gi"
cpu: "2000m"
persistence:
size: "50Gi"
postgres:
replicas: 3
storage:
size: "100Gi"
backup:
enabled: true
mysql:
replicas: 3
storage:
size: "100Gi"
mongodb:
replicas: 3
storage:
size: "100Gi"
kafka:
replicas: 3
fastapi:
replicas: 5
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
targetCPUUtilizationPercentage: 70
ingress:
enabled: true
host: "api.example.com"
tls:
enabled: true
secretName: "api-tls"
podDisruptionBudget:
enabled: true
minAvailable: 2
Deployment Scenarios
Development Environment
helm install greenfield helm/greenfield-cluster \
--namespace greenfield-dev \
--create-namespace \
--values helm/greenfield-cluster/values-dev.yaml
Staging Environment
helm install greenfield helm/greenfield-cluster \
--namespace greenfield-staging \
--create-namespace \
--values helm/greenfield-cluster/values-staging.yaml
Production Environment
helm install greenfield helm/greenfield-cluster \
--namespace greenfield \
--create-namespace \
--values helm/greenfield-cluster/values-prod.yaml
Custom Configuration
Combine multiple values files:
helm install greenfield helm/greenfield-cluster \
--namespace greenfield \
--create-namespace \
--values helm/greenfield-cluster/values-prod.yaml \
--values my-custom-values.yaml
Component Selection
Enable/Disable Components
Disable components you don't need:
# my-values.yaml
components:
redis: true
postgres: true
mysql: false # Disable MySQL
mongodb: false # Disable MongoDB
kafka: true
istio: true
otel: true
jaeger: true
prometheus: true
grafana: true
fastapi: true
Or use inline flags:
helm install greenfield helm/greenfield-cluster \
--set mysql.enabled=false \
--set mongodb.enabled=false
Managing Releases
List Releases
# List all releases in all namespaces
helm list --all-namespaces
# List releases in specific namespace
helm list -n greenfield
Get Release Status
Get Release Values
# Show user-supplied values
helm get values greenfield -n greenfield
# Show all values (including defaults)
helm get values greenfield -n greenfield --all
Get Release Manifest
Release History
Upgrading Releases
Basic Upgrade
Upgrade with New Values
helm upgrade greenfield helm/greenfield-cluster \
--namespace greenfield \
--reuse-values \
--set fastapi.replicas=10
Force Upgrade
Force recreation of resources:
Atomic Upgrade
Rollback on failure:
Wait for Rollout
Wait for all pods to be ready:
Rollback
Rollback to Previous Version
Rollback to Specific Revision
# List history
helm history greenfield -n greenfield
# Rollback to specific revision
helm rollback greenfield 3 -n greenfield
Rollback with Cleanup
Uninstalling
Basic Uninstall
Keep History
Keep release history for potential rollback:
Wait for Deletion
Wait for all resources to be deleted:
Testing and Validation
Template Rendering
Preview generated manifests without installation:
Save output to file:
helm template greenfield helm/greenfield-cluster \
--namespace greenfield \
--values my-values.yaml > rendered.yaml
Dry Run
Simulate installation:
Linting
Validate chart for issues:
helm lint helm/greenfield-cluster
# With custom values
helm lint helm/greenfield-cluster --values my-values.yaml
Diff Changes
Use helm-diff plugin to see changes before upgrading:
# Install plugin (use specific version for security)
helm plugin install https://github.com/databus23/helm-diff --version v3.9.0
# Show diff
helm diff upgrade greenfield helm/greenfield-cluster \
--namespace greenfield \
--values my-values.yaml
GitOps Integration
ArgoCD
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: greenfield-cluster
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/yourusername/green_field_cluster
targetRevision: main
path: helm/greenfield-cluster
helm:
valueFiles:
- values-prod.yaml
parameters:
- name: fastapi.replicas
value: "5"
destination:
server: https://kubernetes.default.svc
namespace: greenfield
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
Flux CD
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: greenfield-cluster
namespace: flux-system
spec:
interval: 1m
url: https://github.com/yourusername/green_field_cluster
ref:
branch: main
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: greenfield-cluster
namespace: flux-system
spec:
interval: 10m
chart:
spec:
chart: ./helm/greenfield-cluster
sourceRef:
kind: GitRepository
name: greenfield-cluster
values:
fastapi:
replicas: 5
valuesFrom:
- kind: ConfigMap
name: greenfield-values
Advanced Configuration
Custom Templates
Override specific templates by creating custom values:
Dependencies
Add external chart dependencies:
# Chart.yaml
dependencies:
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
Update dependencies:
Hooks
Use Helm hooks for lifecycle management:
# templates/backup-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "greenfield.fullname" . }}-backup
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
containers:
- name: backup
image: backup-tool:latest
command: ["/backup.sh"]
Troubleshooting
Common Issues
Release already exists
# Uninstall first
helm uninstall greenfield -n greenfield
# Or use upgrade with --install flag
helm upgrade --install greenfield helm/greenfield-cluster
Failed to download chart
Values not applied
# Check merged values
helm get values greenfield -n greenfield --all
# Use --reuse-values cautiously
helm upgrade greenfield helm/greenfield-cluster --reuse-values=false
Timeout during installation
Incomplete deletion
# Force delete namespace
kubectl delete namespace greenfield --force --grace-period=0
# Check for stuck resources
kubectl api-resources --verbs=list --namespaced -o name \
| xargs -n 1 kubectl get --show-kind --ignore-not-found -n greenfield
Best Practices
- Version Control Values: Keep custom values files in Git
- Use Values Files: Prefer values files over --set for complex configs
- Environment Separation: Different values files per environment
- Test Locally: Use
helm templatebefore deploying - Atomic Upgrades: Use
--atomicflag for production - Resource Limits: Always set resource requests and limits
- Backup Before Upgrade: Backup data before major upgrades
- Monitor Rollouts: Watch pod status during deployments
Helm vs Kustomize
| Feature | Helm | Kustomize |
|---|---|---|
| Learning Curve | Lower | Higher |
| Configuration | Values-based | Patch-based |
| Templating | Go templates | No templating |
| GitOps | Via ArgoCD/Flux | Native support |
| Rollback | Built-in | Manual (via Git) |
| Best For | Quick deployments | Precise control |
Migration to Kustomize
To migrate from Helm to Kustomize:
-
Render templates:
-
Organize by component: Split into component directories
-
Create kustomization.yaml: Reference all components
-
Test deployment: