はじめに

EKSノードのマイナーバージョンアップデートの際、途中でDrainされる部分がある。 Drainの詳しい動きについて調べたので,そのメモを残す

登場人物

  • node:k8sで管理されているコンピューティングリソース。コントロールプレーンとワーカーノードに分けられる。AWSのEKSだとノードとしてEC2が使われる
  • pod:ノードの中に入れる,アプリケーションのコンテナのこと。コンテナは1つでも複数でも良い
  • DaemonSets:Node上で常に稼働していることが保証されるPod。ログ収集などで使われる
  • replicas:Podの複製。podの冗長化等に役立つ

Drainとは

ノードのメンテナンスをする際,対象のノードで稼働しているPodを全て停止させる必要がある。 Podのダウンタイムを作らないで,ノードをメンテナンスしたいというケースはよくある。 そこで登場するのがDrainコマンドである。 Drainコマンドは,対象のノードのPodをほかのPodに安全に退避させるコマンドである。

基本は以下のコマンドを打つと,対象のノードからDrain始まる。

kubectl drain [ノード名]

DaemonSetsが動いている場合は以下の--ignore-daemonsetsを付与しなければ失敗する。

kubectl drain --ignore-daemonsets [ノード名]

–ignore-daemonsets:daemonsetsはdrainしない。基本的にdaemonsetsは落とすことができないので、基本このオプションは必要。

Podを停止する際,安全に停止できないような場合は--forceを付与すると良い。

kubectl drain --ignore-daemonsets [ノード名]

–force:podを停止するときsigkillを送る(通常はsigterm)

Drainのフロー

Drainのフローを以下に示す

対象のノードをcordonする

cordonとは,ノードをスケジュール対象から外すことである。
言い換えると,cordonされたノードは新たにpodが起動しなくなる。

対象のノードからPodが削除され,削除されたPodは他のノードから起動する

対象のノードはcordonされたままなので,メンテナンス等が終了したら以下のコマンドでcordonを解除する必要がある。

$ kubectl uncordon [対象ノード名]

ただ,これだけだとPodが削除されて起動中の状態では,1つもpodが稼働していない状態になり,ダウンタイムが発生してしまう。 そこで登場するのがPodDisruptionBudget(PDB)である。 ¸¸

PodDisruptionBudget(PDB)

PDBは,Drain中にPodが一度に停止して良い最大数(maxUnavailable)またはPodが最低限起動していなければならない最小数(minAvailable)を設定することができる。
また,maxUnavailableminAvailableはどちらか一方しか設定できない。

maxUnavailableminAvailableについてどういうことか,具体例を挙げてみていく

以下のように、1つのノードにPodのReplicasが3個存在し、それを別のノードにDrainしていく作業を想定する image

PDBが設定されていない場合

PDBが設定されていないと、特になにも制約を設けずDrainをしてしまうので、Podの全てのReplicasが稼働していない状態があり得る。 Drain対象のPodが常に稼働していなければならないもので合った場合、この状況になってしまうとダウンタイムが発生してしまう。

image

そこで、ダウンタイムが発生しないようDrainに制約を設けることができるのがPDBである。

PDBの設定値をminAvailable=1にした場合

PDBはPodに紐づけるリソースである。

minAvailableは「稼働していなければなさない最小Pod数」を示す。
例えばPodのReplicasが3でminAvailable=1の状態でDrainを行うと、Podは2つまでしか同時にDrainができない。 このようにPDBのminAvailableを用いれば、Podが常に最低限1つ以上稼働している状態であることを保証し、Drainすることができる。
「Drainに時間をかけないよう可能な限り同時にやりたいが、最低限n個のPodが稼働していることは保証してほしい」のようなシナリオで使いやすい。 image

PDBの設定値をmaxUnavailable=1にした場合

maxUnavailableminAvailableとは逆のアプローチでDrainに制約を設ける。
maxUnavailableminAvailableは同時に設定することはできない。

maxUnavailableは「同時にDrain可能な最大Pod数」を示す。
例えばPodのReplicasが3でmaxUnavailable=1の状態でDrainを行うと、Podは1つまでしか同時にDrainができない。 このように、同時にDrainが可能な最大数としてDrainに制約を設けるアプローチもある。 「Drainに時間がかかっても良いから、Pod数にほとんど影響を与えないようn個ずつしかドレインしたくない」のようなシナリオで使いやすい。 image

参考

Qiita - Kubernetes: 複数の Node を安全に停止する (kubectl drain + PodDisruptionBudget) KubernetesDocumentation - kubectl drain