我有一个“卡住”的名称空间,我删除显示在这个永恒的“终止”状态。


当前回答

编辑: 不建议删除终结器。 正确的做法是:

删除命名空间下的所有资源。

Github问题链接

我通常的工作空间是一个小的k8s集群,我经常破坏并重新构建它,这就是为什么删除终结器方法适合我。

原来的答案:我经常遇到同样的问题。

这就是我的工作

kubectl get ns your-namespace -o json > ns-without-finalizers.json

编辑ns-without-finalizers.json。将所有终结器替换为空数组。

运行kubectl代理(通常在另一个终端上运行)

然后curl这个命令

curl -X PUT http://localhost:8001/api/v1/namespaces/your-namespace/finalize -H "Content-Type: application/json" --data @ns-without-finalizers.json

其他回答

我尝试了3-5个选项来删除ns,但只有这一个对我有用。

这个sh文件将删除所有处于终止状态的名称空间

$ 我们 force-delete-namespaces.sh

$chmod +x force-delete-namespaces.sh

美元。/ force-delete-namespaces.sh

#!/usr/bin/env bash

set -e
set -o pipefail

kubectl proxy &
proxy_pid="$!"
trap 'kill "$proxy_pid"' EXIT

for ns in $(kubectl get namespace --field-selector=status.phase=Terminating --output=jsonpath="{.items[*].metadata.name}"); do
    echo "Removing finalizers from namespace '$ns'..."
    curl -H "Content-Type: application/json" -X PUT "127.0.0.1:8001/api/v1/namespaces/$ns/finalize" -d @- \
        < <(kubectl get namespace "$ns" --output=json | jq '.spec = { "finalizers": [] }')

    echo
    echo "Force-deleting namespace '$ns'..."
    kubectl delete namespace "$ns" --force --grace-period=0 --ignore-not-found=true
done

调试类似的问题。

有两件重要的事情需要考虑:

1)在从命名空间中删除终结器之前要三思,因为可能有一些资源您不想自动删除,或者至少要了解为了排除故障而删除了哪些资源。

2)像kubectl api-resources——verbs=list这样的命令可能不会提供由外部crds创建的资源。


在我的例子中:

我用kubectl编辑ns <ns-name>,在状态->条件下,我看到我安装的一些外部crds未能被删除,因为它们添加了定义的终结器:

 - lastTransitionTime: "2021-06-14T11:14:47Z"
    message: 'Some content in the namespace has finalizers remaining: finalizer.stackinstall.crossplane.io
      in 1 resource instances, finalizer.stacks.crossplane.io in 1 resource instances'
    reason: SomeFinalizersRemain
    status: "True"
    type: NamespaceFinalizersRemaining

将ambassador替换为您的名称空间

检查名称空间是否卡住

kubectl get ns ambassador

NAME         STATUS        AGE
ambassador   Terminating   110d

这个卡了很久了

打开管理终端/cmd提示符或powershell并运行

kubectl代理

这将启动本地web服务器

打开另一个终端并运行

kubectl get ns ambassador -o json >tmp.json

编辑tmp文件。Json使用vi或nano

从这个

{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": {
    "annotations": {
        "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"ambassador\"}}\n"
    },
    "creationTimestamp": "2021-01-07T18:23:28Z",
    "deletionTimestamp": "2021-04-28T06:43:41Z",
    "name": "ambassador",
    "resourceVersion": "14572382",
    "selfLink": "/api/v1/namespaces/ambassador",
    "uid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"spec": {
    "finalizers": [
        "kubernetes"
    ]
},
"status": {
    "conditions": [
        {
            "lastTransitionTime": "2021-04-28T06:43:46Z",
            "message": "Discovery failed for some groups, 3 failing: unable to retrieve the complete list of server APIs: compose.docker.com/v1alpha3: an error on the server (\"Internal Server Error: \\\"/apis/compose.docker.com/v1alpha3?timeout=32s\\\": Post https://0.0.0.1:443/apis/authorization.k8s.io/v1beta1/subjectaccessreviews: write tcp 0.0.0.0:53284-\u0026gt;0.0.0.0:443: write: broken pipe\") has prevented the request from succeeding, compose.docker.com/v1beta1: an error on the server (\"Internal Server Error: \\\"/apis/compose.docker.com/v1beta1?timeout=32s\\\": Post https://10.96.0.1:443/apis/authorization.k8s.io/v1beta1/subjectaccessreviews: write tcp 0.0.0.0:5284-\u0026gt;10.96.0.1:443: write: broken pipe\") has prevented the request from succeeding, compose.docker.com/v1beta2: an error on the server (\"Internal Server Error: \\\"/apis/compose.docker.com/v1beta2?timeout=32s\\\": Post https://0.0.0.0:443/apis/authorization.k8s.io/v1beta1/subjectaccessreviews: write tcp 1.1.1.1:2284-\u0026gt;0.0.0.0:443: write: broken pipe\") has prevented the request from succeeding",
            "reason": "DiscoveryFailed",
            "status": "True",
            "type": "NamespaceDeletionDiscoveryFailure"
        },
        {
            "lastTransitionTime": "2021-04-28T06:43:49Z",
            "message": "All legacy kube types successfully parsed",
            "reason": "ParsedGroupVersions",
            "status": "False",
            "type": "NamespaceDeletionGroupVersionParsingFailure"
        },
        {
            "lastTransitionTime": "2021-04-28T06:43:49Z",
            "message": "All content successfully deleted",
            "reason": "ContentDeleted",
            "status": "False",
            "type": "NamespaceDeletionContentFailure"
        }
    ],
    "phase": "Terminating"
}

}

to

    {
  "apiVersion": "v1",
  "kind": "Namespace",
  "metadata": {
    "annotations": {
      "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Namespace\",\"metadata\":{\"annotations\":{},\"name\":\"ambassador\"}}\n"
    },
    "creationTimestamp": "2021-01-07T18:23:28Z",
    "deletionTimestamp": "2021-04-28T06:43:41Z",
    "name": "ambassador",
    "resourceVersion": "14572382",
    "selfLink": "/api/v1/namespaces/ambassador",
    "uid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "spec": {
    "finalizers": []
  }
}

通过删除终结器中的状态和kubernetes

现在使用该命令并用您的名称空间替换ambassador

curl -k -H "Content-Type: application/json" -X PUT --data-binary @tmp.json http://127.0.0.1:8001/api/v1/namespaces/ambassador/finalize

运行之前,您将看到另一个json

然后运行命令

 kubectl get ns ambassador
Error from server (NotFound): namespaces "ambassador" not found

如果它仍然显示终止或任何其他错误,请确保以适当的方式格式化json,并再次尝试上述步骤。

假设你已经尝试过强制删除资源,比如: Pods卡在终止状态,你在你的智慧的尽头试图恢复命名空间…

您可以强制删除命名空间(可能会留下悬空资源):

(
NAMESPACE=your-rogue-namespace
kubectl proxy &
kubectl get namespace $NAMESPACE -o json |jq '.spec = {"finalizers":[]}' >temp.json
curl -k -H "Content-Type: application/json" -X PUT --data-binary @temp.json 127.0.0.1:8001/api/v1/namespaces/$NAMESPACE/finalize
)

这是对这里的答案的改进,它是基于这里的评论。 我正在使用jq实用程序以编程方式删除终结器部分中的元素。你可以手动来做。 Kubectl代理默认在127.0.0.1:8001上创建监听器。如果您知道集群主机的主机名/IP,则可以使用该主机名/IP。 有趣的是,即使使用kubectl编辑器进行相同的更改也没有效果,这种方法似乎仍然有效。

完成nobar已经很棒的回答。如果您使用Rancher部署集群,则需要注意。

牧场主部署改变每一个api调用,prepending /k8s/clusters/c-XXXXX/到url。

rancher上集群的id (c-XXXXX)可以很容易地从rancher UI中获得,因为它将出现在URL中。

所以在你得到集群id c-xxxx之后,就按照nobar说的去做,只是改变api调用,包括rancher位。

(
NAMESPACE=your-rogue-namespace
kubectl proxy &
kubectl get namespace $NAMESPACE -o json |jq '.spec = {"finalizers":[]}' >temp.json
curl -k -H "Content-Type: application/json" \
  -X PUT --data-binary @temp.json \
  127.0.0.1:8001/k8s/clusters/c-XXXXX/api/v1/namespaces/$NAMESPACE/finalize
)