はじめに
先日個人的な興味でKubevirtを少し触っておりました。その中で、いったん全部のリソースを削除し、最初からやり直そうとしておりました。その中で、namespace
リソースを削除してもTerminating
の状態で止まる状態になってしまいました。これを削除するため色々と調べ、無事に削除することができました。今回は調べたことを一旦まとめておきたいと思い、やったことと参考ドキュメントを残しておきました。
結論
kubevirt-operator
を削除したとき、namespace kubevirt
以外のリソースは削除されたが、namespace
はTermintaing
のまま残り続けた。- いろいろやった結果、最終的にはjsonコンフィグを用意して
curl
コマンドで直接APIを叩き、finalizer
の状態を[]
にしてあげることで削除できた。
起こったこと
Kubevirtの基本的な利用方法は公式ドキュメントに記載されています。これを削除するため、紹介されたリソースを順番に削除していき、最後にkubevirt-operator
を削除しました。
[root@kube-master01 kubevirt]# kubectl delete -f https://github.com/kubevirt/kubevirt/releases/download/v0.20.2/kubevirt -operator.yaml namespace "kubevirt" deleted customresourcedefinition.apiextensions.k8s.io "kubevirts.kubevirt.io" deleted clusterrole.rbac.authorization.k8s.io "kubevirt.io:operator" deleted serviceaccount "kubevirt-operator" deleted clusterrole.rbac.authorization.k8s.io "kubevirt-operator" deleted clusterrolebinding.rbac.authorization.k8s.io "kubevirt-operator" deleted deployment.apps "virt-operator" deleted ^C [root@kube-master01 kubevirt]#
この操作がいつまでも処理が完了せずCtrl+C
で中断したので、この時点で何かおかしいことに気付くべきでした。が、ひとまず削除すべきリソースは削除したはずなので、リソースの状態を確認しておりました。
[root@kube-master01 kubevirt]# kubectl get ns NAME STATUS AGE default Active 42d kube-node-lease Active 42d kube-public Active 42d kube-system Active 42d kubevirt Terminating 20d metallb-system Active 42d [root@kube-master01 kubevirt]#
この時点で初めてnamespace kubevirt
が削除されていないことに気づきました。kubectl
コマンドで他を確認してみると、namespace
リソース以外はすべて削除されていることがわかりました。
ここからnamespace
リソースを削除する方法をいろいろと試していきます。
0. Namespace kubevirtを確認する
まずは残存しているnamespace
リソースの状態を確認します。
[root@kube-master01 ~]# kubectl get namespace kubevirt -o yaml apiVersion: v1 kind: Namespace metadata: creationTimestamp: "2019-08-25T09:29:05Z" deletionTimestamp: "2019-09-15T00:38:00Z" labels: kubevirt.io: "" name: kubevirt resourceVersion: "672268" selfLink: /api/v1/namespaces/kubevirt uid: 371fbd92-d232-45f4-ba4e-2cec041e25f7 spec: finalizers: - kubernetes status: phase: Terminating
1. kubectl delete namespaceを試す
まずはnamespace
の削除をもう一度試してみます。
[root@kube-master01 kubevirt]# kubectl delete namespace kubevirt Error from server (Conflict): Operation cannot be fulfilled on namespaces "kubevirt": The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system. [root@kube-master01 kubevirt]#
エラーメッセージが表示され、削除に失敗します。
2. --grace-period=0 --force
オプションを付与してdelete
まずは強制的にリソースを削除することのできるkubectl
コマンドのオプションを利用してみました。
Podなどのリソースを削除する際、--grace-period=0 --force
オプションを付与してdelete
コマンドを実行すると、即時削除が実行されます。これを```namespace````リソースに対して実行してみます。
※参照リンク:
StackOverflow - Pods stuck in Terminating status
[root@kube-master01 ~]# kubectl delete namespace kubevirt --grace-period=0 --force warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely. Error from server (Conflict): Operation cannot be fulfilled on namespaces "kubevirt": The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system. [root@kube-master01 ~]#
1. kubectl delete namespaceを試す
での実行結果と同じメッセージが出力されました。やはり削除はされません。
3. kubectl edit namespace
でfinalize
を編集
次にnamespace kubevirt
リソースに含まれるfinalizers
という項目の値を変更しようとしました。
finalizer
はCRD(CustomResourceDefinition)の拡張機能の一つで、kubectl delete
によるリソース削除前の処理を定義することができます。もう一度namespace kubevirt
リソースの状態を確認してみます。
[root@kube-master01 ~]# kubectl get namespace kubevirt -o yaml apiVersion: v1 kind: Namespace metadata: creationTimestamp: "2019-08-25T09:29:05Z" deletionTimestamp: "2019-09-15T00:38:00Z" labels: kubevirt.io: "" name: kubevirt resourceVersion: "672268" selfLink: /api/v1/namespaces/kubevirt uid: 371fbd92-d232-45f4-ba4e-2cec041e25f7 spec: finalizers: - kubernetes status: phase: Terminating
ここではfinalizers
にkubernetes
と記載がされています。finalizers
はリソース削除前の処理を定義するものなので、逆に言えばここに記載された内容の処理が完了しないと、(おそらくですが)リソースは削除されません。
先ほど1. kubectl delete namespaceを試す
でnamespace kubevirt
を削除しようとしたときに出力されたメッセージをもう一度見ると、Operation cannot be fulfilled on namespaces "kubevirt": The system is ensuring all content is removed from this namespace.
と表示されています。これを見ても、finalizers
の処理内容が完了していないのでリソースが削除できない、というように読み取れました。
※このあたりの理解はまだまだ浅いので、後ほど修正する可能性があります。
[root@kube-master01 kubevirt]# kubectl delete namespace kubevirt Error from server (Conflict): Operation cannot be fulfilled on namespaces "kubevirt": The system is ensuring all content is removed from this namespace. Upon completion, this namespace will automatically be purged by the system. [root@kube-master01 kubevirt]#
なのでnamespace kubevirt
リソースのうちfinalizers
の記載内容を変更すればよいのでは、と考えました。
※参考リンク:
StackOverflow - Namespace “stuck” as Terminating, How do I remove it?#52369248
[root@kube-master01 ~]# kubectl edit namespace kubevirt ※以下の部分を削除 【編集前】 spec: finalizers: - kubernetes status: 【編集後】 spec: finalizers: [] status: namespace/kubevirt edited [root@kube-master01 ~]# kubectl get ns NAME STATUS AGE default Active 42d kube-node-lease Active 42d kube-public Active 42d kube-system Active 42d kubevirt Terminating 20d metallb-system Active 42d [root@kube-master01 ~]# # namespaceの状態をもう一度確認 [root@kube-master01 ~]# kubectl get namespace kubevirt -o yaml apiVersion: v1 kind: Namespace metadata: creationTimestamp: "2019-08-25T09:29:05Z" deletionTimestamp: "2019-09-15T00:38:00Z" labels: kubevirt.io: "" name: kubevirt resourceVersion: "672268" selfLink: /api/v1/namespaces/kubevirt uid: 371fbd92-d232-45f4-ba4e-2cec041e25f7 spec: finalizers: - kubernetes status: phase: Terminating [root@kube-master01 ~]#
これも削除されませんでした。というよりkubectl edit
の実行結果が反映されていません。
4. jsonコンフィグを用意してcurl
コマンド実行
次の方法として、kubectl
コマンドを使わず、直接Kubernetes APIを叩き、リソースに対する処理を実行する方法があります。
Kubernetesではkubectl
コマンドを利用してリソースに対する処理を行うことが広く利用される方法ですが、Kubernetes自身がAPIを提供しており、kubectl
ではそのAPIを通して処理を行います(実際はKubernetes APIを構成するkube-apiserver
に対してリクエストを送り、リソースに対する処理を行います)。なのでKubernetes APIを直接指定することでリソースに対する操作を行うこともできます。
※参考リンク:
StackOverflow - Namespace “stuck” as Terminating, How do I remove it?
[小ネタ]Kubernetesで消せないNamespaceが発生した場合の対処方法
# namespaceをjson形式で出力する [root@kube-master01 ~]# kubectl get namespace kubevirt -o json { "apiVersion": "v1", "kind": "Namespace", "metadata": { "creationTimestamp": "2019-08-25T09:29:05Z", "deletionTimestamp": "2019-09-15T00:38:00Z", "labels": { "kubevirt.io": "" }, "name": "kubevirt", "resourceVersion": "672268", "selfLink": "/api/v1/namespaces/kubevirt", "uid": "371fbd92-d232-45f4-ba4e-2cec041e25f7" }, "spec": { "finalizers": [ "kubernetes" ] }, "status": { "phase": "Terminating" } } [root@kube-master01 ~]# # 上記出力結果をjsonフォーマットで保存し、finalizersの記載を変更する [root@kube-master01 ~]# vi ns-kubevirt.json [root@kube-master01 ~]# cat ns-kubevirt.json { "apiVersion": "v1", "kind": "Namespace", "metadata": { "creationTimestamp": "2019-08-25T09:29:05Z", "deletionTimestamp": "2019-09-15T00:38:00Z", "labels": { "kubevirt.io": "" }, "name": "kubevirt", "resourceVersion": "672268", "selfLink": "/api/v1/namespaces/kubevirt", "uid": "371fbd92-d232-45f4-ba4e-2cec041e25f7" }, "spec": { "finalizers": [ # ここを空欄にする ] }, "status": { "phase": "Terminating" } } [root@kube-master01 ~]# # curlコマンドでKubernetes APIを操作 [root@kube-master01 ~]# kubectl proxy & [1] 18132 [root@kube-master01 ~]# Starting to serve on 127.0.0.1:8001 [root@kube-master01 ~]# [root@kube-master01 ~]# curl -k -H "Content-Type: application/json" -X PUT --data-binary @ns-kubevirt.json http://127.0.0.1:8001/api/v1/namespaces/kubevirt/finalize { "kind": "Namespace", "apiVersion": "v1", "metadata": { "name": "kubevirt", "selfLink": "/api/v1/namespaces/kubevirt/finalize", "uid": "371fbd92-d232-45f4-ba4e-2cec041e25f7", "resourceVersion": "672268", "creationTimestamp": "2019-08-25T09:29:05Z", "deletionTimestamp": "2019-09-15T00:38:00Z", "labels": { "kubevirt.io": "" } }, "spec": { }, "status": { "phase": "Terminating" } }[root@kube-master01 ~]# [root@kube-master01 ~]# kubectl get ns NAME STATUS AGE default Active 42d kube-node-lease Active 42d kube-public Active 42d kube-system Active 42d metallb-system Active 42d [root@kube-master01 ~]#
無事にnamespace kubevirt
が削除されました。
最後に
今回はcurl
コマンドで直接APIを操作し、Kubernetesリソースを削除する方法を知ることができました。この方法はKubernetesのリソースに対して広く利用できる方法なので、リソースを操作できない場合の最終手段?として、覚えておいて損はないでしょう。
またそれに限らず、今回試した4つの方法は、どこか別のシチュエーションで役立つこともあると思いますので、しっかり覚えておこうと思います。
参考ドキュメント
StackOverflow - Pods stuck in Terminating status
StackOverflow - Namespace “stuck” as Terminating, How do I remove it?
[小ネタ]Kubernetesで消せないNamespaceが発生した場合の対処方法
KubernetesのCRDまわりを整理する。#finalizer
Extend the Kubernetes API with CustomResourceDefinitions #finalizers