Marcio Cunha

How to write reusable Helm charts without duplicating code

Learn how to structure reusable Helm charts using subcharts, advanced templates, and dynamic values to standardize your Kubernetes infrastructure.

Marcio Cunha•4 min
Also available in:PortuguêsEspañol
Summary
  • Duplicating YAML files across different microservices creates maintenance bottlenecks and configuration drift in infrastructure.
  • Encapsulating common logic into parent and child charts centralizes business rules while keeping per-environment flexibility.
  • The lookup function and advanced template features allow injecting robust conditional logic directly into manifests.
  • A strict separation between global values and application-specific parameters prevents excessive coupling.
  • Adopting reusable patterns drastically reduces application delivery time while maintaining strict cluster compliance.

The problem of manifest duplication in Kubernetes

Managing dozens of applications in Kubernetes without a clear packaging strategy turns any operation into a copy-paste nightmare. When each microservice has its own set of YAML files—containing identical deployments, services, and ingresses—any structural change requires manual edits across multiple repositories. In practice, this means updating a simple security policy or adding a default environment variable can consume days of repetitive work and open the door to critical human errors.

To solve this scaling challenge, engineers use Helm, which acts as a package manager for Kubernetes, allowing resources to be bundled into logical units called charts. However, using Helm naively by creating a separate chart for each application without abstractions simply moves duplication to another format. True efficiency emerges when we build modular structures capable of adapting to different scenarios without requiring rewrites of the base code.

Before diving into reuse techniques, it is worth noting that standardized cluster delivery requires stable foundations, something we also cover when discussing how to scale GitLab runners in Kubernetes under high demand to ensure operational consistency at any workload volume.

Structuring architectures with parent charts and subcharts

The first major strategy to eliminate duplication is creating a base chart (often called a parent or umbrella chart) that consumes smaller dependencies known as subcharts. Think of this like an industrial kitchen where core utensils are shared across all workstations, while each chef adjusts only the specific ingredients for their dish. In the Kubernetes universe, this means encapsulating standard database, monitoring, or logging infrastructure into a generic subchart.

To configure this hierarchy, the Chart.yaml file of the main chart declares its dependents by pointing to local or remote repositories. When the installation command runs, Helm merges the contexts, allowing the parent application to feed subcharts with custom parameters. In practice, this prevents every team from having to rewrite database connection logic or application health probes (liveness and readiness).

Furthermore, the smart use of dynamic values ensures that the exact same subchart behaves differently depending on who calls it. A messaging service might run with three replicas in production and just one in development, controlled solely by directives passed from the parent chart without altering a single line of the original template.

Moreover, keeping builds optimized ensures seamless packaging, a topic closely related to improving delivery speeds as seen in slow pipeline? How to speed up Docker builds with cache.

Mastering advanced templates with conditionals and loops

When the basic structure no longer covers all business variations, we turn to advanced features of the Go template engine that powers Helm. Functions like if/else, range, and define blocks allow writing highly adaptable manifests that generate tailored Kubernetes code based on user inputs. This is equivalent to creating an intelligent form that drafts the perfect house depending on the number of occupants reported.

A common mistake is trying to embed excessive logic directly into manifest files, which makes reading and debugging extremely complex. To keep code clean, best practice dictates isolating repetitive blocks into named templates inside the _helpers.tpl folder. Thus, name generation functions, standard labels, and network selectors are centralized in a single place, ensuring consistency across the entire cluster.

Below, check out a practical example of a reusable template for standardized labels in _helpers.tpl:

{{- define 'app.labels' -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.Version | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end -}}

This modular approach eliminates metadata inconsistencies between different services, facilitating resource tracking by observability tools and ensuring security policies are applied uniformly—just as crucial as securing access paths as discussed in how to use Istio to secure mTLS traffic in Kubernetes.

Smart management of values and scopes

The ultimate secret to keeping a reusable chart functional over the long term lies in strict management of the values.yaml file. Global values should be strictly reserved for parameters affecting multiple subcharts simultaneously, such as base domains, corporate image tags, or global network configurations. Mixing application-specific parameters into the global scope destroys modularity and creates invisible, dangerous dependencies.

In practice, each subchart should declare its own default values in its respective values.yaml file, allowing them to function in isolation for unit tests or independent deploys. When the parent chart consumes them, it overrides only what is necessary for that specific environment. This scope separation avoids nasty surprises during version upgrades in continuous integration pipelines.

Final thoughts on standardization with Helm

Adopting reusable Helm charts transforms infrastructure governance, replacing the chaos of duplicated manifests with a clean, auditable, and highly scalable ecosystem. By investing time in crafting well-designed subcharts and intelligent templates, engineering teams eliminate repetitive work and drastically reduce the risk of human error in production environments.

In short, the success of this journey relies on architectural discipline: isolate what is common, parameterize what varies, and keep the values documentation always up to date. With these practices consolidated, your organization gains the agility to launch new applications with the certainty that the technical foundation remains solid and standardized.