Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

Containers and Kubernetes

Helm charts that upgrade safely and stay maintainable

Helm is the package manager for Kubernetes. A chart bundles templated manifests and default values so an application installs, upgrades and rolls back as one versioned release. We write and review charts, set up private chart repositories, and deliver releases through GitOps with sensible values, testing and upgrade safety.

Key takeaways

  • Helm earns its place when you deploy the same application to many environments or distribute software to others, and adds little for a single static manifest.
  • A good chart exposes few, well-documented values and keeps templates boring. Over-parameterised charts are the main source of Helm pain.
  • Upgrades are where Helm bites: CRDs, immutable fields and hooks need an explicit plan.
  • Helm and GitOps work well together when the controller renders charts and Git holds the values.
  • Helm and Kustomize solve different problems, and many teams sensibly use both.

What teams use Helm for

Packaging your own services

One internal chart (or a small library chart) gives every service the same deployment, probes, limits and security context.

Installing third-party software

Ingress controllers, monitoring stacks and operators ship as charts, and we pin and review them rather than applying them blindly.

Multi-environment configuration

Values files per environment keep staging and production in step while allowing deliberate differences.

Private chart distribution

OCI registries or a chart repository let teams and customers install your software with a versioned, signed artefact.

GitOps delivery

ArgoCD or Flux render charts from Git so every cluster change is a reviewed commit.

Safe rollbacks

Release history lets you return to a previous revision quickly, provided stateful and schema changes were planned for it.

What Helm is and when it helps

Helm packages Kubernetes applications. A chart contains templated manifests, a values.yaml of defaults and a Chart.yaml describing the version. When you install it, Helm renders the templates, applies the result and records a release, which lets you list, upgrade and roll back the whole bundle.

That is genuinely useful in two situations: when you deploy the same application across several environments with small differences, and when you install software written by someone else. If you have one service in one cluster and a handful of YAML files, Helm may be more machinery than you need. Our Helm chart development work starts with that honest question, because the best chart is sometimes no chart. Teams looking for Helm consulting usually already have the symptoms: copy-pasted manifests, values nobody understands, or upgrades that fail halfway.

How we structure charts

One contract, few values

The values file is your chart’s public interface. Every option you add is something to document, test and support. We expose image, replicas, resources, ingress, environment variables and a small number of feature switches, and resist the urge to template every field.

A values schema is the cheapest protection against typos and wrong types:

# values.yaml, validated by a values.schema.json beside it
image:
  repository: registry.example.com/orders-api
  tag: ""            # defaults to .Chart.AppVersion
replicaCount: 3
resources:
  requests: { cpu: 250m, memory: 256Mi }
  limits: { memory: 512Mi }
podDisruptionBudget:
  minAvailable: 2
helm lint ./charts/orders-api
helm template orders ./charts/orders-api -f values/prod.yaml | kubeconform -strict -summary
helm upgrade --install orders ./charts/orders-api -n orders -f values/prod.yaml --atomic --timeout 5m

The --atomic flag rolls back a failed upgrade automatically, which is a sensible default for pipelines that deploy directly. Under GitOps the controller handles this instead.

Library charts and umbrella charts

If thirty services each carry their own deployment template, fixing a probe means thirty edits. A library chart holds shared templates, and service charts depend on it. Umbrella charts, which bundle several sub-charts into one release, are tempting but couple unrelated lifecycles together. We use them sparingly, mostly for tightly bound components.

Security and access

Charts run with whatever permissions the installer has, so access matters. We restrict who can deploy to which namespace with Kubernetes RBAC, and we review third-party charts before adopting them: what they create, which cluster roles they request, and whether they run privileged. Pin chart versions and, where supported, verify provenance or signatures.

Secrets need a deliberate pattern. Values files in Git must not carry plaintext credentials; see Sealed Secrets and External Secrets Operator. Charts should set a restrictive pod security context by default, so teams have to opt out rather than opt in.

Cost and capacity

Helm does not cost anything to run, but charts decide what your workloads cost. Missing resource requests mean poor bin-packing, and oversized defaults waste nodes. We bake in realistic requests, a limit policy and a disruption budget, then tune from real usage. A shared chart makes that one change rather than thirty, which is where the practical savings come from.

Day-2 operations

Upgrades

Chart upgrades are where teams get hurt. Review the diff before applying: the helm diff plugin or your GitOps tool’s diff view shows exactly what will change. Read upstream release notes for breaking changes to values. CRDs are not upgraded by Helm from a chart’s crds directory, so manage them explicitly. Immutable fields, such as a StatefulSet’s selector, cannot be patched and need a planned recreate.

Repositories and promotion

We publish charts to an OCI registry or a repository, version them with semantic versioning, and promote through environments by pull request. Details are in Helm chart repository setup. Delivery with ArgoCD or Flux is covered in migrating from kubectl and Helm to GitOps.

Helm and Kustomize compared

NeedHelmKustomize
Install third-party softwareNatural fit, most vendors publish chartsPossible, but you vendor and patch YAML
Per-environment differencesValues filesOverlays and patches
Versioned, shareable packageYes, via registry or repositoryNo
Release history and rollbackBuilt inLeft to your GitOps tool
Learning curveGo templates and values designLower, plain YAML

Neither is universally better. We often use Helm for the application and a thin Kustomize layer for cluster-specific tweaks, and our guide to multi-environment promotion with Kustomize shows where that boundary works well.

Common failure modes

  • Hooks that hang or leave state, such as migration jobs with no clean-up policy.
  • Values drift, where helm upgrade --reuse-values hides what is really deployed. Prefer explicit values files in Git.
  • Stuck releases in a pending state after an interrupted upgrade, which need careful recovery rather than deletion.
  • Template sprawl: nested conditionals and tpl calls that nobody can read. Simplify or split the chart.
  • Unpinned dependencies that change under you between builds.

When not to use Helm, and migration paths

If your team only patches environments of manifests you own, Kustomize is simpler and needs no release concept. For software that manages itself, an operator may be a better answer than a chart. If your templating logic keeps growing, consider a typed configuration language. Moving away from Helm is usually straightforward: render with helm template and take the output as your starting manifests. For clusters running on Kubernetes, we can review your charts in a short audit. Book a consultation to discuss yours.

Official documentation: helm.sh/docs

How we work with Helm

  1. 01

    Inventory what you deploy

    We list raw manifests, existing charts, scripts and hand-applied resources, and note which differ between environments.

  2. 02

    Design the chart structure

    We decide between one chart per service, a shared library chart or an umbrella chart, and define the values contract.

  3. 03

    Build and harden

    Templates get probes, resource requests, security contexts, disruption budgets and a values schema that rejects bad input.

  4. 04

    Test in CI

    Lint, template rendering, schema validation and kubeconform checks run on every change, with install tests on a throwaway cluster.

  5. 05

    Publish

    Charts are versioned and pushed to an OCI registry or repository, with provenance where your policy requires it.

  6. 06

    Deliver through GitOps

    ArgoCD or Flux applies releases per environment, with promotion handled by pull requests.

Helm compared with the alternatives

We recommend the tool that fits your team, not the one we know best. Here is when each option makes sense.

OptionChoose it when
HelmHelm is the package manager for Kubernetes.
KustomizeChoose it for patching plain YAML per environment when you own the manifests and do not need packaging or release versions. It is built into kubectl.
Plain manifestsChoose them for a small, stable application with one environment, where templating adds more complexity than it removes.
Jsonnet, CUE or TimoniChoose a typed configuration language when templating logic has outgrown Go templates and your team is willing to learn it.
OperatorsChoose an operator when the software needs ongoing lifecycle logic such as backups or failover, not just installation.

Tools we use alongside Helm

ArgoCDFluxKustomizeHelmfileHelm Diff pluginkubeconformchart-testingOCI registriesSealed SecretsExternal Secrets OperatorCosignKubernetes

Frequently asked questions

What is a Helm chart?
A Helm chart is a package of Kubernetes manifest templates, default values and metadata. Installing it renders the templates with your values and creates a release that Helm tracks, so it can be upgraded or rolled back as a unit. Charts are versioned separately from the application they deploy.
Helm or Kustomize?
Helm packages and templates, with release tracking and versioned distribution. Kustomize patches existing YAML without templating. Use Helm for installing third-party software and for reusable internal charts, and Kustomize for light environment overlays. They combine well, for example by post-rendering a chart or letting ArgoCD apply both.
Does Helm work with GitOps tools?
Yes. ArgoCD and Flux both render Helm charts from Git, a chart repository or an OCI registry. The controller owns the release, so you should not run helm upgrade by hand against the same resources. Values live in Git, which gives you review, audit and rollback by revert.
How do you handle secrets in Helm values?
We keep plaintext secrets out of values files. Use Sealed Secrets or the External Secrets Operator so Git holds only encrypted or referenced data, and let the chart reference an existing Secret by name. Avoid helm secrets patterns that decrypt on developer laptops unless you have a clear key policy.
Why does helm upgrade fail on CRDs?
Helm installs files in a chart's crds directory once and does not upgrade or delete them. Changes to custom resource definitions need a separate step, such as applying them from CI or managing CRDs in their own chart. We plan this before the first upgrade, not during an outage.
Is Helm 3 still the right version?
Helm 3 is the long-established major version and what most tooling targets. Check the project's release notes for current status before committing to a version policy. We pin the Helm client in CI so every environment renders charts identically.

Talk to an engineer about Helm

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-09.