What should I do if Kubernetes'NameSpace can't be deleted?

This article was last updated on: February 7, 2024 pm

overview

Sometimes we operate incorrectly, or there is a problem with the order of deletion, or a critical service is not started, resulting in Kubernetes often being unable to delete NameSpace. What should we do in this case?

Standardize the deletion process

In fact, many times this situation occurs, mainly because our deletion operation is not standardized, typical of the following situations:

  • There are problems with the order of deletion, such as:
    • Remove the key components of Traefik before attempting to delete CRDs that contain Traefik Ingress or EdgeIngress
  • A critical service is not started, such as:
    • For Kubernetes clusters with Prometheus Operator + custom adapter installed, remove NameSpaces that contain these monitoring CRDs or HPA custom metrics in the case of scaling down some of Prometheus’ key components

To sum up, in most cases, NameSpace cannot be deleted, because we are wrong in the first place.

In order to avoid the recurrence of such mistakes, it is recommended to set up the deletion according to the following process:

  1. Ensure that all basic service components are in a healthy state (e.g., ingress component, monitoring component, servicemesh component…)
  2. Check all resources under NameSpace to delete,CRD in particular, recommended here Krew - CLI plugin manager for Kubernetes Installation get-all comegenuineto get all the resources under the NameSpace, as shown in the code block that follows:
  3. For some of these CRDs or special resources, it’s a good idea to explicitly specify the deletion first and ensure that it can be deleted successfully
  4. Finally, delete the NameSpace

Code block for step 2: (there are so many CRDs)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
❯ kubectl get-all -n cert-manager
NAME NAMESPACE AGE
configmap/cert-manager-webhook cert-manager 277d
configmap/kube-root-ca.crt cert-manager 277d
endpoints/cert-manager cert-manager 277d
endpoints/cert-manager-webhook cert-manager 277d
endpoints/cert-manager-webhook-dnspod cert-manager 277d
pod/cert-manager-6d6bb4f487-hkwpn cert-manager 85d
pod/cert-manager-6d6bb4f487-wgtd8 cert-manager 85d
pod/cert-manager-cainjector-7d55bf8f78-5797c cert-manager 277d
pod/cert-manager-webhook-577f77586f-txlcx cert-manager 85d
pod/cert-manager-webhook-577f77586f-xh4st cert-manager 85d
pod/cert-manager-webhook-dnspod-5d5566c7bc-5cj4s cert-manager 211d
secret/cert-manager-cainjector-token-h8cqq cert-manager 277d
secret/cert-manager-token-28knj cert-manager 277d
secret/cert-manager-webhook-ca cert-manager 277d
secret/cert-manager-webhook-dnspod-ca cert-manager 277d
secret/cert-manager-webhook-dnspod-letsencrypt cert-manager 277d
secret/cert-manager-webhook-dnspod-secret cert-manager 277d
secret/cert-manager-webhook-dnspod-token-jsjrn cert-manager 277d
secret/cert-manager-webhook-dnspod-webhook-tls cert-manager 277d
secret/cert-manager-webhook-token-qxq44 cert-manager 277d
secret/default-token-mkpmt cert-manager 277d
secret/ewhisper-crt-secret cert-manager 277d
secret/sh.helm.release.v1.cert-manager-webhook-dnspod.v1 cert-manager 277d
secret/sh.helm.release.v1.cert-manager.v1 cert-manager 277d
serviceaccount/cert-manager cert-manager 277d
serviceaccount/cert-manager-cainjector cert-manager 277d
serviceaccount/cert-manager-webhook cert-manager 277d
serviceaccount/cert-manager-webhook-dnspod cert-manager 277d
serviceaccount/default cert-manager 277d
service/cert-manager cert-manager 277d
service/cert-manager-webhook cert-manager 277d
service/cert-manager-webhook-dnspod cert-manager 277d
order.acme.cert-manager.io/ewhisper-crt-6v6s4-2449993249 cert-manager 209d
order.acme.cert-manager.io/ewhisper-crt-89n7g-2449993249 cert-manager 23d
order.acme.cert-manager.io/ewhisper-crt-8g496-2449993249 cert-manager 277d
order.acme.cert-manager.io/ewhisper-crt-jj24l-2449993249 cert-manager 83d
order.acme.cert-manager.io/ewhisper-crt-q8pvw-2449993249 cert-manager 149d
deployment.apps/cert-manager cert-manager 277d
deployment.apps/cert-manager-cainjector cert-manager 277d
deployment.apps/cert-manager-webhook cert-manager 277d
deployment.apps/cert-manager-webhook-dnspod cert-manager 277d
replicaset.apps/cert-manager-6d6bb4f487 cert-manager 277d
replicaset.apps/cert-manager-cainjector-7d55bf8f78 cert-manager 277d
replicaset.apps/cert-manager-webhook-577f77586f cert-manager 277d
replicaset.apps/cert-manager-webhook-dnspod-5d5566c7bc cert-manager 211d
replicaset.apps/cert-manager-webhook-dnspod-5d78f9bfcb cert-manager 217d
replicaset.apps/cert-manager-webhook-dnspod-7c5cd575fc cert-manager 277d
app.catalog.cattle.io/cert-manager cert-manager 270d
app.catalog.cattle.io/cert-manager-webhook-dnspod cert-manager 270d
certificaterequest.cert-manager.io/cert-manager-webhook-dnspod-ca-l57hl cert-manager 277d
certificaterequest.cert-manager.io/cert-manager-webhook-dnspod-webhook-tls-7zwdh cert-manager 277d
certificaterequest.cert-manager.io/cert-manager-webhook-dnspod-webhook-tls-gs57f cert-manager 34d
certificaterequest.cert-manager.io/ewhisper-crt-6v6s4 cert-manager 209d
certificaterequest.cert-manager.io/ewhisper-crt-89n7g cert-manager 23d
certificaterequest.cert-manager.io/ewhisper-crt-8g496 cert-manager 277d
certificaterequest.cert-manager.io/ewhisper-crt-jj24l cert-manager 83d
certificaterequest.cert-manager.io/ewhisper-crt-q8pvw cert-manager 149d
certificate.cert-manager.io/cert-manager-webhook-dnspod-ca cert-manager 277d
certificate.cert-manager.io/cert-manager-webhook-dnspod-webhook-tls cert-manager 277d
certificate.cert-manager.io/ewhisper-crt cert-manager 277d
issuer.cert-manager.io/cert-manager-webhook-dnspod-ca cert-manager 277d
issuer.cert-manager.io/cert-manager-webhook-dnspod-selfsign cert-manager 277d
endpointslice.discovery.k8s.io/cert-manager-9lm6j cert-manager 277d
endpointslice.discovery.k8s.io/cert-manager-webhook-dnspod-q7f8n cert-manager 277d
endpointslice.discovery.k8s.io/cert-manager-webhook-z6qdd cert-manager 277d
rolebinding.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving cert-manager 277d
role.rbac.authorization.k8s.io/cert-manager-webhook:dynamic-serving cert-manager 277d
ingressroute.traefik.containo.us/alertmanager cert-manager 244d
ingressroute.traefik.containo.us/grafana cert-manager 255d
ingressroute.traefik.containo.us/grafana-rancher cert-manager 238d
ingressroute.traefik.containo.us/prometheus cert-manager 244d
ingressroute.traefik.containo.us/rsshub cert-manager 268d
ingressroute.traefik.containo.us/ttrss cert-manager 257d
tlsstore.traefik.containo.us/default cert-manager 268d

Try force deletion

If NameSpace is already in terminating status, and can not be deleted for a long time, you can try to add these 2 parameters to force the deletion:

  • --force
  • --grace-period=0
1
kubectl delete ns ${NAMESPACE} --force --grace-period=0

Force delete failed? Let’s try this again

Force delete failed? Try this again:Call the Kubernetes API to delete

Hard Way steps

First, get the JSON file where you want to delete NameSpace:

1
2
NAMESPACE=cert-manager
kubectl get ns ${NAMESPACE} -o json > namespace.json

Then, edit namespace.jsonfrom finalizers field delete kubernetes and save, an example is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
...: ...
},
"spec": {
"finalizers": []
},
"status": {
"phase": "Terminating"
}
}

After that, it can be passed kubectl proxy Set the ephemeral IP and port for APIServer

1
kubectl proxy --port=6880 &

Finally, make an API call to force the deletion:

1
curl -k -H "Content-Type: application/json" -X  PUT --data-binary @namespace.json http://127.0.0.1:6880/api/v1/namespaces/${NAMESPACE}/finalize

Verify that the deletion was successful:

1
kubectl get ns ${NAMESPACE}

Scripted

📝Notes:

Dependent components:

  • kubectl
  • jq
  • curl

force-delete-ns.sh

1
2
3
4
5
6
7
8
#!/bin/bash
set -ex
PATH=$PATH:.
NAMESPACE=$1 # 读取命令行第一个参数
kill -9 $(ps -ef|grep proxy|grep -v grep |awk '{print $2}')
kubectl proxy --port=6880 &
kubectl get namespace ${NAMESPACE} -o json |jq '.spec = {"finalizers":[]}' > namespace.json
curl -k -H "Content-Type: application/json" -X PUT --data-binary @namespace.json 127.0.0.1:6880/api/v1/namespaces/${NAMESPACE}/finalize

Examples of how to use it:

1
bash force-delete-ns.sh cert-manager

🎉🎉🎉

summary

It is often encountered that the NameSpace of Kubernetes cannot be deleted, how should I solve it? Here are 3 scenarios:

  1. Try not to have the above situation (😑 eh… nonsense)
  2. plus --force flag Force deletion
  3. Call the namespace’s finalize API to force the deletion

However, when it comes to the stage where it needs to be forcefully deleted, 2/3 of the parts cannot be guaranteed to be 100% successful.
So the first step is the right way … (Stay, but useful)

EOF


What should I do if Kubernetes'NameSpace can't be deleted?
https://e-whisper.com/posts/33147/
Author
east4ming
Posted on
December 4, 2022
Licensed under