How to: Delete a stubborn Kubernetes namespaces.

david_j_eddy profile image David J Eddy ・3 min read

First posted on my blog.

The Situation

Recently I was introduced to a new project. The getting started documentation was decent and I was able to get the project started up. When it came time to clear the project out of my local machines Kubernetes cluster however, the same space for to the terminating life cycle phase and stayed there for days. Fast forward a couple of weeks and I notice it there, still terminating. Turns out the project had a finalizer that was not responding back. Think of remote service call. In this case the remote service never responded. So below is a little script I put together to force a namespace deletion.

The Code

echo "Provided namesapce: ${k8s_delete_ns}..."
echo "Exporting namespace configuration..."
kubectl get namespaces -o json | grep "${k8s_delete_ns}"
kubectl get namespace ${k8s_delete_ns} -o json > temp.json
echo "Opening editor..."
wait 3
vi temp.json
echo "Sending configuration to k8s master for processing..."
curl -H "Content-Type: application/json" -X PUT --data-binary @temp.json${k8s_delete_ns}/finalize
echo "Waiting for namespace deletion to process..."
wait 12
kubectl get namespaces
echo "...done."

So what does this do? Lets remove the shell, echo and wait statements since we know the machine does not really do anything with those.

kubectl get namespaces -o json | grep "${k8s_delete_ns}"
kubectl get namespace ${k8s_delete_ns} -o json > temp.json
vi temp.json
curl -H "Content-Type: application/json" -X PUT --data-binary @temp.json${k8s_delete_ns}/finalize
kubectl get namespaces

So what does this do exactly?

Ok, so what do we have here. Line one takes the first argument from the command invocation and assigns it to a local variable. ./script.sh stuck_namespace. So stuck_namespace is the value that is assigned to k8s_delete.

The next two commands get's the current namespace configuration and writes it to temp.json.

The fourth command opens the temp.json configuration file using vi.

With the configuration open we want to remove any items listed in the finalizers array. This is the real magic moment here. Removing the finalizers with allow kubectl to remove the namespace.

Speaking of the next command uses curl to pass the newly edited configuration to kubectl. This updates the namespace configuration with the config that does not contain finalizers.

And finally, get namespaces will output the existing namespace after the update. If all went as expected the list will not contain the stuck namespace.


So there it is. There are a number of solutions out floating around the internet but the release cadence of Kubernetes renders some of then out-dated in a matter of months. So let me state this: this solution works for Kubernetes 1.13. Other than that, I hope you it helps you out as it helped me.

P.S.: If you would like to keep up with Kubernetes helpers I make, checkout the repo on GitHub.

Posted on Sep 25 '19 by:

david_j_eddy profile

David J Eddy


AWS Certified (x4), Automated Testing / Continuous Integration / Delivery / Deployment (CI/CDs), Cloud, Containers, Dev(Sec)Ops, Software Engineer.


markdown guide