はじめに
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)を設定することができる。
また,maxUnavailableとminAvailableはどちらか一方しか設定できない。
maxUnavailableとminAvailableについてどういうことか,具体例を挙げてみていく
以下のように、1つのノードにPodのReplicasが3個存在し、それを別のノードにDrainしていく作業を想定する
PDBが設定されていない場合
PDBが設定されていないと、特になにも制約を設けずDrainをしてしまうので、Podの全てのReplicasが稼働していない状態があり得る。 Drain対象のPodが常に稼働していなければならないもので合った場合、この状況になってしまうとダウンタイムが発生してしまう。
そこで、ダウンタイムが発生しないよう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が稼働していることは保証してほしい」のようなシナリオで使いやすい。
PDBの設定値をmaxUnavailable=1にした場合
maxUnavailableはminAvailableとは逆のアプローチでDrainに制約を設ける。
maxUnavailableとminAvailableは同時に設定することはできない。
maxUnavailableは「同時にDrain可能な最大Pod数」を示す。
例えばPodのReplicasが3でmaxUnavailable=1の状態でDrainを行うと、Podは1つまでしか同時にDrainができない。
このように、同時にDrainが可能な最大数としてDrainに制約を設けるアプローチもある。
「Drainに時間がかかっても良いから、Pod数にほとんど影響を与えないようn個ずつしかドレインしたくない」のようなシナリオで使いやすい。
参考
Qiita - Kubernetes: 複数の Node を安全に停止する (kubectl drain + PodDisruptionBudget) KubernetesDocumentation - kubectl drain