You can’t actually "uninstall" a Helm release while keeping its Kubernetes resources because Helm’s uninstall process is the deletion of those resources. Helm manages the lifecycle of your application’s components, and when you tell Helm to uninstall, it interprets that as "clean up everything I created for this release."

To achieve what you’re describing, you need to decouple Helm from the resources it installed. This isn’t a direct Helm operation, but rather a process of telling Helm to essentially forget about a release after its resources are already in a state where Helm won’t touch them.

Here’s how you do it:

The Core Problem: Helm Owns the Resources

When you helm install or helm upgrade, Helm creates Kubernetes resources (Deployments, Services, ConfigMaps, Secrets, etc.) and annotates them with labels like app.kubernetes.io/managed-by: Helm and helm.sh/chart: mychart-0.1.0. These labels are Helm’s way of knowing "these objects belong to me, specifically to release 'myrelease' from chart 'mychart'."

When you run helm uninstall myrelease, Helm scans the Kubernetes API for all objects matching these labels and deletes them. If you want to keep the resources, you need to break this ownership chain before Helm gets a chance to delete them.

The Solution: "Forgetting" the Release

The strategy is to tell Helm that you no longer want it to manage a particular release, but after you’ve manually removed Helm’s ownership markers from the Kubernetes resources.

Step 1: Identify the Release and Its Resources

First, make sure you know the exact name of the Helm release you want to "uninstall" without deleting its resources. You can list your releases with:

helm list -n my-namespace

Let’s assume your release is named my-app in the default namespace.

Next, you need to find all the Kubernetes resources associated with this release. Helm uses labels for this. A common label selector for a Helm release is:

kubectl get all -n default -l app.kubernetes.io/instance=my-app

This command will list Deployments, Services, Pods, ReplicaSets, ConfigMaps, Secrets, etc., that Helm has associated with the my-app release. You might need to adjust the label selector if your chart uses different labels (e.g., heritage=Tiller for older Helm versions, or custom labels).

Step 2: Remove Helm’s Ownership Labels from Resources

This is the crucial step. You need to edit each resource and remove the labels that Helm uses to track them. The most important ones are usually:

  • app.kubernetes.io/instance=<release-name>
  • helm.sh/chart=<chart-name>-<chart-version>
  • app.kubernetes.io/managed-by=Helm

You can do this manually for each resource, or more efficiently, using kubectl label with the --overwrite flag and an empty value to remove the label.

For example, to remove the app.kubernetes.io/instance label from all resources in the default namespace that have it set to my-app:

kubectl label --overwrite namespace default app.kubernetes.io/instance=
kubectl label --overwrite deployment --all -n default app.kubernetes.io/instance=
kubectl label --overwrite service --all -n default app.kubernetes.io/instance=
kubectl label --overwrite statefulset --all -n default app.kubernetes.io/instance=
kubectl label --overwrite daemonset --all -n default app.kubernetes.io/instance=
kubectl label --overwrite replicaset --all -n default app.kubernetes.io/instance=
kubectl label --overwrite pod --all -n default app.kubernetes.io/instance=
kubectl label --overwrite configmap --all -n default app.kubernetes.io/instance=
kubectl label --overwrite secret --all -n default app.kubernetes.io/instance=
kubectl label --overwrite ingress --all -n default app.kubernetes.io/instance=
# ... and so on for any other resource types your chart might create

Important Considerations for Label Removal:

  • Specificity: If your cluster has multiple Helm releases sharing the same namespace, be very careful with the label selectors. You might need to be more specific. Instead of --all, you might need to pipe kubectl get ... to xargs kubectl label.
    kubectl get all -n default -l app.kubernetes.io/instance=my-app -o name | xargs -I {} kubectl label {} app.kubernetes.io/instance-
    
    This command gets all resources for my-app, extracts their names (-o name), and then iterates through them to remove the label.
  • Other Labels: Some charts might add other identifying labels. You might need to inspect your resources (kubectl get <resource-type> <resource-name> -o yaml) to see what other labels Helm might be using and remove those too. The helm.sh/chart label is also a strong indicator.
  • CRDs: Custom Resource Definitions (CRDs) are not typically managed by Helm releases in this way. They are cluster-scoped and usually installed separately. If your release installed a CRD, you’ll need to handle that separately.

Step 3: "Uninstall" the Release in Helm (Now it’s a "Forget" Operation)

Once you’ve stripped the identifying labels from the resources, Helm won’t be able to find them when you try to uninstall. However, Helm still has the release record in its own history. To remove this record without deleting the resources, you use the --no-hooks flag and potentially the --ignore-hooks flag (though --no-hooks is usually sufficient when combined with label stripping).

The standard helm uninstall command will try to delete resources. If you’ve successfully removed the labels, it will fail to find them and report that it deleted zero resources.

helm uninstall my-app -n default --no-hooks

The --no-hooks flag prevents Helm from running any pre- or post-uninstall hooks, which could potentially cause issues.

After this command, the release my-app will be removed from helm list, but the Kubernetes resources (Deployments, Services, etc.) will remain untouched because Helm can no longer identify them as belonging to that release.

Step 4: Verify

Check that the release is gone from Helm’s list:

helm list -n default

Then, check that the resources are still present in Kubernetes:

kubectl get all -n default -l app.kubernetes.io/instance=my-app

If you followed the label removal correctly, this command should still list your resources. If you can’t see them, it means you either didn’t remove the labels properly, or the resources were not labeled in the first place by Helm.

The Next Hurdle: Managing the Orphaned Resources

Now that Helm is no longer managing these resources, you are responsible for them.

  • Updates: You cannot helm upgrade this release anymore. Any updates will need to be done manually using kubectl edit, kubectl apply -f <yaml-file>, or by re-installing the Helm chart into a new release name (which won’t be associated with the old resources).
  • Configuration: If you need to change configuration (e.g., update a ConfigMap or Secret), you’ll have to do it manually via kubectl.
  • Deletion: When you eventually want to delete these resources, you’ll have to do it manually using kubectl delete.

The next logical step is usually to re-apply the same chart, but with a different release name, to get it back under Helm management.

Want structured learning?

Take the full Helm course →