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

ノードの修復またはメンテナンスが必要な場合は、まずノードをメンテナンス モードにする必要があります。これにより、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 の一般提供として利用できます。

  • ノードが 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: 一般提供
  • 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
  • Pod に PriorityClass がない
  • 既知の 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: クラスタの名前空間。
    • CLUSTER_NAME: クラスタの名前。
  2. メンテナンス モードにするノードの単一の IP アドレスかアドレス範囲を指定するため、クラスタ構成ファイルに maintenanceBlocks セクションを追加します。

    次のサンプルでは、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-anthos-baremetal-01   Ready    control-plane   2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-04   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-baremetal-05   Ready    worker          2d22h   v1.27.4-gke.1600
    user-anthos-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: クラスタの名前空間。
    • 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 ファイルのパスに置き換えます。