Module 2.2: Helm Package Manager
Complexity:
[MEDIUM]- Essential tool added to CKAD 2025Time to Complete: 45-55 minutes
Prerequisites: Module 2.1 (Deployments), understanding of YAML templates
Learning Outcomes
Section titled “Learning Outcomes”After completing this module, you will be able to:
- Deploy applications using
helm installwith custom values and namespace targeting - Create value overrides to customize chart behavior for different environments
- Debug failed Helm releases using
helm status,helm history, and rollback operations - Explain Helm chart structure including templates, values, and the release lifecycle
Why This Module Matters
Section titled “Why This Module Matters”Helm is the package manager for Kubernetes. Instead of managing dozens of YAML files, Helm bundles them into “charts” that can be installed, upgraded, and rolled back as a unit. The 2025 CKAD exam added Helm as a required skill.
You’ll encounter questions like:
- Install a chart from a repository
- Upgrade a release with new values
- Rollback a failed release
- List and inspect releases
- Create basic chart customizations
The App Store Analogy
Helm is like an app store for Kubernetes. Charts are apps—pre-packaged, tested, and ready to install. Just like you’d install Slack with one click instead of compiling it yourself, Helm lets you install complex applications (databases, monitoring stacks, web servers) with a single command. Values are like app settings—you customize behavior without modifying the app itself.
Helm Concepts
Section titled “Helm Concepts”Key Terminology
Section titled “Key Terminology”| Term | Description |
|---|---|
| Chart | Package of Kubernetes resources (like an app) |
| Release | Installed instance of a chart |
| Repository | Collection of charts (like apt repos) |
| Values | Configuration for customizing a chart |
| Revision | Version of a release after upgrade/rollback |
How Helm Works
Section titled “How Helm Works”Chart (template) + Values (config) = Release (running app)┌─────────────────────────────────────────────────────────┐│ Helm Workflow │├─────────────────────────────────────────────────────────┤│ ││ Repository Chart Release ││ ┌─────────┐ ┌─────────┐ ┌─────────┐ ││ │ bitnami │──────▶│ nginx │─────▶│ my-web │ ││ │ repo │ pull │ chart │install│ release │ ││ └─────────┘ └─────────┘ └─────────┘ ││ │ │ ││ ▼ ▼ ││ ┌─────────┐ ┌─────────┐ ││ │ values │ │ Pods │ ││ │ .yaml │ │Services │ ││ └─────────┘ │ConfigMaps│ ││ └─────────┘ │└─────────────────────────────────────────────────────────┘Helm Commands
Section titled “Helm Commands”Repository Management
Section titled “Repository Management”# Add a repositoryhelm repo add bitnami https://charts.bitnami.com/bitnami
# Add stable repohelm repo add stable https://charts.helm.sh/stable
# Update repository cachehelm repo update
# List repositorieshelm repo list
# Search for chartshelm search repo nginxhelm search repo bitnami/nginx
# Search with versionshelm search repo nginx --versionsInstalling Charts
Section titled “Installing Charts”# Install with default valueshelm install my-release bitnami/nginx
# Install in specific namespacehelm install my-release bitnami/nginx -n production
# Install and create namespacehelm install my-release bitnami/nginx -n production --create-namespace
# Install with custom values filehelm install my-release bitnami/nginx -f values.yaml
# Install with inline valueshelm install my-release bitnami/nginx --set replicaCount=3
# Install with multiple value overrideshelm install my-release bitnami/nginx \ --set replicaCount=3 \ --set service.type=NodePort
# Dry-run (see what would be created)helm install my-release bitnami/nginx --dry-run
# Generate name automaticallyhelm install bitnami/nginx --generate-nameListing Releases
Section titled “Listing Releases”# List releases in current namespacehelm list
# List in all namespaceshelm list -A
# List in specific namespacehelm list -n production
# List with statushelm list --all
# Filter by statushelm list --failedhelm list --pendingInspecting Charts and Releases
Section titled “Inspecting Charts and Releases”# Show chart infohelm show chart bitnami/nginx
# Show default valueshelm show values bitnami/nginx
# Show all infohelm show all bitnami/nginx
# Get release valueshelm get values my-release
# Get all release infohelm get all my-release
# Get release manifest (rendered YAML)helm get manifest my-release
# Get release historyhelm history my-releaseUpgrading Releases
Section titled “Upgrading Releases”# Upgrade with new valueshelm upgrade my-release bitnami/nginx --set replicaCount=5
# Upgrade with values filehelm upgrade my-release bitnami/nginx -f new-values.yaml
# Upgrade or install if not existshelm upgrade --install my-release bitnami/nginx
# Reuse existing values and add new oneshelm upgrade my-release bitnami/nginx --reuse-values --set image.tag=1.21Stop and think: You run
helm upgrade my-release bitnami/nginx --set replicaCount=5without--reuse-values. What happens to all the other custom values you set during the initial install? This is a very common mistake.
Rolling Back
Section titled “Rolling Back”# Rollback to previous revisionhelm rollback my-release
# Rollback to specific revisionhelm rollback my-release 2
# Check history firsthelm history my-releaseUninstalling
Section titled “Uninstalling”# Uninstall releasehelm uninstall my-release
# Uninstall but keep historyhelm uninstall my-release --keep-history
# Uninstall from namespacehelm uninstall my-release -n productionWorking with Values
Section titled “Working with Values”Pause and predict: If you pass both a values file with
replicaCount: 2AND use--set replicaCount=5on the samehelm installcommand, which value wins? Think about why Helm would design it this way.
Values Hierarchy (Lowest to Highest Priority)
Section titled “Values Hierarchy (Lowest to Highest Priority)”- Default values in chart (
values.yaml) - Parent chart values
- Values file passed with
-f - Individual values with
--set
Values File Example
Section titled “Values File Example”replicaCount: 3
image: repository: nginx tag: "1.21" pullPolicy: IfNotPresent
service: type: NodePort port: 80
resources: limits: cpu: 100m memory: 128Mi requests: cpu: 50m memory: 64Mi
nodeSelector: disktype: ssdUsing Values Files
Section titled “Using Values Files”# Install with values filehelm install my-release bitnami/nginx -f my-values.yaml
# Multiple values files (later overrides earlier)helm install my-release bitnami/nginx -f values.yaml -f production.yaml
# Combine file and inlinehelm install my-release bitnami/nginx -f values.yaml --set replicaCount=5Common —set Syntax
Section titled “Common —set Syntax”# Simple value--set replicaCount=3
# Nested value--set image.tag=1.21
# String value (use quotes for special chars)--set image.repository="my-registry.com/nginx"
# Array value--set nodeSelector.disktype=ssd
# Multiple values--set replicaCount=3,service.type=NodePort
# List items--set ingress.hosts[0].host=example.comPractical Exam Scenarios
Section titled “Practical Exam Scenarios”Scenario 1: Install and Configure
Section titled “Scenario 1: Install and Configure”# Add repohelm repo add bitnami https://charts.bitnami.com/bitnamihelm repo update
# Install with custom valueshelm install my-nginx bitnami/nginx \ --set replicaCount=2 \ --set service.type=ClusterIP \ -n web --create-namespace
# Verifyhelm list -n webk get pods -n webScenario 2: Upgrade and Rollback
Section titled “Scenario 2: Upgrade and Rollback”# Check current releasehelm listhelm get values my-nginx
# Upgradehelm upgrade my-nginx bitnami/nginx --set replicaCount=3
# Something goes wrong - rollbackhelm history my-nginxhelm rollback my-nginx 1
# Verifyhelm listScenario 3: Inspect Before Install
Section titled “Scenario 3: Inspect Before Install”# See what you're installinghelm show values bitnami/nginx | head -50
# Dry run to see generated manifestshelm install test bitnami/nginx --dry-run | less
# Then installhelm install my-nginx bitnami/nginxChart Structure (Reference)
Section titled “Chart Structure (Reference)”my-chart/├── Chart.yaml # Chart metadata├── values.yaml # Default configuration├── charts/ # Dependency charts├── templates/ # Kubernetes manifests│ ├── deployment.yaml│ ├── service.yaml│ ├── _helpers.tpl # Template helpers│ └── NOTES.txt # Post-install notes└── README.mdYou won’t create charts in the CKAD exam, but understanding structure helps with debugging.
What would happen if: You run
helm install my-app bitnami/nginxin thedefaultnamespace, then later runhelm listin theproductionnamespace. Would you seemy-appin the output? Why does this matter during the exam?
Troubleshooting Helm
Section titled “Troubleshooting Helm”Common Issues
Section titled “Common Issues”# Release stuck in pending-installhelm list --pendinghelm uninstall stuck-release
# See what's wronghelm get manifest my-release | k apply --dry-run=server -f -
# Debug template renderinghelm template my-release bitnami/nginx --debug
# Check release statushelm status my-releaseUseful Debug Commands
Section titled “Useful Debug Commands”# See rendered templateshelm template my-release bitnami/nginx > rendered.yaml
# Validate without installinghelm install my-release bitnami/nginx --dry-run --debug
# Get notes (post-install instructions)helm get notes my-releaseDid You Know?
Section titled “Did You Know?”-
Helm 3 removed Tiller. Helm 2 required a server-side component (Tiller) with cluster-admin privileges. Helm 3 runs entirely client-side, using your kubeconfig permissions.
-
helm upgrade --installis idempotent—it installs if the release doesn’t exist, or upgrades if it does. Great for CI/CD pipelines. -
Helm stores release data as Secrets (default) or ConfigMaps. Each revision is a separate Secret, enabling rollback to any previous state.
Common Mistakes
Section titled “Common Mistakes”| Mistake | Why It Hurts | Solution |
|---|---|---|
Forgetting helm repo update | Install old chart versions | Always update before installing |
| Wrong namespace | Release in default namespace | Use -n namespace consistently |
--set typos | Values not applied | Use --dry-run to verify |
Forgetting --reuse-values | Upgrade resets to defaults | Add flag when only changing some values |
| Not checking history before rollback | Roll back to wrong version | Run helm history first |
-
Your CI/CD pipeline needs to deploy a chart that may or may not already be installed in the cluster. It should install on first run and upgrade on subsequent runs, without error. What single Helm command handles both cases?
Answer
Use `helm upgrade --install my-release bitnami/nginx`. The `--install` flag makes the command idempotent -- it installs if the release doesn't exist and upgrades if it does. This is the standard pattern for CI/CD pipelines because it eliminates the need for conditional logic to check whether a release exists. Add `--atomic` to automatically roll back if the upgrade fails, ensuring the pipeline never leaves a broken release behind. -
A teammate upgraded a Helm release with
helm upgrade my-app bitnami/nginx --set replicaCount=5but now reports that theservice.typethey set during initial install has reverted to the chart defaultLoadBalancerinstead of their customClusterIP. What happened and how do they fix future upgrades?Answer
Without `--reuse-values`, `helm upgrade` resets all values to chart defaults except those explicitly passed in the current command. Only `replicaCount=5` was set, so `service.type` reverted to the default. Fix with: `helm rollback my-app` to restore the previous state, then `helm upgrade my-app bitnami/nginx --reuse-values --set replicaCount=5`. The `--reuse-values` flag carries forward all values from the previous revision. Better yet, maintain a values file with all customizations and always pass it: `helm upgrade my-app bitnami/nginx -f values.yaml --set replicaCount=5`. -
During the CKAD exam, you’re told to “find what values the release
web-prodis using in thefrontendnamespace.” You runhelm get values web-prodand get “release not found.” The release definitely exists. What’s wrong?Answer
Helm releases are namespace-scoped. You need to specify the namespace: `helm get values web-prod -n frontend`. By default, Helm looks in the current kubectl context namespace. This is a common exam pitfall -- always include `-n` when working with Helm releases outside the default namespace. Use `helm list -A` to find releases across all namespaces when you're not sure where a release lives. -
You installed a Helm chart but the pods are crash-looping. You need to inspect the exact Kubernetes manifests that Helm generated to see if the configuration is correct. How do you view the rendered YAML without uninstalling and reinstalling?
Answer
Run `helm get manifest web-prod` to see the exact rendered Kubernetes YAML that was applied. This shows every resource (Deployments, Services, ConfigMaps, etc.) as they were sent to the API server. For debugging before deploying, use `helm template my-release bitnami/nginx -f values.yaml` to render templates locally without contacting the cluster, or `helm install my-release bitnami/nginx --dry-run --debug` to simulate the install with server-side validation.
Hands-On Exercise
Section titled “Hands-On Exercise”Task: Complete Helm workflow with a real chart.
Setup:
# Add repositoryhelm repo add bitnami https://charts.bitnami.com/bitnamihelm repo updatePart 1: Inspect and Install
# See available valueshelm show values bitnami/nginx | head -30
# Install with custom valueshelm install web bitnami/nginx \ --set replicaCount=2 \ --set service.type=ClusterIP
# Verify installationhelm listk get pods -l app.kubernetes.io/instance=webPart 2: Upgrade
# Upgrade replicashelm upgrade web bitnami/nginx --reuse-values --set replicaCount=3
# Check historyhelm history web
# Verify podsk get pods -l app.kubernetes.io/instance=webPart 3: Rollback
# Rollback to revision 1helm rollback web 1
# Verify revertedhelm get values webk get pods -l app.kubernetes.io/instance=webPart 4: Cleanup
helm uninstall webPractice Drills
Section titled “Practice Drills”Drill 1: Repository Management (Target: 2 minutes)
Section titled “Drill 1: Repository Management (Target: 2 minutes)”# Add bitnami repohelm repo add bitnami https://charts.bitnami.com/bitnami
# Updatehelm repo update
# Search for mysqlhelm search repo mysql
# List reposhelm repo listDrill 2: Basic Install (Target: 2 minutes)
Section titled “Drill 2: Basic Install (Target: 2 minutes)”# Install nginxhelm install drill2 bitnami/nginx
# List releaseshelm list
# Check statushelm status drill2
# Cleanuphelm uninstall drill2Drill 3: Install with Values (Target: 3 minutes)
Section titled “Drill 3: Install with Values (Target: 3 minutes)”# Create values filecat << 'EOF' > /tmp/values.yamlreplicaCount: 2service: type: ClusterIPEOF
# Install with values filehelm install drill3 bitnami/nginx -f /tmp/values.yaml
# Verify values appliedhelm get values drill3
# Cleanuphelm uninstall drill3Drill 4: Upgrade and Rollback (Target: 4 minutes)
Section titled “Drill 4: Upgrade and Rollback (Target: 4 minutes)”# Installhelm install drill4 bitnami/nginx --set replicaCount=1
# Upgradehelm upgrade drill4 bitnami/nginx --set replicaCount=3
# Check historyhelm history drill4
# Rollbackhelm rollback drill4 1
# Verifyhelm get values drill4
# Cleanuphelm uninstall drill4Drill 5: Namespace Operations (Target: 3 minutes)
Section titled “Drill 5: Namespace Operations (Target: 3 minutes)”# Install in new namespacehelm install drill5 bitnami/nginx -n helm-test --create-namespace
# List in namespacehelm list -n helm-test
# Get pods in namespacek get pods -n helm-test
# Cleanuphelm uninstall drill5 -n helm-testk delete ns helm-testDrill 6: Complete Scenario (Target: 6 minutes)
Section titled “Drill 6: Complete Scenario (Target: 6 minutes)”Scenario: Deploy a production-ready nginx.
# 1. Create values filecat << 'EOF' > /tmp/prod-values.yamlreplicaCount: 3service: type: NodePort nodePorts: http: 30080resources: limits: cpu: 100m memory: 128Mi requests: cpu: 50m memory: 64MiEOF
# 2. Dry-run firsthelm install prod-web bitnami/nginx -f /tmp/prod-values.yaml --dry-run
# 3. Installhelm install prod-web bitnami/nginx -f /tmp/prod-values.yaml
# 4. Verifyhelm listhelm get values prod-webk get pods -l app.kubernetes.io/instance=prod-web
# 5. Upgrade with more replicashelm upgrade prod-web bitnami/nginx -f /tmp/prod-values.yaml --set replicaCount=5
# 6. Something wrong - rollbackhelm rollback prod-web 1
# 7. Cleanuphelm uninstall prod-webNext Module
Section titled “Next Module”Module 2.3: Kustomize - Customize Kubernetes resources without templates.