Helm’s history tracking is one of its most powerful, yet often overlooked, features.
Let’s see this in action. Imagine you have a "my-app" release that’s been updated a few times.
helm history my-app
This command spits out a table. The REVISION column is the key here. Each number represents a distinct state of your release. NAME is the release name, REVISION is the version number, UPDATED shows when it changed, STATUS tells you if it’s deployed or superseded, and CHART is the chart version.
REVISION UPDATED STATUS CHART
1 2023-10-27 10:00:00.123456789 +0000 UTC superseded nginx-1.16.0
2 2023-10-27 10:15:00.987654321 +0000 UTC superseded nginx-1.16.0
3 2023-10-27 10:30:00.555555555 +0000 UTC deployed nginx-1.16.0
So, what problem does this solve? It gives you an audit trail for your Kubernetes deployments managed by Helm. If a deployment goes sideways, you can instantly see the sequence of changes that led to the current state.
Internally, Helm stores this history as Kubernetes resources, specifically as Secrets (or ConfigMaps if configured that way). Each helm history command is essentially querying these Kubernetes Secrets for a specific release name and then parsing their annotations and data to reconstruct the history. When you run helm upgrade or helm rollback, Helm creates a new Secret (or modifies an existing one depending on the Helm version and configuration) that represents that specific revision. The REVISION number is incremented with each change.
The actual manifest for a specific revision is stored within the data field of the Helm Secret object. This is the complete Kubernetes YAML that was applied to your cluster for that particular version of the release.
To get the full manifest of a specific revision, say revision 2 of my-app, you’d use:
helm get manifest my-app --revision 2
This command retrieves the Secret associated with my-app and extracts the manifest data for the specified revision. It’s not just a diff; it’s the entire desired state of your application at that point in time.
The STATUS column is crucial. deployed means this is the version currently running in your cluster. superseded means it was a previous version that has since been updated or rolled back. Helm doesn’t delete superseded revisions by default; they remain part of the history for rollback purposes.
When you perform a helm rollback my-app 2, Helm doesn’t just undo changes. It actually takes the manifest from revision 2 and applies it to your cluster, marking the current deployed revision as superseded and making revision 2 the new deployed state. This is why you can roll back multiple versions – the historical manifests are preserved.
Many users think helm history is just a log of when things changed, but it’s more profound. Each entry is a snapshot of the entire application state as defined by the Helm chart and your values at that moment. This is how helm rollback works its magic: it’s not an undo operation, but a re-application of a past snapshot.
The next step is understanding how to leverage this history for automated recovery or advanced deployment strategies.