Back to Blog
DevOps

Helm Essentials: Streamlining Kubernetes Application Deployment

N
NeoNube Team
Cloud Solutions Architects
January 22, 202510 min read
HelmKubernetesDevOpsCloud Native

Helm Essentials: Streamlining Kubernetes Application Deployment

Managing Kubernetes applications can quickly become overwhelming. Between deployment manifests, ConfigMaps, Secrets, Services, and Ingress rules, even a simple application might require dozens of YAML files. As your application portfolio grows, maintaining these configurations across multiple environments becomes a nightmare.

Enter Helm—the package manager that revolutionized how teams deploy and manage Kubernetes applications.

The Kubernetes Deployment Challenge

Before diving into Helm, let's understand the problems it solves.

The Traditional Kubernetes Deployment Workflow

Deploying a typical microservice to Kubernetes without Helm looks like this:

  1. Manually create and maintain separate YAML files for each resource
  2. Copy-paste configurations between environments (dev, staging, production)
  3. Manually update image tags, replica counts, and configuration values
  4. Apply resources in the correct order to avoid dependency issues
  5. Track which versions of manifests are deployed where
  6. Roll back by manually reverting to previous manifest versions

The Result: Error-prone deployments, configuration drift between environments, and significant operational overhead.

Common Pain Points

Configuration Management Complexity A typical application might have different configurations for:

  • Development (minimal resources, debug logging enabled)
  • Staging (moderate resources, performance testing enabled)
  • Production (auto-scaling, high availability, strict security policies)

Managing these variations manually leads to:

  • Copy-paste errors
  • Configuration drift
  • Inconsistent deployments
  • Difficult rollbacks

Version Control Challenges Without a packaging system, tracking application versions requires:

  • Manual tagging in Git
  • Complex directory structures
  • Custom scripting
  • Spreadsheet tracking (seriously, we've seen this)

Deployment Coordination Multi-component applications require precise orchestration:

  • Database migrations before application updates
  • Service dependencies during startup
  • Configuration updates synchronized with code changes
  • Graceful handling of stateful services

Introducing Helm: The Kubernetes Package Manager

Helm addresses these challenges through a simple but powerful concept: packaging all Kubernetes resources for an application into a single, versioned, configurable unit called a chart.

Think of Helm as the APT, YUM, or Homebrew for Kubernetes—it provides:

  • Package Management: Bundle all resources together
  • Templating: Parameterize configurations for different environments
  • Versioning: Track and rollback application versions
  • Distribution: Share applications through chart repositories
  • Dependency Management: Handle complex multi-chart applications

Core Helm Concepts

1. Charts: The Packaging Unit

A Helm chart is a collection of files that describe a complete Kubernetes application. Charts follow a standardized structure:

mychart/
├── Chart.yaml          # Chart metadata
├── values.yaml         # Default configuration values
├── charts/            # Dependency charts
├── templates/         # Kubernetes resource templates
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   └── _helpers.tpl
└── .helmignore        # Files to exclude

Chart.yaml Example:

apiVersion: v2
name: myapp
description: A production-ready microservice
version: 1.0.0
appVersion: "2.3.1"
keywords:
- microservice
- api
maintainers:
- name: NeoNube Team
email: team@neonube.io

Key Fields:

  • version: Chart version (follows semantic versioning)
  • appVersion: Application version being deployed
  • dependencies: Other charts this chart depends on

2. Values: Configuration Parameterization

Values files define configurable parameters. The values.yaml provides defaults, which can be overridden per environment.

values.yaml:

replicaCount: 3
 
image:
repository: myregistry/myapp
tag: "2.3.1"
pullPolicy: IfNotPresent
 
service:
type: ClusterIP
port: 80
 
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
 
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilization: 70

Environment-Specific Overrides:

Production values (values-prod.yaml):

replicaCount: 5
 
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
 
autoscaling:
minReplicas: 5
maxReplicas: 20

3. Templates: Dynamic Resource Generation

Templates use Go templating to generate Kubernetes manifests from values:

templates/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
resources:
{{- toYaml .Values.resources | nindent 10 }}

4. Releases: Deployed Instances

When you install a chart, Helm creates a release—a specific instance of that chart deployed to your cluster.

Each release:

  • Has a unique name
  • Tracks revision history
  • Maintains its own configuration
  • Can be independently upgraded or rolled back

This allows you to deploy the same chart multiple times with different configurations:

  • myapp-dev: Development release
  • myapp-staging: Staging release
  • myapp-prod: Production release

5. Repositories: Chart Distribution

Helm repositories are HTTP servers that host chart packages. They work like Docker registries but for Helm charts.

Popular Public Repositories:

  • Artifact Hub (https://artifacthub.io): Central hub for Helm charts
  • Bitnami: Production-ready application charts
  • Prometheus Community: Monitoring and observability charts

Getting Started with Helm

Installation

Install Helm v3 (latest version):

# 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

Creating Your First Chart

Generate a new chart:

helm create myapp

This creates a chart with sensible defaults for a web application.

Customize the chart:

  1. Update Chart.yaml with your application details
  2. Modify values.yaml with your default configuration
  3. Edit templates to match your Kubernetes resources
  4. Add any additional resources your application needs

Installing a Chart

Deploy your application:

# Basic installation
helm install myapp-dev ./myapp
 
# With custom values
helm install myapp-prod ./myapp -f values-prod.yaml
 
# Override specific values
helm install myapp-staging ./myapp \
--set replicaCount=5 \
--set image.tag=2.4.0

Managing Releases

List all releases:

helm list

Check release status:

helm status myapp-prod

View release history:

helm history myapp-prod

Upgrade a release:

helm upgrade myapp-prod ./myapp -f values-prod.yaml

Rollback to previous version:

# Rollback to previous revision
helm rollback myapp-prod
 
# Rollback to specific revision
helm rollback myapp-prod 3

Uninstall a release:

helm uninstall myapp-dev

Advanced Helm Techniques

1. Template Debugging

Before deploying, verify generated manifests:

# Render templates locally
helm template myapp ./myapp
 
# Render with custom values
helm template myapp ./myapp -f values-prod.yaml
 
# Debug mode (shows more details)
helm template myapp ./myapp --debug
 
# Dry-run deployment
helm install myapp-test ./myapp --dry-run --debug

2. Chart Dependencies

Declare dependencies in Chart.yaml:

dependencies:
- name: postgresql
version: 12.1.0
repository: https://charts.bitnami.com/bitnami
- name: redis
version: 17.3.0
repository: https://charts.bitnami.com/bitnami

Install dependencies:

helm dependency update ./myapp

Override dependency values:

# values.yaml
postgresql:
auth:
username: myapp
database: myapp_db
primary:
resources:
requests:
memory: 256Mi
cpu: 250m

3. Hooks: Lifecycle Management

Hooks run at specific points in the release lifecycle:

# templates/job-migrate-db.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-migrate
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["./migrate-db.sh"]
restartPolicy: Never

Available Hooks:

  • pre-install: Before resources are installed
  • post-install: After all resources are installed
  • pre-upgrade: Before upgrade
  • post-upgrade: After upgrade
  • pre-rollback: Before rollback
  • post-rollback: After rollback
  • pre-delete: Before deletion

4. Chart Testing

Add tests to validate deployments:

# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: {{ include "myapp.fullname" . }}-test
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "myapp.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never

Run tests:

helm test myapp-prod

Best Practices for Production

1. Chart Organization

Keep Charts Focused

  • One chart per logical application
  • Use dependencies instead of monolithic charts
  • Separate infrastructure (databases, caches) from applications

Use Meaningful Names

  • Charts: mycompany-servicename
  • Releases: servicename-environment
  • Resources: Use chart helpers for consistent naming

2. Values Management

Structure Values Logically

# Group related settings
image:
repository: myapp
tag: 1.0.0
 
service:
type: ClusterIP
port: 80
 
ingress:
enabled: true
className: nginx
hosts:
- host: myapp.example.com

Document All Values Include comments explaining each value:

# Number of pod replicas (3-5 recommended for production)
replicaCount: 3
 
# Container image configuration
image:
# Image repository (without tag)
repository: myregistry/myapp
# Image tag (usually matches appVersion in Chart.yaml)
tag: "1.0.0"

3. Security Practices

Use Secrets Properly Never commit secrets to values files:

# Bad - Don't do this
database:
password: "hardcodedPassword123"
 
# Good - Reference existing secrets
database:
existingSecret: myapp-db-secret
secretKey: password

Implement RBAC Include appropriate RBAC resources:

# templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "myapp.fullname" . }}

4. Version Management

Follow Semantic Versioning

  • MAJOR: Breaking changes
  • MINOR: New features (backwards compatible)
  • PATCH: Bug fixes

Keep appVersion Synchronized Update both chart version and appVersion together:

version: 1.2.0 # Chart version
appVersion: "2.3.1" # Application version

5. Testing Strategy

Multi-Level Testing

  1. Lint charts:
helm lint ./myapp
  1. Template validation:
helm template myapp ./myapp | kubectl apply --dry-run=client -f -
  1. Integration tests:
helm install myapp-test ./myapp
helm test myapp-test
helm uninstall myapp-test
  1. Automated CI/CD: Include Helm operations in your pipeline:
# .github/workflows/helm-deploy.yml
- name: Lint chart
run: helm lint ./charts/myapp
 
- name: Deploy to staging
run: |
helm upgrade --install myapp-staging ./charts/myapp \
-f ./charts/myapp/values-staging.yaml \
--wait --timeout 5m

Common Pitfalls to Avoid

1. Over-Templating

Problem: Making everything configurable creates complexity.

Solution: Template only what actually varies between deployments. Keep it simple.

2. Ignoring Chart Dependencies

Problem: Not managing dependencies properly leads to version conflicts.

Solution: Lock dependency versions and update them deliberately:

helm dependency update ./myapp
git add Chart.lock

3. Skipping Validation

Problem: Deploying untested charts causes production issues.

Solution: Always use --dry-run and --debug before actual deployment:

helm upgrade myapp-prod ./myapp --dry-run --debug

4. Inadequate Rollback Planning

Problem: Not testing rollback procedures until an emergency.

Solution: Practice rollbacks in staging:

# Deploy new version
helm upgrade myapp-staging ./myapp
 
# Test rollback
helm rollback myapp-staging
 
# Verify functionality
helm test myapp-staging

Helm in Action: Real-World Workflow

Here's how a typical production deployment workflow looks with Helm:

1. Development

# Create feature branch
git checkout -b feature/new-api
 
# Update application code
# Update Chart.yaml and values.yaml if needed
 
# Test locally
helm template myapp ./charts/myapp --debug
helm install myapp-local ./charts/myapp -f values-dev.yaml
 
# Run integration tests
helm test myapp-local

2. Staging Deployment

# Deploy to staging
helm upgrade --install myapp-staging ./charts/myapp \
-f values-staging.yaml \
--wait --timeout 10m
 
# Verify deployment
kubectl get pods -l app=myapp
helm status myapp-staging
 
# Run smoke tests
./scripts/smoke-tests.sh staging

3. Production Deployment

# Create release
git tag -a v1.2.0 -m "Release v1.2.0"
 
# Dry-run production deploy
helm upgrade myapp-prod ./charts/myapp \
-f values-prod.yaml \
--dry-run --debug
 
# Deploy to production
helm upgrade myapp-prod ./charts/myapp \
-f values-prod.yaml \
--wait --timeout 15m
 
# Monitor deployment
kubectl rollout status deployment/myapp-prod

4. Rollback (if needed)

# Check history
helm history myapp-prod
 
# Rollback to previous version
helm rollback myapp-prod
 
# Or rollback to specific revision
helm rollback myapp-prod 5

Conclusion: Helm's Impact on Kubernetes Operations

Helm transforms Kubernetes application management from a complex manual process into a streamlined, automated workflow. By standardizing packaging, versioning, and deployment practices, Helm enables teams to:

Increase Deployment Velocity

  • Deploy complex applications in seconds instead of hours
  • Reduce deployment errors by 80%+
  • Enable self-service deployments for development teams

Improve Reliability

  • Consistent deployments across all environments
  • Simple, tested rollback procedures
  • Reduced configuration drift

Reduce Operational Overhead

  • Eliminate manual YAML management
  • Reuse charts across projects
  • Share best practices through chart repositories

Scale Operations

  • Manage hundreds of applications consistently
  • Support multiple environments effortlessly
  • Enable GitOps workflows

Next Steps: Mastering Helm

Ready to implement Helm in your organization? Here's your action plan:

  1. Start Small: Convert one simple application to a Helm chart
  2. Build Chart Library: Create charts for your core applications
  3. Establish Practices: Document your chart standards and workflows
  4. Implement CI/CD: Integrate Helm into your deployment pipelines
  5. Train Teams: Share knowledge and best practices across your organization

At NeoNube, we help organizations successfully adopt Helm and modernize their Kubernetes deployment practices. Our cloud-native experts can:

  • Assess your current deployment workflows
  • Design Helm chart architectures for your applications
  • Implement automated deployment pipelines
  • Train your teams on Helm best practices
  • Provide ongoing support and optimization

Contact us to accelerate your Kubernetes journey with Helm.

Ready to Optimize Your Cloud Infrastructure?

Let our experts help you reduce costs, improve performance, and enhance security.

Schedule a Consultation