How to Package an App as a Helm Chart

A Helm chart packages your Kubernetes manifests into one reusable, parameterized unit you install with a single command. Here's the chart structure, how templating works, and how to lint and package it.

DevOps Engineerhelmkubernetescharts

What a Helm chart is

A chart bundles your Kubernetes YAML (Deployment, Service, etc.) into a versioned, templated package. Instead of hand-editing manifests per environment, you set values and Helm renders the YAML. One command installs the whole app.

The chart layout

charts/api/
  Chart.yaml          # metadata: name, version, appVersion
  values.yaml         # default config (image, replicas, ports...)
  templates/
    deployment.yaml   # templated manifests
    service.yaml
    _helpers.tpl      # reusable template snippets

Chart.yaml - identity + versions:

apiVersion: v2
name: api
description: A reusable Helm chart for the API service.
type: application
version: 0.1.0        # the chart version
appVersion: "1.0.0"   # the app version it deploys

values.yaml - the knobs users override:

image:
  repository: ghcr.io/example/api
  tag: latest
replicaCount: 2
service:
  port: 80

Templating the manifests

Templates pull from .Values (values.yaml) and .Chart (Chart.yaml):

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Chart.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  template:
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

_helpers.tpl holds snippets you reuse (like a standard label block) via {{ include }}.

Validate before you ship

helm lint ./charts/api                 # catch schema/template errors
helm template ./charts/api             # render the YAML locally to eyeball it
helm package ./charts/api              # produce api-0.1.0.tgz to publish

Then anyone installs it with helm install api ./charts/api and overrides values with --set image.tag=v2 or a custom values.yaml.

Why charts beat raw manifests

Environments, upgrades, and rollbacks

One chart, many environments: keep defaults in values.yaml and override per environment with a second file - helm upgrade --install myapp . -f values-prod.yaml. Use --set image.tag=1.4.2 for one-off overrides in CI.

helm upgrade --install is the command you actually run in a pipeline: it installs the release if it is new and upgrades it in place if it exists, so deploys are idempotent. If a release goes bad, helm rollback myapp 1 reverts to a previous revision in seconds - Helm keeps a history you can list with helm history myapp.

Version two things in Chart.yaml: bump version whenever the templates change, and set appVersion to the application image you ship. Keeping them distinct tells consumers whether the packaging or the app changed. Run helm lint and helm template in CI so a broken chart never reaches a cluster.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

What files make up a Helm chart?

Chart.yaml (name + versions), values.yaml (default config), and a templates/ directory of templated Kubernetes manifests, often with a _helpers.tpl for reusable snippets.

How do I validate a Helm chart?

Run helm lint to catch errors, helm template to render the YAML locally and inspect it, then helm package to build the distributable .tgz.

What's the difference between version and appVersion in Chart.yaml?

version is the chart's own version (bumped when you change the chart); appVersion is the version of the application the chart deploys.

Keep learning

Fix the Nginx 502 Bad GatewayDevOps projectRecover a Crashed Linux ServiceDevOps projectCorrect a Postgres Port MismatchDevOps projectDevOps roadmapStep by step to hiredDevOps interview questionsSTAR answersAll DevOps projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →