この記事は、CAST AI社により公開されたブログ記事を元に翻訳・作成したものです。元の記事については以下をご覧ください。
(記事最終更新日:2022年11月17日)
Kubernetes Cordon:使い方と使いどころ
公開日:2023年12月21日
更新日:2023年12月21日
Kubernetesは、ノードを手動で管理やメンテナンスすることもできます。kubectlを使えば、ノードオブジェクトを簡単に作成したり、ノードを変更したりすることもできます。たとえば、ラベルの設定やスケジュール不可のマークなどです。Kubernetes cordonはこのような場面で活躍します。Kubernetes cordonコマンドはどのようなものでしょうか?そして、どのように使うのでしょうか?

Kubernetes cordonとは何か?
Kubernetes cordonは、既存のノードプール内のノードをスケジューリング不可能なものとしてマーク(汚染(taint)といいます)する操作のことです。ノードに対してこの操作をすると、そのノードは新しいポッドがスケジュールされないようになります。このコマンドは、Kubernetesスケジューラーがそのノードに新しいポッドを配置することを防ぎますが、すでにそのノード上にあるポッドには影響しません。
ノードをスケジュール不可としてマークする方法は、次のコマンドを実行するだけです。
kubectl cordon $NODENAME
なお、DaemonSetに含まれるポッドは、スケジューリング不可なノードであっても実行されます。これはなぜかというと、通常DaemonSetは、スケジュール不可とマークされワークロードが枯渇していたとしても、ノード上で実行されるべきノードローカルなサービスを提供するからです。
Kubernetes cordonの使いどころは?
Kubernetesクラスターのノードは、メンテナンスが必要になることがあります。たとえば、自社で保有するハードウェアコンポーネントの交換、ノードのカーネル更新、クラウドプロバイダによるコンピュートリソースのサイズ変更などです。
Kubernetes cordonとdrainは、対象ノードで実行中のワークロードをほかのノードに再スケジュールさせることで、アプリケーションがノードの停止に対応できるようにします。これによって、サービスの可用性に何ら影響を与えず、ノードを安全にシャットダウンし、クラスターから削除できます。
ステップバイステップガイド:Kubernetes cordonの使い方
Step1:ノードの遮断(Cordon)
ノードをcordonすると、そのノードがスケジューラーは使用不可としてマークされます。これによって、このノードはクラスターに追加される新しいポッドをホストすることはなくなります。
ノードの名前を指定してcordonするには、次のコマンドを使用します。
$ kubectl cordon node-12
このノード上の既存のポッドはcordonの影響を受けず、アクセス可能なままです。
現在、どのノードがcordonされているかを確認したいときは、ノードの取得コマンドを使用します。
$ kubectl get nodes
NAME STATUS
ROLES AGE VERSION
node-12 Ready,SchedulingDisabled control-plane,master 22m v1.23.3
cordonされたノードはステータスがSchedulingDisabledと表示されます。
Step2:ノードの解放(drain)
ノードを空にするために、残ったポッドを削除するためには、ノードをdrainする必要があります。このプロセスによってポッドをクラスター内のほかのノードに再スケジュールすることで退避できます。こうすることで、drain予定のノードから強制的に削除することなく、ポッドを正常に終了させることができます。
drainを実行するには、kubectl drainコマンドにdrainしたいノードの名前を指定して実行します。
$ kubectl drain node-12
node/node-12 already cordoned
evicting pod kube-system/storage-provisioner
evicting pod default/nginx-7c658794b9-zszdd
evicting pod kube-system/coredns-64897985d-dp6lx
pod/storage-provisioner evicted
pod/nginx-7c658794b9-zszdd evicted
pod/coredns-64897985d-dp6lx evicted
node/node-12 evicted
注:実際には、ここにあるようにdaemonsetsを無視したdrainはめったに発生しません。
drain運用はどのように行うのでしょうか?まず、Kubernetes codonです。手動で行うのでなければ、cordonを使ってノードを遮断します。次に、実行中のポッドを(再スケジュールするスペースがないとしても)削除します。ノードが空になったら、シャットダウンまたは破棄できます。cordonによって、drainが完了するまで、このノードで新しいワークロードがスケジュールされないことが保証されています。
ポッドの猶予期間(grace period)が長い場合は、どうするか?
ポッドの猶予期間が長い場合、Kubernetesノードのdrainに時間がかかることがあります。ノードをすぐにオフラインにしたい場合、これが問題になる可能性があります。
このようなときは、--grace-periodフラグを使用してポッド終了猶予期間をオーバーライドし、即時停止を強制できます。
$ kubectl drain node-12 --grace-period 0
しかし、これは慎重に使用してください。一部のワークロードは、クリーンアップする機会がないまま強制的に停止すると、適切に応答しない可能性があります。
ReplicationController,Job,DaemonSetによって管理されるポッドがノード上にない場合に、使うことができ、ノードを解放するための別のコマンドも知っておく価値があるでしょう。
$ kubectl drain node-12 --force
Kubernetesでノードのdrainを中止(undrain/uncordon)するには?
対象ノードをスケジュール可能としてマークしなおすことで、Kubernetesのノードをundorain/uncordonすることができます。次のコマンドを使用してください。
kubectl uncordon NODE
Kubernetes cordonを使用したクラスターの最適化
サードパーティの最適化ソリューションを使用してクラスターを分析し、大きなコスト削減の余地を発見したとします。ただし、それを実現するには、クラスターが実行されているコンピューティングリソースを変更する必要があるとします。このようなときにKubernetesのtaintが役に立ちます。
当社のお客さまは、Evictorを使用することでコスト削減をすぐに最大化できます。Evictorは、無駄を見つけてポッドをより少ないノードに集約し、ノード削除ポリシーによって空のノードを作成して削除するメカニズムです。
このガイドを見てCAST AIをインストールし、クラスターに接続すれば、Evictorポリシーが設定できます。
次のステップは、既存のノードをやめて、CAST AIに最適化されたクラスターを作成させることです。ワークロード構成によっては、これによってダウンタイムが発生する可能性があることに注意してください。Evictorは、ダウンタイムを引き起こさないように「安全第一」となるよう設計されていますが、一部の設定はより積極的な内容に上書きされる可能性があります。
Evictorの動作は次のようになります。

-
1つのノード(赤色の枠)がエビクション(立ち退き)の候補として認識されます。
-
Evictorはポッドをほかのノードに自動的に移動します。これを私は「ビンパッキング」と呼びます。
-
ノードが空になると、クラスターから削除されます。
-
ステップ1に戻ります。
ノードが1つ削除されるとこうなります。

そして、プロセス終了後は、ノードが3つ残りました。

Evictorは10分で、3つのノードを削除し、3つのノードを稼動させたまま最適な設定にし、コストの削減ができました。
Kubernetesノードのcordonとdrainを自動化する
ノード大量に扱っていると、ノードが実行されているコンピューティングリソースを手動で変更しようとすると、あっという間に時間を浪費してしまいます。CAST AIに任せれば、自動最適化メカニズムの一環として、ノードのcordonとdrainを代行してくれます。
まずは、CAST AIをクラスターに接続(読み取りだけ)して、無料のKubernetesコスト監視でどれだけ節約できるか、そしてそれを実現する方法を確認してみましょう。

2018年にオラクルに買収されたZenedgeの共同創業者兼最高製品・事業責任者を務めました。
Laurentは、2012年にGoogleに買収されたViewdleのCEO兼共同創業者でもあります。
タグ一覧