删除namespace为什么会Terminating?

2021-03-16 15:08:43 浏览数 (1)

当我们删除集群中的某个namespace之后,有时候namespace并没有按照我们的期望正常删除,而是一直卡在Terminating状态。本文主要讨论下Terminating状态发生的可能性以及解决办法。

删除namespace后发生了什么

我们从kubectl delele namespace动作开始,当执行了删除命名空间的动作后,k8s并不会直接删除该命名空间,而是设置了namespace对象的metadata.deleteTimestasp字段,然后kube-controlller-manager组件中的namespace-controller开始工作,负责执行namespace删除的相关事宜,比如清理被删除命名空间下面的资源等,最后才会删除该命名空间,而如果namespace-controller有报错或者没有走到终止流程,就会一直卡在Terminating状态。

接下来先描述下namespace-controller的工作流程,如图所示:

image.pngimage.png

可能原因1:资源发现

k8s的api组织形式

k8s使用的是声明式API,其中API是通过分组、版本、资源名组成,而谈论某个资源,必须要属于某个API分组/版本,比如通过yaml创建对象时,除了要声明Kind外,还需要声明apiVersion对象。

代码语言:txt复制
# 查看资源
$ kubectl api-resources [-o wide]
# 查看API版本
$ kubectl api-versions

聚合层扩展kubernetes api

聚合层通常用于扩展k8s api-server,允许添加新的API分组/版本。用户通过创建apiService对象来注册API,并声明自定义的扩展apiserver,当请求到该API分组/版本的时候,k8s apiservice会代理转发到后端自定义的apiserver来处理。比如,TKE集群中的hpa-metrics-server,就实现了metrics.k8s.io/v1beta1 这个API分组/版本(用户也可以部署promethues的metrics-adapter进行替换)。

在资源发现这里,会先获取API分组/版本信息,然后再获取各个API分组/版本的资源信息,从而罗列出集群中的所有资源。如果罗列资源发生报错,也有可能导致namespace卡主Terminating状态,常见于聚合层扩展kubernetes api。

1、查看是namespace 卡主Terminating的原因

代码语言:txt复制
$ kubectl get namespace <name> -o yaml
conditions:
  - lastTransitionTime: "2021-03-12T12:46:17Z"
    message: 'Discovery failed for some groups, 1 failing: unable to retrieve the
      complete list of server APIs: webhook.cert-manager.io/v1beta1: the server is
      currently unable to handle the request'
    reason: DiscoveryFailed
    status: "True"
    type: NamespaceDeletionDiscoveryFailure

2、查看apiservice的状态

代码语言:txt复制
$ kubectl get apiservice
NAME                                   SERVICE                             AVAILABLE                 AGE
v1beta1.webhook.cert-manager.io        cert-manager/cert-manager-webhook   False (ServiceNotFound)   3d23h

3、将异常的apiservice状态恢复成True或者删除不需要的apiservice,即可恢复。

可能原因2:finalizer

finalizer导致namespace Terminating一般主要集群中以下两种情况:

1 namespace资源对象的spec.finalizer[] 列表中不为空

解决办法:手动清理

代码语言:txt复制
$ kubectl get ns delete-me -o json | jq '.spec.finalizers=[]' > ns-without-finalizers.json
cat ns-without-finalizers.json
$ kubectl proxy &
$ PID=$!
$ curl -X PUT http://localhost:8001/api/v1/namespaces/delete-me/finalize -H "Content-Type: application/json" --data-binary @ns-without-finalizers.json
$ kill $PID

相关链接:https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/namespaces.md#rest-api

2 namespace资源对象的metadata.finalizer[] 列表不为空

比如:将集群托管到rancher管理后,rancher就会写finalizer到metadata.finalizer[] 列表,而当集群脱离rancher管理之后,手动删除namespace,往往就会发生Terminating

解决办法:

代码语言:txt复制
$ kubelet edit ns <name> #将metadata.finalizer[]列表删除

0 人点赞