Helm Made Simple: Managing Kubernetes Apps with Charts

Sep 28, 2025 posted by Ilman Iqbal

Learn how Helm simplifies Kubernetes application management by packaging your deployments, services, and ingress configurations into reusable charts. This guide walks you through installing Helm on Ubuntu, creating and customizing your own Helm chart for a User Management service, working with values overrides, and finally packaging and sharing your chart for reuse across different environments.

Helm Kubernetes illustration

What is Helm?

Deploying applications into Kubernetes using raw YAML manifests can be repetitive and error-prone. Imagine having to manage dozens of deployments, services, and configs for multiple environments (dev, QA, prod). That’s where Helm, the Kubernetes package manager, comes in.

Think of Helm as apt or yum for Kubernetes.

Helm helps you:

Why not just kubectl apply -f?

If you only use kubectl, you'll encounter several practical problems:

Helm Concepts in a Nutshell

Installing Helm on Ubuntu

Before using Helm charts, you need to install the Helm CLI. On Ubuntu or other Debian-based systems, you can install Helm in a few simple steps.

1. Update apt package index

sudo apt-get update

2. Install prerequisite packages (curl, apt-transport-https, gnupg)

sudo apt-get install -y curl apt-transport-https gnupg

3. Add the Helm GPG key

curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -

4. Add the Helm apt repository

echo "deb https://baltocdn.com/helm/stable/debian/ all main" | \
sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

5. Install Helm

sudo apt-get update
sudo apt-get install helm

6. Verify installation

helm version
# Example output
version.BuildInfo{Version:"v3.16.2", GitCommit:"...", GoVersion:"go1.22.2"}

If you see a version output, Helm is installed successfully and ready to use!

Working with Helm Repositories (Using Curity as an Example)

Once Helm is installed, the next step is to work with Helm repositories. These are collections of charts hosted on web servers, similar to how apt or yum repositories store software packages.

Instead of writing and managing all Kubernetes YAML files manually, you can use charts from these repos to quickly deploy common applications like databases, message queues, or identity servers.

Let’s walk through an example with the Curity Identity Server. Curity is an OAuth and OpenID Connect server used for authentication and API security in enterprise setups. Deploying it manually with YAML would be complex, but with Helm it’s just a few commands.

1. Add the Curity Helm repository

# Add the official Curity Helm repo
helm repo add curity https://curityio.github.io/idsvr-helm/

This registers the Curity chart repo so you can install charts from it.

2. Verify repositories

helm repo list
# Output
NAME    URL
curity  https://curityio.github.io/idsvr-helm/

Now Helm knows about the curity repository.

3. Search for charts inside the repo

helm search repo curity
# Output
NAME            CHART VERSION   APP VERSION     DESCRIPTION
curity/idsvr    0.13.8          10.3.0          A Helm chart for Curity Identity Server

This shows the available chart (curity/idsvr), its version, and description.

4. Install Curity Identity Server

helm install idsvr-tutorial curity/idsvr \
  --namespace curity \
  --create-namespace \
  --set image.tag=latest \
  --set curity.config.password=12345678 \
  --set curity.config.uiEnabled=true \
  --timeout 10m

- idsvr-tutorial: your deployment instance name for the curity/idsvr chart.
- --namespace curity: deploy into a namespace called curity.
- --create-namespace: creates the namespace if it doesn’t exist.
- --set ...: overrides values defined in the chart’s values.yaml file (e.g., password, enabling UI).
- --timeout 10m: sets the maximum time Helm will wait for all resources to be ready. If deployment takes longer than this, Helm will report a timeout error.

5. Check installed releases

helm list -n curity
# Output
NAME            NAMESPACE   REVISION   UPDATED               STATUS    CHART        APP VERSION
idsvr-tutorial  curity      2          2025-09-24 23:37:26   deployed  idsvr-0.13.8 10.3.0

This shows the deployment instance is running, which chart version is used, and its status.

6. Inspect Kubernetes resources

kubectl get deployments -n curity
# Output
NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
idsvr-tutorial-admin     1/1     1            1           10m
idsvr-tutorial-runtime   1/1     1            1           10m

Helm deployed two deployments: admin and runtime. Both are ready.

kubectl get svc -n curity
# Output
NAME                         TYPE        CLUSTER-IP      PORT(S)
idsvr-tutorial-admin-svc     ClusterIP   10.43.209.141   6749/TCP ...
idsvr-tutorial-runtime-svc   ClusterIP   10.43.66.149    8443/TCP ...

Services expose the pods inside the cluster. These ports (e.g., 6749, 8443) can be port-forwarded.

7. Port-forward to access locally

# Forward Admin UI service to localhost:6749
kubectl port-forward svc/idsvr-tutorial-admin-svc 6749:6749 -n curity

# Forward Runtime service to localhost:9443
kubectl port-forward svc/idsvr-tutorial-runtime-svc 9443:8443 -n curity

By forwarding the service, you automatically access all pods behind it. You can now open http://localhost:6749 to access the admin UI, and https://localhost:9443 for the runtime.

8. Upgrade with new configs

helm upgrade idsvr-tutorial curity/idsvr \
  --namespace curity \
  --set curity.admin.logging.level=DEBUG \
  --set curity.runtime.logging.level=DEBUG

Updates your existing deployment instance (idsvr-tutorial) with new configuration values, without reinstalling from scratch.

9. Uninstall the release

helm delete idsvr-tutorial -n curity

Deletes all Kubernetes resources (Deployments, Services, ConfigMaps, etc.) created by this instance. The namespace remains unless you explicitly delete it.

Helm Chart Structure

A Helm chart is essentially a package containing all the Kubernetes manifests and configuration needed to deploy an application. A typical chart looks like this:

springboot-helm-chart/
  Chart.yaml       # Metadata about the chart (name, version, description)
  values.yaml      # Default configuration values for this chart
  charts/          # Dependencies (sub-charts)
  templates/       # Templates that generate Kubernetes manifests
    deployment.yaml
    service.yaml
    ingress.yaml
    _helpers.tpl   # Custom template helpers for reuse

Charts use values.yaml to define configurable parameters. You can reference these values in your templates using the syntax:

{{ .Values.variableName }}

Example usage:

# In deployment.yaml template
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
replicas: {{ .Values.replicaCount }}

# In values.yaml
image:
  repository: myapp/springboot
  tag: 4.0.0
replicaCount: 2

You can override these values at install or upgrade time using --set or a custom values file (e.g., -f values-prod.yaml), allowing you to deploy the same chart across multiple environments with different configurations.

Converting Existing Kubernetes Manifests into a Helm Chart

In the Kubernetes Made Simple and Kubernetes StatefulSets with MongoDB blog post, we created several Kubernetes manifests to deploy a User Management application with a MongoDB StatefulSet:

Instead of managing these YAMLs manually, we can package them into a Helm chart for easier deployment, configuration, and reusability. We’ll also add a new user-management-ingress.yaml to expose the app externally.

1. Create a new chart

helm create user-management

This creates a new directory user-management/ with a standard Helm chart structure, including Chart.yaml, values.yaml, and templates/.

2. Review and edit Chart.yaml

The Chart.yaml file defines metadata about your chart (name, description, version, etc.). Example:

# user-management/Chart.yaml
apiVersion: v2
name: user-management
description: A Helm chart for deploying the User Management app
type: application
version: 0.1.0          # chart version
appVersion: "1.0.0"     # actual app version

You can reference these values inside your templates with .Chart.*, for example:

metadata:
  labels:
    app.kubernetes.io/name: {{ .Chart.Name }}
    app.kubernetes.io/version: {{ .Chart.Version }}
    app.kubernetes.io/appVersion: {{ .Chart.AppVersion }}

This ensures your manifests always carry chart metadata (useful for debugging and when sharing charts).

3. Replace template files with your manifests

Copy the manifests from the earlier blog post into the templates/ folder and rename them. By renaming, you also stick to the standard Helm chart layout (deployment.yaml, service.yaml, ingress.yaml), which makes it easier for others to recognize the purpose of each file at a glance. If you ever share your chart (for example, publish it to a repo), other developers will expect to see these common naming patterns.

4. Parameterize values

Replace hardcoded values in your manifests with {{ .Values.* }} placeholders and define them in values.yaml. For example:

# templates/deployment.yaml
replicas: {{ .Values.userManagement.replicas }}
image: "{{ .Values.userManagement.image.repository }}:{{ .Values.userManagement.image.tag }}"
env:
- name: EXTERNAL_BACKEND_URL
  value: "{{ .Values.userManagement.externalBackendUrl }}"

# values.yaml
userManagement:
  replicas: 2
  image:
    repository: user-management
    tag: latest
  externalBackendUrl: "http://external-backend-svc:8088"

5. Add an Ingress for user-management

Create a new file templates/ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Chart.Name }}-ingress           # Uses the chart name from Chart.yaml (e.g., "user-management")
  namespace: {{ .Release.Namespace }}       # The namespace where the Helm release is installed (set with --namespace when you run `helm install`)
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: {{ .Values.ingress.host }}
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: {{ .Values.userManagement.serviceName }}
            port:
              number: 8082

# values.yaml
ingress:
  host: user-management.local
userManagement:
  serviceName: user-management-svc

6. Install your chart

helm install user-mgmt user-management/ \
  --namespace user-mgmt-ns \
  --create-namespace \
  --timeout 10m

This installs your chart into a fresh namespace user-mgmt-ns

Helm lets you customize deployments in two ways:

7. Verify installation

kubectl get all -n user-mgmt-ns
kubectl get ingress -n user-mgmt-ns

You now have a fully parameterized Helm chart for your User Management application. Any changes (replica counts, image versions, or ingress hostnames) can be managed easily via values.yaml.

Share your Helm chart

Once your Helm chart is ready, you can share it with others or use it across different environments. There are multiple ways to distribute your chart effectively.

By versioning your chart, maintaining standard structure, and using proper packaging, you make it easier for others to reuse, update, and deploy your application consistently. Always document any required overrides, such as namespace, image tags, or ingress hosts, so that installation is smooth for other users.