Helm Package Manager Installation and Usage
Helm is the package manager for Kubernetes, providing a standardized way to define, install, and manage Kubernetes applications. It simplifies complex deployments by bundling manifests, configurations, and dependencies into reusable packages called Charts. This guide covers installation, repository management, chart deployment, and creating custom charts for your Kubernetes infrastructure.
Table of Contents
- Installation
- Helm Architecture
- Repository Management
- Working with Charts
- Custom Chart Creation
- Helm Operations
- Best Practices
- Conclusion
Installation
Prerequisites
Before installing Helm, ensure you have:
- Kubernetes cluster running (v1.19 or later recommended)
- kubectl configured and working properly
- curl or wget installed
Installing Helm 3
Helm 3 is the current version with significant improvements over Helm 2, including removal of Tiller.
Using the official installation script:
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
Verify the installation:
helm version
Expected output:
version.BuildInfo{Version:"v3.14.0", GitCommit:"..."}
Manual Installation
Download the binary directly:
# Set variables
HELM_VERSION="v3.14.0"
OS="linux"
ARCH="amd64"
# Download
wget https://get.helm.sh/helm-${HELM_VERSION}-${OS}-${ARCH}.tar.gz
# Extract
tar -zxvf helm-${HELM_VERSION}-${OS}-${ARCH}.tar.gz
# Move to PATH
sudo mv ${OS}-${ARCH}/helm /usr/local/bin/
# Verify
helm version
Using Package Managers
On Ubuntu/Debian:
curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
On macOS with Homebrew:
brew install helm
Helm Completion
For bash:
helm completion bash | sudo tee /etc/bash_completion.d/helm
For zsh:
helm completion zsh | sudo tee /usr/share/zsh/site-functions/_helm
Helm Architecture
Core Components
Charts: Collections of templates and values that define Kubernetes resources. Charts are essentially parameterized Kubernetes manifests.
Releases: Instances of charts deployed to a cluster. Each release has a unique name and version.
Templates: Go template files that generate Kubernetes manifests by combining templates with values.
Values: Configuration data that parameterizes charts, allowing customization without modifying the chart itself.
Directory Structure
A typical Helm chart structure:
my-chart/
├── Chart.yaml # Chart metadata
├── values.yaml # Default configuration values
├── charts/ # Dependent charts
├── templates/ # Kubernetes manifest templates
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # Template helpers
│ └── NOTES.txt # Deployment notes
├── README.md # Chart documentation
└── .helmignore # Files to ignore when packaging
Repository Management
Adding Repositories
Add the official Helm Hub repository:
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add jetstack https://charts.jetstack.io
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
Listing Repositories
helm repo list
Searching Charts
Search for available charts:
helm search repo mysql
helm search repo nginx --versions
helm search hub postgresql
Updating Repository Cache
helm repo update
This updates your local cache of chart information. Always run this before searching or installing charts.
Removing Repositories
helm repo remove stable
Working with Charts
Installing Charts
Basic installation:
helm install my-release bitnami/mysql
Specify namespace:
helm install my-release bitnami/mysql --namespace data-layer --create-namespace
Customizing Values
Override values during installation:
helm install my-release bitnami/mysql \
--set auth.rootPassword=MyPassword123 \
--set primary.persistence.enabled=true \
--set primary.persistence.size=20Gi
Using a values file:
helm install my-release bitnami/mysql -f values-prod.yaml
Example values file:
# values-prod.yaml
auth:
rootPassword: "SecurePassword123"
database: production_db
username: produser
password: "ProdUserPass456"
primary:
persistence:
enabled: true
size: 50Gi
storageClass: fast-ssd
resources:
limits:
memory: "2Gi"
cpu: "1"
requests:
memory: "1Gi"
cpu: "500m"
replica:
replicaCount: 2
persistence:
enabled: true
size: 50Gi
Listing Releases
helm list
helm list -A # All namespaces
helm list -n production
Getting Release Information
helm status my-release
helm get values my-release
helm get manifest my-release
Custom Chart Creation
Scaffolding a New Chart
Create a new chart structure:
helm create my-web-app
This generates a complete chart template with examples.
Chart.yaml Metadata
Define chart metadata:
apiVersion: v2
name: my-web-app
description: A Helm chart for deploying a web application
type: application
version: 1.0.0
appVersion: "2.1.0"
keywords:
- web
- application
home: https://example.com
sources:
- https://github.com/example/my-web-app
maintainers:
- name: DevOps Team
email: [email protected]
Creating Templates
Deployment template (templates/deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-web-app.fullname" . }}
labels:
{{- include "my-web-app.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-web-app.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "my-web-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
resources:
{{- toYaml .Values.resources | nindent 12 }}
Service template (templates/service.yaml):
apiVersion: v1
kind: Service
metadata:
name: {{ include "my-web-app.fullname" . }}
labels:
{{- include "my-web-app.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "my-web-app.selectorLabels" . | nindent 4 }}
Default Values
values.yaml configuration:
replicaCount: 3
image:
repository: my-registry.azurecr.io/my-web-app
pullPolicy: IfNotPresent
tag: "1.0.0"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/metrics"
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
service:
type: ClusterIP
port: 80
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hosts:
- host: "myapp.example.com"
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts:
- myapp.example.com
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 80
Validating Charts
helm lint my-web-app
Packaging Charts
helm package my-web-app
This creates my-web-app-1.0.0.tgz ready for distribution.
Helm Operations
Upgrading Releases
helm upgrade my-release bitnami/mysql \
--set auth.rootPassword=NewPassword123
Dry-run before upgrade:
helm upgrade my-release bitnami/mysql --dry-run --debug
Rolling Back Releases
View release history:
helm history my-release
Rollback to previous release:
helm rollback my-release
Rollback to specific revision:
helm rollback my-release 2
Uninstalling Releases
helm uninstall my-release
Keep release history:
helm uninstall my-release --keep-history
Testing Charts
helm test my-release
Debugging
Get rendered templates without installing:
helm template my-release bitnami/mysql
Install with debug output:
helm install my-release bitnami/mysql --debug
Best Practices
Version Management
Always pin chart versions in production:
helm install my-release bitnami/mysql --version 11.3.4
Values Organization
Use multiple values files for different environments:
# Development
helm install dev-release my-chart -f values-base.yaml -f values-dev.yaml
# Production
helm install prod-release my-chart -f values-base.yaml -f values-prod.yaml
Security Considerations
Store sensitive values in Kubernetes Secrets:
kubectl create secret generic app-secrets \
--from-literal=db-password=SecurePass123 \
--from-literal=api-key=ApiKey456
helm install my-release my-chart \
--set-string externalSecrets.dbPassword='$db-password' \
--set-string externalSecrets.apiKey='$api-key'
Testing and Validation
Before production deployment:
helm lint my-chart
helm template my-release my-chart --validate
helm install my-release my-chart --dry-run --debug
Documentation
Document your charts thoroughly:
# README.md included in chart
# NOTES.txt for post-install information
# values.yaml with comments explaining each option
Conclusion
Helm is essential for managing Kubernetes deployments at scale. Mastering Helm enables you to standardize application deployment, maintain consistency across environments, and reduce manual configuration errors. By following these practices for repository management, custom chart creation, and deployment operations, you'll build a robust and maintainable Kubernetes infrastructure on your VPS or baremetal servers. Regularly update your charts, maintain clear documentation, and implement proper version control to ensure smooth operations and easy rollbacks when needed.


