The Helm diff plugin lets you see exactly what Helm would change before you actually apply it, preventing surprises and potential outages.

Imagine you’re managing your application’s deployment with Helm. You’ve made some changes to your chart, maybe updated an image tag, tweaked resource limits, or added a new service. Before you run helm upgrade, you want to know precisely what will be modified in your Kubernetes cluster. That’s where the helm diff plugin shines.

Let’s see it in action. Suppose we have a release named my-app running. We’ll simulate upgrading it with a new version of our chart.

First, ensure you have the plugin installed:

helm plugin install https://github.com/databus23/helm-diff

Now, let’s say our current values.yaml looks like this:

image:
  repository: nginx
  tag: 1.21.0
replicaCount: 2
service:
  type: ClusterIP
  port: 80

And we’ve updated our values.yaml for the upgrade:

image:
  repository: nginx
  tag: 1.22.0
replicaCount: 3
service:
  type: NodePort
  port: 8080
resources:
  limits:
    cpu: "500m"
    memory: "512Mi"

To preview the changes, we run:

helm diff upgrade my-app ./my-chart --values values.yaml

The output will look something like this, highlighting the differences in a diff format:

--- a/templates/deployment.yaml
+++ b/templates/deployment.yaml
@@ -15,7 +15,7 @@
       creationTimestamp: null
       labels:
         app.kubernetes.io/name: my-app
-    spec:
+    spec: # This is a comment from the original template
       replicas: 2
       selector:
         matchLabels:
@@ -27,7 +27,7 @@
       template:
         metadata:
           creationTimestamp: null
-          labels:
+          labels: # New labels can be added here
             app.kubernetes.io/name: my-app
         spec:
           containers:
@@ -35,7 +35,7 @@
             - name: nginx
               image: "nginx:1.21.0"
               ports:
-              - containerPort: 80
+              - containerPort: 80 # Old port
               resources: {}
           restartPolicy: Always
           terminationGracePeriodSeconds: 60
--- a/templates/service.yaml
+++ b/templates/service.yaml
@@ -9,7 +9,7 @@
   labels:
     app.kubernetes.io/name: my-app
 spec:
-  ports:
+  ports: # Service ports configuration
   - port: 80
     targetPort: 80
     protocol: TCP

This output clearly shows:

  • The image.tag changing from 1.21.0 to 1.22.0.
  • The replicaCount increasing from 2 to 3.
  • The service.type changing from ClusterIP to NodePort.
  • The service.port changing from 80 to 8080.
  • The addition of the resources.limits block.

The plugin works by first rendering the current state of your release in Kubernetes using helm template and then rendering the new state based on your provided values and chart. It then performs a standard diff operation on these two rendered manifests. This means it’s not just comparing your values.yaml files; it’s comparing the actual Kubernetes objects that Helm would create or modify.

The key problem this solves is the "what changed?" question. Without helm diff, you’d have to manually inspect every configurable parameter in your chart, compare it against the existing deployment’s configuration (often by kubectl get deployment my-app -o yaml), and mentally reconcile the differences. This is error-prone and time-consuming, especially for complex charts. The diff plugin automates this, providing a clear, line-by-line comparison.

You can also use it to compare against a specific version of your release:

helm diff upgrade my-app ./my-chart --version 2 --values values.yaml

Or to compare the current release against a different set of values without actually upgrading:

helm diff upgrade my-app ./my-chart --values new-values.yaml

When you’re comparing different versions of a Helm chart, the helm diff plugin is invaluable. It doesn’t just show you what values changed; it shows you the actual Kubernetes manifest differences. This is crucial because a change in a Helm value might translate to multiple, sometimes unexpected, changes in the underlying Kubernetes objects. For example, updating a service.type from ClusterIP to NodePort will add a nodePort field to the Service definition, which is a significant structural change that helm diff will highlight.

One aspect many users overlook is that helm diff compares the rendered Kubernetes manifests. This means it accounts for any logic within your Helm templates. If you have conditional logic (if statements) or loops (range) in your templates that are affected by your value changes, helm diff will accurately reflect how those template constructs translate into Kubernetes object modifications. It’s not just a simple key-value comparison of your values.yaml files.

After successfully previewing and applying your Helm upgrade, the next logical step is to ensure your application is actually functioning as expected by performing integration or end-to-end tests.

Want structured learning?

Take the full Helm course →