Kustomize vs Helm
Kubernetes isnβt exactly known for its simplicity, largely due to the granular control it offers over a wide range of objects used to manage microservice applications. As these applications grow in complexity as they invariably seem to do, managing them can become even more challenging. Helm and Kustomize are two widely used tools designed to make this process more manageable. While both aim to facilitate the deployment of complex applications in Kubernetes environments, they approach the task from two different directions.
In this post, weβll explore their key features, compare their strengths and weaknesses, and help you decide which tool is the better fit for your needs at any given stage of deployment.
What is Helm?β
Helm is a cloud native CLI tool, which has risen to be the most widely used package manager for Kubernetes to date. It allows users to define, install, and manage applications as Helm charts. Helm uses a temple engine based on Go templating to generate Kubernetes manifests based on user-defined templates and configuration values. Helm charts encapsulate all the necessary resources and configurations needed to generate the manifests that define the application which is to be deployed, making it easy to share and reuse configurations across different projects. Helm also supports versioning, rollbacks, and dependency management, making it a powerful tool for managing complex applications in Kubernetes.
We recently published an in-depth Helm guide, sharing key commands, common errors, best practices and a comprehensive live of FAQs covering many Helm related queries. Check it out.
What is a Helm chart?β
A Helm chart is essentially a blueprint for deploying applications to a Kubernetes cluster. It packages together all the necessary Kubernetes resources (Pods, Services, ConfigMaps, etc.) into a bundle, which can then be named and deployed as a single release. These charts are stored in Helm repositories, where users can download and install pre-configured applications with ease.
To create a Helm chart, use the following command:
helm create <chart-name>
This sets up the basic file structure, including a templates/
directory for your custom Kubernetes manifests and a values.yaml
file for defining configurable parameters. Helm charts are a great starting point for packaging and deploying applications in Kubernetes environments. However, they come with some challenging limitations, such as:
- Dependency management can be difficult and error-prone.
- Updating CRDs (Custom Resource Definitions) is not supported.
- There's no server-side component, making it hard to track issues like health degradation or configuration drift.
- Native support for reusing configurations with environment-specific changes is lacking.
Helm chart structureβ
A typical Helm chart project structure looks like this:
mychart/
Chart.yaml
values.yaml
charts/
templates/
deployment.yaml
service.yaml
Chart.yaml
: Contains metadata about the chart (name, version, etc.).values.yaml
: Stores the default configuration values, which can be customized and injected into the templates dynamically.templates/
: Holds the Kubernetes manifests for each resource (e.g., Deployment, Service, etc.).
Thereβs much more to Helm than whatβs covered here. As mentioned earlier, a previously published in-depth guide explores Helm in greater detail. In the upcoming sections, weβll focus on Helm specifically in comparison to Kustomize.
What is Kustomize?β
Kustomize is a Kubernetes-native tool developed after Helm, addressing the need to manage Kubernetes configurations declaratively without templating. Many Kubernetes users sought a way to manipulate plain YAML files with kubectl commands, whether for handling multiple files, creating or updating ConfigMaps
and Secrets
, or rolling out changes across environments. Kustomize emerged as a solution for configuration management, using base manifests to create environment-specific variants.
Unlike Helm, which relies on templates, Kustomize uses overlays to apply different configurations to a base set of resources. This allows you to maintain base YAML files and layer environment-specific changes, such as for development
, staging
, or production
.
We recently published an in-depth Kustomize tutorial that explores the various types of patches, transformers, and generators, along with best practices for using the tool effectively. Be sure to check it out for a more detailed guide.
How to use Kustomize?β
Kustomize allows you to manage and customize Kubernetes configurations by layering modifications without altering the original files. A typical Kustomize setup involves a directory structure consisting of a base and overlays.
Kustomize project structureβ
The base/
directory contains a kustomization.yaml file along with manifest files for common resources shared across environments. The kustomization.yaml
file defines the core resources, like Deployments
and Services
, that apply to all environments.
The overlays/
directories contain their own kustomization.yaml
files, which reference the resources from the base and apply environment-specific patches or customizations. These patches could include changes to image tags, resource limits, labels, or other environment-specific configurations. The overlay directories allow you to apply modifications for environments such as development, staging, or production, without altering the core configurations in the base.
βββ base/
β βββ kustomization.yaml
β βββ deployment.yaml
β βββ service.yaml
βββ overlays/
βββ production/
β βββ kustomization.yaml
β βββ replica-patch.yaml
βββ staging/
βββ kustomization.yaml
βββ resource-patch.yaml
There isn't a definitive project structure for Kustomize. This is just a structure recommended in the Kustomize documentation which is often used since it has proven to be quite flexible.
Kustomize vs Helm, what are the differences?β
Feature | Kustomize | Helm |
---|---|---|
Kubectl integration | Yes (since v1.14) | No |
Ease of use | Simple for patching | More complex due to templating syntax |
Approach | Overlays for resource customization | Templates for dynamic configuration |
Declarative/imperative | Fully declarative | Both declarative and imperative (with hooks, scripts) |
Packaging & distribution | No | Yes (packaging applications as charts) |
Version control/Rollbacks | No (requires external tools like Git) | Yes (built-in release management) |
State management | No | Yes (manages release history and state) |
Customization flexibility | High for environment-specific changes | High for full application lifecycle |
Pre-built ecosystem | None | Extensive (large library of pre-built charts) |
CI/CD integration | Ideal for GitOps | Well-suited for traditional CI/CD workflows and GitOps |
Complexity of logic | Low (no logic or scripting) | Medium to High (templating logic, hooks, and scripts) |
Kustomize vs Helm: Method of operationβ
Helm uses a templating engine, allowing users to pass values into predefined templates for dynamic, repeatable configurations. However, this introduces complexity, as the unrendered templates can be difficult to read and debug.
Kustomize, in contrast, focuses on declarative configurations with plain Kubernetes manifests, making it more intuitive and readable. While Kustomize simplifies configuration management, it lacks some of Helmβs imperative features, like state management, which can be useful in more complex scenarios.
Kustomize vs Helm: Ease of useβ
Helm is often considered easier for packaging entire applications, thanks to its extensive ecosystem of pre-built charts. However, Kustomize isnβt necessarily harder to use, itβs just built for a different purpose. Kustomize shines when making small, targeted modifications to existing resource definition files, making it ideal for managing configurations across multiple environments, rather than packaging whole applications like Helm.
One of Helmβs drawbacks is that its dynamically populated templates can be hard to interpret unless rendered. In contrast, Kustomize manages and modifies plain YAML manifests, making it much easier to read and understand. Engineers are likely to find Kustomize configurations more approachable and intuitive compared to Helm charts when inspecting a repository.
Kustomize vs Helm: Packagingβ
Helm is purpose-built for packaging and distributing Kubernetes applications, while Kustomize is more about applying modifications to existing YAML configurations. If you need full application lifecycle management, Helm might be better suited. For granular resource customization, Kustomize is the way to go.
kubectl Integrationβ
Kustomize is natively integrated with kubectl from version 1.14 onwards, meaning you can use it directly without needing any additional tools. Helm, on the other hand, requires the Helm CLI.
Install kubectl
and run:
kubectl apply -k <kustomization directory>
Helm on the other hand is custom-built to be used in Kubernetes environments but it is not integrated into kubectl
.
Declarative vs. Imperativeβ
- Kustomize (Declarative), focuses purely on defining and applying the desired state with no scripting or state management, keeping things straightforward and predictable.
- Helm (Declarative and Imperative), supports declarative configurations but also allows for imperative operations like running hooks and managing deployment state, adding flexibility at the cost of complexity.
Release History Managementβ
- Helm maintains a history of deployments through its "releases" system. This allows for tracking changes over time and provides rollback capabilities.
- Kustomize focuses solely on generating the desired state of Kubernetes resources without built-in history tracking. While it doesn't manage releases natively, similar functionality can be achieved by:
- Using labels in your Kustomize configurations
- Combining with
kubectl apply --prune
to handle resource cleanup - Integrating with external tools for deployment tracking
Kustomize vs Helm: CI/CD Integrationβ
While both Helm and Kustomize are used in CI/CD pipelines, Helmβs release management and rollback capabilities are often better suited for automating continuous delivery. Kustomize, by focusing on resource customization, fits well with GitOps workflows where changes are version-controlled, but may need more tools to track and manage changes at scale.
Learning Curve and Maintainabilityβ
Helm has a steeper learning curve due to its templating system and the need to understand the Helm-specific syntax. Kustomize, being closer to native Kubernetes, might feel more intuitive for users already familiar with Kubernetes resource definitions. However, this simplicity can also lead to challenges when dealing with more complex configurations.
Using Helm and Kustomize Togetherβ
Helm and Kustomize can each be used as standalone tools, but in practice, they are often combined to manage Kubernetes deployments more effectively. Consider using them together in the following scenarios:
- Environment-specific customizations: Use Kustomize to apply changes such as resource limits, quotas, annotations, or namespaces across multiple environments (e.g., development, staging, production) without altering the original Helm chart. This allows you to dynamically configure any environment-specific adjustments while maintaining the core deployment logic in Helm, ensuring that the base setup remains consistent across environments.
- When using third party Helm charts: Modify manifests from third-party Helm charts without altering the original chart using Kustomize (e.g., adding labels or changing configurations).
- Managing Secrets and ConfigMaps: Keep sensitive resources separate from Helm charts by creating them with Kustomize after the chart is deployed. Kustomize can also be used to inject sensitive resources that have already been created.
- GitOps workflows: Use Helm to generate the base manifests, keep Helm rendered manifests and environment customizations separate while adhering to a clean, declarative GitOps model. Using Helm and Kustomize together supports the principle of separation of concerns, which is a key aspect of the GitOps methodology.
There are three approaches to combining Helm and Kustomize, though not all are equally mature or reliable.
-
Using
helm template
and apply with Kustomize: In this method, you usehelm template
to generate the Kubernetes manifests from a Helm chart, and then use Kustomize to apply patches or overlays. Since Kustomize is in charge of deploying the resources to Kubernetes, Helm won't manage the release, so there's no Helm-based release tracking. -
Using
helm install
with Kustomize pre-modifications: Through this method, Helm is responsible for the application release, so it manages and keeps track of the application's lifecycle, while Kustomize modifies the manifests before applying them to the cluster. This allows you to still benefit from Helm's release management. -
Using Kustomize's HelmChartInflationGenerator: Kustomize includes built-in support for Helm chart inflation through the
helmCharts
field. This feature requires the--enable-helm
flag:kustomize build --enable-helm
However, this approach is considered experimental and has known limitations. Its future development status remains uncertain, making it a less reliable choice for production environments.
Key takeawaysβ
Helm excels at packaging applications, it offers rich features like rollback, versioning, and dependency management. However, its use of templates reduce it to the limitations of the Go templating framework and can become quite complicated, especially when maintaining large and intricate deployments.
On the other hand, Kustomize takes a simpler, template-free approach, focusing on patch-based configuration management. It's particularly useful for managing different environments (development, staging, production) without leaning on complicated templating logic. This makes Kustomize the obvious option when you need to apply variations to a common set of base configurations in an elegant and straightforward way.
In practice, combining Helmβs packaging capabilities with Kustomizeβs flexible overlay system offers the best of both worlds. Together, they enable robust, maintainable, and adaptable Kubernetes deployments, where Helm handles application releases, and Kustomize manages environment-specific customizations quite well. While some may find using two separate tools for Kubernetes package management less convenient, until a more comprehensive, all-in-one solution emerges, this combination remains one of the most effective approaches available.