ノードメンテナンス

KubernetesBeginner
オンラインで実践に進む

はじめに

本番環境の Kubernetes では、ノードのメンテナンスが必要になることがあります。課題は、ワークロードに不要な影響を与えずにメンテナンスを実施することです。

Node をホテルの部屋、Pod を宿泊客だと考えてみましょう。部屋を改装する場合、宿泊客が寝ている最中にいきなり入るわけにはいきません。丁寧で安全な手順が必要です。

この実験では、ノードメンテナンスの標準的なワークフローを学びます。

  • Cordon(立入禁止):ドアに「新しい宿泊客は受け入れません」という札を掛けます。ホテル(scheduler)は、この部屋に新しい宿泊客を案内しなくなります。
  • Drain(退避):現在いる宿泊客に丁寧に退室してもらい、別の空いている部屋へ移動させます。
  • メンテナンス:必要な作業(改装)を実施します。
  • Uncordon(再開):札を外し、再びスケジューリングできるようにします。

このプロセスをシミュレートするため、ローカルの Minikube クラスターを使用します。

ノードを Cordon する

メンテナンスを実施する前に、これから作業するノードに Kubernetes scheduler が新しい Pod を配置しないようにする必要があります。この処理を「cordon」と呼びます。ホテルの部屋のドアに「立入禁止」や「使用停止」の札を掛けるようなものです。

これはスケジューリングに関する設定であり、シャットダウンではありません。Cordon されたノードは正常な状態を保ち、既存の Pod を引き続き実行できます。Kubernetes は、そのノードを新しい配置先として使用不可にするだけなので、制御された状態でメンテナンスを開始できます。

まず、ノード名を確認します。次のコマンドを実行してください。

kubectl get nodes

Ready 状態のノードが 1 つ(例:minikube)表示されます。

ノードをスケジューリング不可にするには、cordon コマンドを使用します。コマンド置換 $() を使って、ノード名を自動的に取得します。

kubectl cordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')

次に、ノードの状態をもう一度確認します。

kubectl get nodes

状態が Ready,SchedulingDisabled に変わっていることを確認してください。これは、ノードが Cordon されたことを示します。このノードには新しい Pod はスケジュールされませんが、既存の Pod は引き続き実行されます。

ノードを Drain する

Cordon で停止できるのは、新しい Pod の配置だけです。部屋にはまだ実行中のアプリケーション(宿泊客)が残っています。これらを安全に退避させるには、drain コマンドを使用します。

このコマンドは Pod を退避させます。すると Kubernetes は、必要なレプリカ数である 2 個が不足していることを認識し、利用可能な別のノードに新しい Pod を作成しようとします。

ここでは evict(退避) という言葉が重要です。Drain は、強制的に停止するための処理ではありません。Kubernetes の仕組みに沿ってワークロードを退避させることで、コントローラーが代替 Pod を作成し、終了ルールも守れるようにします。そのため、ノード上のプロセスを無作為に手動削除するよりも drain のほうが安全です。

Drain コマンドを実行します。この環境で退避を強制するため、いくつかのオプションを追加します。

  • --ignore-daemonsets:一部のシステム Pod(DaemonSet)はノードに固定されていて移動できません。それらを無視します。
  • --delete-emptydir-data:Pod がローカルの一時ストレージを使用している場合、Drain によってそのデータが削除されます。この動作を了承します。
  • --force:ReplicationController、ReplicaSet、Job、DaemonSet、StatefulSet のいずれにも管理されていない Pod(Minikube の storage-provisioner など)を削除するために必要です。
kubectl drain $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}') --ignore-daemonsets --delete-emptydir-data --force

Pod が退避されていることを示す出力が表示されます。

注記:この単一ノードの Minikube 実験で、唯一のノードを Drain すると、Pod は退避されますが Pending 状態になります。移動先となる「ホテルの別の部屋」がないためです。実際のマルチノードクラスターでは、正常な別のノードへすぐに移動します。

状態を確認する

ノードを Drain した後は、アプリケーションがどうなったかを確認することが重要です。

この確認作業は、クラスター管理における重要な習慣を身につけるためのものです。メンテナンスコマンドを実行しただけで終わらせず、必ずワークロードの視点からスケジューリング結果を確認してください。アプリケーションが想定した場所で実行されて初めて、メンテナンス作業は成功したと判断できます。

Pod の状態を確認します。

kubectl get pods

前述のとおり、Pod はおそらく Pending 状態になっています。

Pending になっている理由を確認するため、Kubernetes に問い合わせます。Pod の 1 つを詳しく表示してください。

kubectl describe pod $(kubectl get pods -o jsonpath='{.items[0].metadata.name}')

出力の下部にある Events セクションを確認します。「0/1 nodes are available: 1 node(s) are unschedulable.」に似たメッセージが表示されます。

これは、Drain が成功したことを示します。scheduler は Pod を実行しようとしていますが、利用可能な唯一のノードに設定した「立入禁止」の札を尊重しているため、配置できません。

ノードを Uncordon する

「改装」(OS のアップグレードやメンテナンス)が完了したとします。部屋を再び開放し、ノードをサービスに戻す時です。

uncordon はスケジューリングのブロックを解除するだけです。Pod を直ちにノードへ強制配置するわけではありません。このノードが今後の配置先として再び利用可能になったことを scheduler に伝え、その後は通常の調整処理が行われます。

この処理には uncordon コマンドを使用します。「立入禁止」の札を外す処理です。

kubectl uncordon $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')

次に、ノードの状態を確認します。

kubectl get nodes

状態が Ready に戻り、SchedulingDisabled の表示がなくなっていることを確認してください。

最後に、Pod の状態をもう一度確認します。ノードが再び利用可能になったため、Kubernetes scheduler は Pending 状態の Pod をこのノードに配置できるようになります。

kubectl get pods

Pod の状態が Pending から ContainerCreating、最後に Running へ変化することを確認してください。

まとめ

この実験では、Kubernetes ノードのメンテナンスを安全に進めるライフサイクルを実践しました。次の操作を学びました。

  1. Cordon:ノードをスケジューリング不可(立入禁止)に設定する。
  2. Drain:実行中のワークロードを安全に退避させる。
  3. Uncordon:ノードをサービスに復帰させる。

これらのコマンドは、高可用性を維持するためにシステム管理者が使用する重要な操作です。これにより、アプリケーションをダウンタイムから守りながらインフラストラクチャを修復できます(もちろん、マルチノードクラスターの場合です)。