名前空間が Terminating 状態でスタックする

症状

名前空間が Terminating 状態でスタックする

原因

Kubernetes API 拡張機能が使用可能でない場合、その拡張機能によって管理されるリソースは削除できません。 API 拡張機能の削除失敗は、名前空間の削除が失敗する原因になります。

問題の解決

削除されていない API の説明を取得します。

以下のステップを実行して、削除されない API の説明を取得します。

  1. Terminating 状態でスタックしている名前空間を表示します。

    kubectl get namespaces
    
  2. 削除されていないリソースを次のように見つけます。

    kubectl api-resources --verbs=list --namespaced -o name | xargs -n 1 kubectl get --show-kind --show-all --ignore-not-found -n <terminating-namespace>
    
  3. 前のコマンドでエラー・メッセージ: unable to retrieve the complete list of server APIs: <api-resource>/<version>: the server is currently unable to handle the request が返される場合、受け取った情報を使用して次のコマンドを実行します。

    kubectl get APIService <version>.<api-resource>
    

    例えば、custom.metrics.k8s.io/v1beta1 という名前の API サービスに対して次のコマンドを実行します。

    kubectl get APIService v1beta1.custom.metrics.k8s.io
    
  4. API サービスのデバッグを続行するため、API サービスの説明を取得します。 次のコマンドを実行します。

    kubectl describe APIService <version>.<api-resource>
    
  5. 問題が解決されたことを確認します。 次のコマンドを実行して、名前空間を削除できることを確認します。

    kubectl get namespace
    

手動で Terminating 状態の名前空間を削除します。

問題が解決しない場合、Terminating 状態でスタックしている名前空間を手動で削除できます。

  1. Terminating 状態でスタックしている名前空間を表示します。

     kubectl get namespaces
    
  2. Terminating 状態の名前空間を選択し、以下のように、finalizer を見つけるために名前空間の内容を表示します。

     kubectl get namespace <terminating-namespace> -o yaml
    

    YAML の内容は、以下のような出力になります。

     apiVersion: v1
     kind: Namespace
     metadata:
       creationTimestamp: 2018-11-19T18:48:30Z
       deletionTimestamp: 2018-11-19T18:59:36Z
       name: <terminating-namespace>
       resourceVersion: "1385077"
       selfLink: /api/v1/namespaces/<terminating-namespace>
       uid: b50c9ea4-ec2b-11e8-a0be-fa163eeb47a5
     spec:
       finalizers:
       - kubernetes
     status:
       phase: Terminating
    
  3. 一時 JSON ファイルを以下のように作成します。

     kubectl get namespace <terminating-namespace> -o json >tmp.json
    
  4. tmp.json ファイルを編集します。 finalizers フィールドから kubernetes 値を削除して、ファイルを保存します。

    tmp.json ファイルは、以下のような出力になります。

      {
          "apiVersion": "v1",
          "kind": "Namespace",
          "metadata": {
              "creationTimestamp": "2018-11-19T18:48:30Z",
              "deletionTimestamp": "2018-11-19T18:59:36Z",
              "name": "<terminating-namespace>",
              "resourceVersion": "1385077",
              "selfLink": "/api/v1/namespaces/<terminating-namespace>",
              "uid": "b50c9ea4-ec2b-11e8-a0be-fa163eeb47a5"
          },
          "spec": {
             "finalizers": 
          },
          "status": {
              "phase": "Terminating"
          }
      }
    
  5. 一時プロキシー IP およびポートを設定するには、以下のコマンドを実行します。 スタックしている名前空間を削除するまで、端末ウィンドウは必ず開いたままにしてください。

     kubectl proxy
    

    プロキシー IP とポートは以下のような出力になります。

     Starting to serve on 127.0.0.1:8001
    
  6. 新規端末ウィンドウから、一時プロキシー IP およびポートを使用して API 呼び出しを行います。

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

    出力は以下の内容のようになります。

     {
       "kind": "Namespace",
       "apiVersion": "v1",
       "metadata": {
         "name": "<terminating-namespace>",
         "selfLink": "/api/v1/namespaces/<terminating-namespace>/finalize",
         "uid": "b50c9ea4-ec2b-11e8-a0be-fa163eeb47a5",
         "resourceVersion": "1602981",
         "creationTimestamp": "2018-11-19T18:48:30Z",
         "deletionTimestamp": "2018-11-19T18:59:36Z"
       },
          "spec": {
    
       },
       "status": {
         "phase": "Terminating"
       }
    }
    

    注: 「finalizer」パラメーターは削除されます。

  7. Terminating 状態の名前空間が削除されたことを以下のように確認します。

     kubectl get namespaces
    
  8. Terminating 状態でスタックしている他の名前空間に対して、引き続きこれらのステップを実行します。