ノードをメンテナンス モードにする

ノードの修復またはメンテナンスが必要な場合は、まずノードをメンテナンス モードにする必要があります。これにより、API サーバーなどの重要なシステム Pod を除き、既存の Pod とワークロードが適切にドレインされます。また、メンテナンス モードでは、ノードが新しい Pod の割り当てを受け取ることはできません。メンテナンス モードでは、Pod トラフィックが中断するリスクなしに、ノードを操作できます。

仕組み

Google Distributed Cloud では、ノードをメンテナンス モードに設定できます。この方法により、他のクラスタ コンポーネントは、ノードがメンテナンス モードであることを正しく認識することができます。ノードをメンテナンス モードにすると、そのノードでは追加の Pod をスケジュールできなくなり、既存の Pod は停止します。

メンテナンス モードを使用する代わりに、特定のノードで kubectl cordonkubectl drain などの Kubernetes コマンドを手動で使用することもできます。

メンテナンス モードのプロセスを使用すると、Google Distributed Cloud は次の処理を行います。

1.29

  • Google Distributed Cloud は、ノード上の新しい Pod のスケジューリングを防ぐため、指定されたノードに baremetal.cluster.gke.io/maintenance:NoSchedule taint を追加します。

  • Google Distributed Cloud は、Eviction API を使用して各 Pod を強制排除します。この方法でノードをドレインした場合、PodDisruptionBudgets(PDB)が適用されます。PDB を構成すると、minAvailablemaxUnavailable フィールドで一連の Pod の許容可能な中断レベルを指定し、ワークロードを保護することができます。この方法でノードをドレインすると、ワークロードの中断に対する保護が強化されます。強制排除ベースのノードドレインは、リリース 1.29 の GA として利用できます。

  • ノードが Pod の停止を待機したままの状態になることを防ぐため、20 分のタイムアウトが適用されます。Pod は、すべての taint を許容するよう構成されている場合、またはファイナライザが設定されている場合、停止できませんGoogle Distributed Cloud はすべての Pod を停止しようとしますが、タイムアウトを超えるとノードがメンテナンス モードになります。このタイムアウトにより、実行中の Pod のアップグレードがブロックされなくなります。

1.28 以前

  • Google Distributed Cloud は、ノード上の新しい Pod のスケジューリングを防ぐため、指定されたノードに baremetal.cluster.gke.io/maintenance:NoSchedule taint を追加します。

  • Google Distributed Cloud は baremetal.cluster.gke.io/maintenance:NoExecute taint を追加します。NoExecute taint として機能することで、Google Distributed Cloud kube-scheduler は Pod を停止し、ノードをドレインします。この方法でノードをドレインした場合、PDB は適用されません。

  • ノードが Pod の停止を待機したままの状態になることを防ぐため、20 分のタイムアウトが適用されます。Pod は、すべての taint を許容するよう構成されている場合、またはファイナライザが設定されている場合、停止できませんGoogle Distributed Cloud はすべての Pod を停止しようとしますが、タイムアウトを超えるとノードがメンテナンス モードになります。このタイムアウトにより、実行中の Pod のアップグレードがブロックされなくなります。

強制排除ベースのドレイン

taint ベースのドレインから強制排除ベースのノードのドレインへの切り替えに関連する手順に変更はありません。この切り替えは、調整ロジックにのみ影響します。

この機能は、サポートされているすべてのバージョンで同じリリース ステージにあるわけではありません。

  • 1.29: GA
  • 1.28: 提供なし
  • 1.16: 提供なし

ドレインの順序

リリース 1.29 より前では、Google Distributed Cloud kube-scheduler による taint ベースのノードドレインでノードから Pod をドレインするときに、特定のアルゴリズムを使用していません。強制排除ベースのノードドレインでは、Pod は優先度に基づいて特定の順序で強制排除されます。次の表に示すように、強制排除の優先度は特定の Pod 条件に関連付けられています。

ドレインの順序 Pod の条件(すべてと一致する必要があります)
1

次の条件に一致する Pod が強制排除されます。

  • spec.prorityClassName のない Pod
  • 既知の Container Storage Interface(CSI)名と一致しない Pod
  • DaemonSet に属していない Pod
2

次の条件に一致する Pod が強制排除されます。

  • DaemonSet に属する Pod
  • PriorityClass が Pod
  • 既知の Container Storage Interface(CSI)名と一致しない Pod
3

次の条件に一致する Pod が強制排除されます。

  • Spec.ProrityClassName のある Pod
  • 既知の Container Storage Interface(CSI)名と一致しない Pod

一致する Pod の強制排除順序は、PriorityClass.value に基づいて低い順に決定されます。

4

Pod がすべて強制排除されたら、CSI が PV / PVC マウントをクリーンアップするまで待ちます。すべてのボリュームがクリーンアップされたことを示すには、Node.Status.VolumesInUse を使用します。

5

次の条件に一致する Pod が強制排除されます。

  • 既知の Container Storage Interface(CSI)名に一致する Pod

kubelet はインプレース アップグレードの互換性を提供していないため、これらの Pod は引き続きドレインする必要があります。

強制排除ベースのノードドレインには PDB が適用されるため、状況によっては、PDB の設定でノードのドレインがブロックされることがあります。ノードプールのドレインに関するトラブルシューティング情報については、ノードが長期間ドレインされている理由を確認するをご覧ください。

強制排除ベースのノードのドレインを無効にする

マイナー バージョン 1.29 のクラスタ、またはマイナー バージョン 1.29 にアップグレードされるクラスタでは、強制排除ベースのノードドレインはデフォルトで有効になっています。強制排除ベースのノードドレインが原因で、クラスタのアップグレードやクラスタのメンテナンスで問題が発生している場合は、クラスタ リソースに baremetal.cluster.gke.io/maintenance-mode-ignore-pdb: true アノテーションを追加して、taint ベースのノードドレインに戻すことができます。

ノードをメンテナンス モードにする

クラスタ構成ファイルの maintenanceBlocks で選択したノードの IP 範囲を指定して、メンテナンス モードにするノードを選択します。選択するノードは、準備完了状態で、クラスタで機能している必要があります。

ノードをメンテナンス モードにするには:

  1. クラスタ構成ファイルを編集して、メンテナンス モードにするノードを選択します。

    任意のエディタで構成ファイルを編集するか、次のコマンドを実行して、クラスタのカスタム リソースを直接編集します。

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME

    次のように置き換えます。

    • CLUSTER_NAMESPACE: クラスタの Namespace。
    • CLUSTER_NAME: クラスタの名前。
  2. クラスタ構成ファイルに maintenanceBlocks セクションを追加して、メンテナンス モードにするノードの単一の IP アドレスまたはアドレス範囲を指定します。

    次のサンプルでは、IP アドレスの範囲を指定して複数のノードを選択する方法を示します。

    metadata:
      name: my-cluster
      namespace: cluster-my-cluster
    spec:
      maintenanceBlocks:
        cidrBlocks:
        - 172.16.128.1-172.16.128.64
    
  3. 更新したクラスタ構成を保存して適用します。

    Google Distributed Cloud がノードをメンテナンス モードに切り替えます。

  4. 次のコマンドを実行して、クラスタ内のノードのステータスを確認します。

    kubectl get nodes --kubeconfig=KUBECONFIG

    出力は次のようになります。

    NAME                STATUS   ROLES           AGE     VERSION
    user-baremetal-01   Ready    control-plane   2d22h   v1.27.4-gke.1600
    user-baremetal-04   Ready    worker          2d22h   v1.27.4-gke.1600
    user-baremetal-05   Ready    worker          2d22h   v1.27.4-gke.1600
    user-baremetal-06   Ready    worker          2d22h   v1.27.4-gke.1600
    

    ノードは引き続きスケジューリング可能ですが、taint によって、Pod(適切な toleration のない)がノードにスケジュールされることがなくなります。

  5. 次のコマンドを実行して、メンテナンス モードになっているノードの数を確認します。

    kubectl get nodepools --kubeconfig ADMIN_KUBECONFIG 
    

    次のようなレスポンスが返されるはずです。

    NAME   READY   RECONCILING   STALLED   UNDERMAINTENANCE   UNKNOWN
    np1    3       0             0         1                  0
    

    このサンプルの UNDERMAINTENANCE 列は、1 つのノードがメンテナンス モードであることを示しています。

    メンテナンス モードになったノードには、Google Distributed Cloud により次の taint も追加されます。

    • baremetal.cluster.gke.io/maintenance:NoExecute
    • baremetal.cluster.gke.io/maintenance:NoSchedule

ノードのメンテナンス モードを解除する

ノードのメンテナンス モードを解除するには:

  1. クラスタの構成ファイルを編集して、メンテナンス モードを解除するノードを消去します。

    任意のエディタで構成ファイルを編集するか、次のコマンドを実行して、クラスタのカスタム リソースを直接編集します。

    kubectl -n CLUSTER_NAMESPACE edit cluster CLUSTER_NAME

    次のように置き換えます。

    • CLUSTER_NAMESPACE: クラスタの Namespace。
    • CLUSTER_NAME: クラスタの名前。
  2. 特定のノードのメンテナンス モードを解除するには、IP アドレスを編集します。また、すべてのノードのメンテナンス モードを解除するには、maintenanceBlocks セクションを削除します。

  3. 更新したクラスタ構成を保存して適用します。

  4. kubectl コマンドを使用して、ノードのステータスを確認します。

クラスタをシャットダウンして再起動する

クラスタ全体を停止する必要がある場合は、次のセクションの手順に沿ってクラスタをシャットダウンし、安全に再起動します。

クラスタをシャットダウンする

ユーザー クラスタを管理するクラスタをシャットダウンする場合は、まず、すべてのマネージド ユーザー クラスタをシャットダウンする必要があります。次の手順は、すべての Google Distributed Cloud クラスタタイプに適用されます。

  1. すべてのクラスタノードのステータスを確認します。

    kubectl get nodes --kubeconfig CLUSTER_KUBECONFIG
    

    CLUSTER_KUBECONFIG は、クラスタの kubeconfig ファイルのパスに置き換えます。

    出力は次のようになります。

    NAME        STATUS   ROLES           AGE    VERSION
    control-0   Ready    control-plane   202d   v1.27.4-gke.1600
    control-1   Ready    control-plane   202d   v1.27.4-gke.1600
    control-2   Ready    control-plane   202d   v1.27.4-gke.1600
    worker-0    Ready    worker          202d   v1.27.4-gke.1600
    worker-1    Ready    worker          202d   v1.27.4-gke.1600
    worker-2    Ready    worker          202d   v1.27.4-gke.1600
    worker-3    Ready    worker          202d   v1.27.4-gke.1600
    worker-4    Ready    worker          154d   v1.27.4-gke.1600
    worker-5    Ready    worker          154d   v1.27.4-gke.1600
    worker-6    Ready    worker          154d   v1.27.4-gke.1600
    worker-7    Ready    worker          154d   v1.27.4-gke.1600
    worker-8    Ready    worker          154d   v1.27.4-gke.1600
    worker-9    Ready    worker          154d   v1.27.4-gke.1600
    

    ノードの STATUSReady でない場合は、ノードのトラブルシューティングを行い、すべてのノードが Ready になってから操作を続けてください。

  2. ユーザー クラスタをシャットダウンする場合は、管理クラスタノードのステータスを確認します。

    kubectl get nodes --kubeconfig ADMIN_KUBECONFIG
    

    ADMIN_KUBECONFIG は、管理クラスタの kubeconfig ファイルのパスに置き換えます。

    以降の手順は管理クラスタに依存しています。ノードの STATUSReady でない場合は、ノードのトラブルシューティングを行い、すべてのノードが Ready になってから操作を続けてください。

  3. シャットダウンするクラスタの健全性を確認します。

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    

    次のように置き換えます。

    • CLUSTER_NAME: 確認するクラスタの名前。

    • ADMIN_KUBECONFIG: 管理クラスタの kubeconfig ファイルのパス。

    報告された問題を修正してから次に進みます。

  4. シャットダウンするクラスタで、すべての etcd Pod が実行されていることを確認します。

    kubectl get pods --kubeconfig CLUSTER_KUBECONFIG -A \
        -l component=etcd
    

    CLUSTER_KUBECONFIG は、クラスタの kubeconfig ファイルのパスに置き換えます。

    出力は次のようになります。

    NAMESPACE     NAME                   READY   STATUS    RESTARTS   AGE
    kube-system   etcd-control-0-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-1-admin   1/1     Running   0          2d22h
    kube-system   etcd-control-2-admin   1/1     Running   0          2d22h
    

    Pod の STATUSRunning でない場合は、Pod のトラブルシューティングを行い、すべての Pod が Running になってから操作を続けてください。

  5. クラスタをバックアップするで説明されているように、バックアップを実行します。

    クラスタの再起動で問題が発生したときにクラスタを復元できるように、クラスタをシャットダウンする前に etcd のバックアップを行うことが重要です。Etcd の破損、ノードのハードウェア障害、ネットワーク接続の問題など、他の条件により、クラスタが正常に再起動できない場合があります。

  6. ワーカーノードを含むクラスタをシャットダウンする場合は、ワーカーノードをメンテナンス モードにします。

    このステップにより、etcd への書き込み量を最小限に抑えることができるため、クラスタの再起動時に大量の etcd 書き込みを調整する必要性が低くなります。

  7. コントロール プレーン ノードをメンテナンス モードに切り替えます。

    このステップにより、ノードのシャットダウン中にステートフル ワークロードの書き込みが破損するのを防ぐことができます。

  8. 次の順序でクラスタノードをシャットダウンします。

    1. ワーカーノード
    2. コントロール プレーン ロードバランサ ノード
    3. コントロール プレーン ノード(etcd フォロワーから etcd リーダーまで)

      高可用性(HA)クラスタがある場合は、SSH を使用して各コントロール プレーン ノードに接続し、次の etcdctl コマンドを実行して etcd リーダーを確認できます。

      ETCDCTL_API=3 etcdctl \
          --cacert /etc/kubernetes/pki/etcd/ca.crt \
          --cert /etc/kubernetes/pki/etcd/server.crt \
          --key /etc/kubernetes/pki/etcd/server.key \
          --write-out=table endpoint status
      

      レスポンスには IS LEADER 列が含まれます。ノードが etcd リーダーである場合、この列は true になります。

この時点で、クラスタは完全にシャットダウンされます。必要なメンテナンスを実施した後、次のセクションで説明するようにクラスタを再起動します。

クラスタを再起動する

電源が完全にオフになっているクラスタを再起動するには、次の操作を行います。

  1. 電源を切る手順と逆の順序でノードマシンの電源を入れます。

  2. コントロール プレーン ノードのメンテナンス モードを解除します。

    手順については、ノードのメンテナンス モードを解除するをご覧ください。

  3. ワーカーノードのメンテナンス モードを解除します。

  4. クラスタ ヘルスチェックを実行して、クラスタが正常に動作していることを確認します。

    bmctl check cluster -c CLUSTER_NAME --kubeconfig ADMIN_KUBECONFIG
    
  5. etcd クラッシュ ループなどの問題によりクラスタが正常に再起動されない場合は、正常であることが確認されている最新のバックアップからクラスタの復元を試してください。手順については、クラスタを復元するをご覧ください。

課金とメンテナンス モード

Google Distributed Cloud の課金は、クラスタでワークロードを実行可能なノードの vCPU 数に基づきます。ノードをメンテナンス モードにすると、NoExecuteNoSchedule の taint がノードに追加されますが、課金は無効になりません。ノードをメンテナンス モードにした後、ノード(kubectl cordon NODE_NAME)を閉鎖してスケジュール不可としてマークします。ノードがスケジュール不可としてマークされると、ノードとそれに関連付けられた vCPU は課金対象から除外されます。

料金ページで説明しているように、kubectl を使用すると、各ユーザー クラスタの vCPU 容量(課金対象)を確認できます。このコマンドでは、ノードがスケジューリング可能かどうかは考慮されず、ノードあたりの vCPU 数のみが示されます。

ユーザー クラスタのノードあたりの vCPU 数を確認するには:

kubectl get nodes \
    --kubeconfig USER_KUBECONFIG \
    -o=jsonpath="{range .items[*]}{.metadata.name}{\"\t\"} \
    {.status.capacity.cpu}{\"\n\"}{end}"

USER_KUBECONFIG は、ユーザー クラスタの kubeconfig ファイルのパスに置き換えます。