Pod 停止予算によってブロックされたノードを削除する

特定の条件下では、Pod 停止予算(PDB)ポリシーにより、ノードプールからノードが正常に削除されない場合があります。そのような状況下では、ノード ステータスは削除されても Ready,SchedulingDisabled を通知します。

Pod 停止予算は、使用可能な Pod の数と競合します。

PDB ポリシーは、システムを変更する際に Pod が同時に停止しないようにすることで、アプリのパフォーマンスを保証します。その結果、PDB ポリシーは、複製されたアプリケーションで同時に使用できない Pod の数を制限します。

ただし、ノードを削除することで、ポリシーに違反する可能性がある場合、PDB ポリシーにより、ノードの削除ができないことがあります。

例えば、PDF ポリシーで、システム内で使用可能な Pod は、常に 2 つであると定義できます。(.spec.minAvailable が 2)。ただし、Pod が 2 つしかない場合、その内の 1 つを含むノードを削除しようとすると、PDB ポリシーが有効になり、ノードの削除が妨げられます。

同様に、PDB ポリシーで、使用できない Pod がない(.spec.maxUnavailable が 0)と定義すると、そのポリシーにより関連するノードはどれも削除が妨げられます。一度に 1 つの Pod を削除しようとしても、PDB ポリシーにより、影響を受けるノードを削除することはできません。

回避策: PDB ポリシーを無効にして、また再度有効にする

この競合を解決するには、PDB ポリシーのバックアップを作成してから削除します。PDB が正常に削除されると、ノードがドレインされ、関連する Pod が削除されます。必要な修正を加えたら、PDB ポリシーを再度有効にできます。

次の例は、この条件のノードを削除する方法を示しています。このノードは、あらゆる種類の GKE on Bare Metal クラスタ(管理クラスタ、ハイブリッド クラスタ、スタンドアロン クラスタ、ユーザー クラスタ)に影響を与える可能性があります。

同様の手順を、すべてのクラスタ タイプに適用できます。ただし、管理クラスタ ノードプール(管理クラスタ、ハイブリッド クラスタ、またはスタンドアロン クラスタ)からノードを削除する特定のコマンドは、ユーザー クラスタ ノードプールからノードを削除するコマンドとは若干異なります。

クラスタ タイプ別のコマンド バリエーション

読みやすくするため、次のコマンドのプレースホルダ ${KUBECONFIG} に注意してください。クラスタの種類に応じて、管理クラスタの kubeconfig(ADMIN_KUBECONFIG)または、ユーザー クラスタの kubeconfig(USER_CLUSTER_CONFIG)パスを $(KUBECONFIG) にエクスポートし、以下の手順に従います。

  • ユーザー クラスタからノードプールを削除するには、export KUBECONFIG=USER_CLUSTER_CONFIG
  • 管理クラスタからノードを削除するには、export KUBECONFIG=ADMIN_KUBECONFIG
  1. (省略可)ユーザー クラスタ ノードプールからノードを削除する場合は、次のコマンドを実行してユーザー クラスタ kubeconfig ファイルを抽出します。変数 ADMIN_KUBECONFIG は管理クラスタ kubeconfig へのパスを指定し、変数 USER_CLUSTER_NAME はクラスタの名前を指定します。

    kubectl --kubeconfig ADMIN_KUBECONFIG -n cluster-USER_CLUSTER_NAME  \
    get secret USER_CLUSTER_NAME-kubeconfig  \
    -o 'jsonpath={.data.value}' | base64 -d > USER_CLUSTER_CONFIG
    
  2. ノードプールからノードを削除した後、ノードのステータスを確認します。影響を受けるノードは、Ready, SchedulingDisabled を報告します。

    kubectl get nodes --kubeconfig ${KUBECONFIG}
    

    ノードのステータスは次のようになります。

    NAME        STATUS                    ROLES      AGE      VERSION
    abmnewCP2   Ready                     Master     11m      v.1.18.6-gke.6600
    abmnewCP3   Ready,SchedulingDisabled  <none>     9m22s    v.1.18.6-gke.6600
    abmnewCP4   Ready                     <none>     9m18s    v.1.18.6-gke.6600
    
  3. クラスタ内の PDB を確認します。

    kubectl get pdb --kubeconfig ${KUBECONFIG} -A
    

    システムにより、次のような PDB が通知されます。

    NAMESPACE     NAME             MIN AVAILABLE    MAX UNAVAILABLE   ALLOWED DISRUPTIONS   AGE
    gke-system    istio-ingress    1                N/A               1                     19m
    gke-system    istiod           1                N/A               1                     19m
    kube-system   coredns          1                N/A               0                     19m
    kube-system   log-aggregator   N/A              0                 0                     19m
    kube-system   prometheus       N/A              0                 0                     19m
     ```
    
  4. PDB を検査します。PDB 内の Pod ラベルと、ノード内の一致する Pod の間で照合する必要があります。この照合により、正しい PDB を無効にしてノードを正常に削除できます。

    kubectl --kubeconfig ${KUBECONFIG} get pdb log-aggregator -n kube-system -o 'jsonpath={.spec}'
    

    PDB ポリシー内の一致するラベルの結果がシステムによって返されます。

    {"maxUnavailable":0,"selector":{"matchLabels":{"app":"stackdriver-log-aggregator"}}}
    
  5. PDB ポリシーラベルと一致する Pod を検索します。

    kubectl --kubeconfig ${KUBECONFIG} get pods -A --selector=app=stackdriver-log-aggregator  \
    -o=jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.nodeName}{"\n"}{end}'
    

    このコマンドは、PDB ラベルと一致する Pod のリストを返します。また、削除する必要がある PDB ポリシーを検証します。

    stackdriver-log-aggregator-0    abmnewCP3
    stackdriver-log-aggregator-1    abmnewCP3
    
  6. 該当する Pod を確認した後、PDB ポリシー(この例では log-aggregator ポリシー)のバックアップ コピーを作成します。

    kubectl get pdb log-aggregator --kubeconfig ${KUBECONFIG} -n kube-system  \
    -o yaml >> log-aggregator.yaml
    
  7. 特定の PDB ポリシー(この場合は log-aggregator ポリシー)を削除します。

    kubectl delete pdb log-aggregator --kubeconfig ${KUBECONFIG} -n kube-system
    

    PDB ポリシーを削除すると、ノードがドレインを開始します。ただし、ノードが完全に削除されるまでに時間がかかることがあります(最大 30 分)。このため、ノードのステータスのチェックが続きます。

    ノードを完全に削除し、ノードに関連付けられたストレージ リソースも削除するには、PDB ポリシーを復元する前に行います。ストレージ リソースの削除をご覧ください。

  8. コピーから PDB ポリシーを復元します。

    kubectl apply -f log-aggregator.yaml --kubeconfig ${KUBECONFIG}
    
  9. 削除された Pod が正常に再作成されていることを確認します。この例では、2 つの stackdriver-log-aggregator-x Pod がある場合、どちらも再作成されます。

    kubectl get pods -o wide --kubeconfig ${KUBECONFIG} -A
    

ノードを復元する場合は、ノードプール構成を適切に編集し、ノード IP アドレスを復元します。

完全に削除されたノードからストレージ リソースを削除する

ノードを完全に削除した後に、そのノードをシステムに復元しない場合は、そのノードに関連付けられているストレージ リソースを削除することもできます。

次のコマンドでは、以下の変数にご注意ください。

  • ADMIN-KUBECONFIG は、管理クラスタのパスを指定します。
  • USER_CLUSTER_CONFIG は、クラスタ構成 YAML ファイルへのパスを指定します。
  1. ノードに関連付けられた永続ボリューム(PV)の名前を確認し、取得します。

    kubectl get pv --kubeconfig ${KUBECONFIG}  \
    -A -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{.spec.claimRef.name}{":\t}  \
    {.spec.nodeAffinity.required.nodeSelectorTerms[0].matchExpressions[0].values}{"\n"}{end}'
    
  2. ノードに関連付けられた PV を削除します。

    kubectl delete pv PV_NAME --kubeconfig ${KUBECONFIG}