スケジューラが席を選ぶのを見る
このラボはリソースが本当に足りないクラスター上で行います
VMの中に本物のk3sが起動しています。ノードのCPUが実際に有限なので、要求を大きく設定すると、本当に席が足りず、Pendingのままになります。
CKAコースのほかのスケジューリングのラボが動く偽のクラスターには、偽のノードが複数あり、リソースの圧迫がないため、何を要求してもすべて配置されます。そのため、スケジューラーが実際に何を見て拒否するのかを、確認できませんでした。
最初の起動に2分ほどかかります。
目標
スケジューラーが席を選ぶ5つの仕組みを、実際に詰まらせて確認します。そして、優先度の低いPodが追い出されるところまで見ます。
なぜ重要なのか
スケジューリングの設定は、「うまく使えば望むところに配置される」よりも、「間違って使うとどこにも配置されない」ほうが、はるかによく問題になります。そして、その症状は常に同じです。PodがPendingになることです。
原因は、複数の層に散らばっています。
- リソース要求がノードより大きい →
Insufficient cpu - テイントを許容しない →
untolerated taint requiredアフィニティに合うノードがない →didn't match node affinity- アンチアフィニティが同じノードを塞ぐ
- トポロジーの分散が
DoNotScheduleなのに、分けるノードがない
スケジューラーは、なぜ配置できなかったのかを、常にイベントに残します。それを読む訓練が、このラボのすべてです。
ステップ
すべて、cschネームスペースに作成します。ノードは1台です。
- ノードの
capacityとallocatable、そして今どれだけ要求されているかを記録してください(保存先:/root/csch/capacity.txt)。 hog-a・hog-b・hog-cの3つのPodで、席を奪い合わせてください。前の2つは配置され、3つ目はPendingである必要があります。スケジューラーの理由を記録します(保存先:/root/csch/pressure.txt)。- ノードにテイント(
lab=only:NoSchedule)を設定し、トレラレーションのないno-tolと、あるものwith-tolを比較して記録してください(保存先:/root/csch/taint.txt)。 - ノードに
disktype=ssdラベルを付け、aff-required(合うもの)・aff-impossible(存在しないラベルをrequiredで)・aff-preferred(存在しないラベルをpreferredで)の3つを作成して記録してください(保存先:/root/csch/affinity.txt)。 - Deployment(
spread、レプリカ2)にrequiredアンチアフィニティを設定し、ノードが1つだけなので1つしか起動しないことを記録してください(保存先:/root/csch/anti.txt)。 - PriorityClass(
low-prio・high-prio)を作成し、低いものでノードを埋めたあと、important(高いほう)を投入して、プリエンプションが起こることを記録してください(保存先:/root/csch/preempt.txt)。 - Deployment(
even)にtopologySpreadConstraintsをScheduleAnywayで設定して記録してください(保存先:/root/csch/spread.txt)。 - 次の3行と説明を書いてください(保存先:
/root/csch/report.md)。pending_reason=Insufficient、taint_effect=NoSchedule、high_priority_value=の3行です。
参考
- ノード情報は、
kubectl describe nodeのCapacity・Allocatable・Allocated resourcesの3つの節にあります。3つは、異なる値です。 - スケジューラーの理由は、
kubectl -n csch describe pod <이름>のEventsや、.status.conditions[?(@.type=="PodScheduled")].messageにあります(プレースホルダーはPod名です)。 - テイントは、
kubectl taint node <노드> lab=only:NoScheduleで設定し、削除するときは末尾に-を付けます(プレースホルダーはノード名です)。 - 7で
whenUnsatisfiableをDoNotScheduleにすると、ノードが1つだけなので何も起動しません。ScheduleAnywayを使ってください。 - よくあるミス1:
requestsの代わりにlimitsで席を奪い合わせようとすることです。スケジューラーが見るのは、requestsだけです。limitsは、実行中にカーネルが強制する値です。 - よくあるミス2: テイントを設定したあと、既存のPodがなぜ追い出されないのかと不思議に思うことです。
NoScheduleは、新しく配置するものだけを防ぎます。すでにあるものまで追い出すには、NoExecuteです。
ノードに何がどれだけあるか
ノードのcapacityとallocatable、そして今どれだけ要求されているかを記録してください(保存先: /root/csch/capacity.txt)。
capacityはハードウェアが持っているもの、allocatableはシステム分を引いた残り、Allocated resourcesはすでに要求された合計です。
席が足りなければ待つ
hog-a・hog-b・hog-cの3つのPodで、席を奪い合わせてください。前の2つは配置され、3つ目はPendingである必要があります。スケジューラーの理由を記録します(保存先: /root/csch/pressure.txt)。
CPUのrequestsを大きく設定して、2つだけが入るようにしてください。スケジューラーが見るのは、requestsだけです。
ノードが拒否する
ノードにテイント(lab=only:NoSchedule)を設定し、トレラレーションのないno-tolと、あるものwith-tolを比較して記録してください(保存先: /root/csch/taint.txt)。
テイントはノードが設定するもので、トレラレーションはPodが持つものです。NoScheduleは、新しく配置するものだけを防ぎます。
requiredとpreferred
ノードにdisktype=ssdラベルを付け、aff-required(合うもの)・aff-impossible(存在しないラベルをrequiredで)・aff-preferred(存在しないラベルをpreferredで)の3つを作成して記録してください(保存先: /root/csch/affinity.txt)。
requiredは合わせられなければ永遠にPendingで、preferredは合わせられなくても配置されます。
同じノードを避ける
Deployment(spread、レプリカ2)にrequiredアンチアフィニティを設定し、ノードが1つだけなので1つしか起動しないことを記録してください(保存先: /root/csch/anti.txt)。
topologyKey: kubernetes.io/hostnameは、「ノードが違えばよい」という意味です。ノードが1つなら、2つ目は配置される場所がありません。
高い優先度が席を奪う
PriorityClass(low-prio・high-prio)を作成し、低いものでノードを埋めたあと、important(高いほう)を投入して、プリエンプションが起こることを記録してください(保存先: /root/csch/preempt.txt)。
低い優先度でノードを埋めたあとに、高い優先度のPodを入れると、スケジューラーが低いものを追い出します。
均等に散らばらせる
Deployment(even)にtopologySpreadConstraintsをScheduleAnywayで設定して記録してください(保存先: /root/csch/spread.txt)。
ノードが1つだけなので、whenUnsatisfiable: ScheduleAnywayである必要があります。DoNotScheduleなら、何も起動しません。
何を学んだか
次の3行と説明を書いてください(保存先: /root/csch/report.md)。pending_reason=Insufficient、taint_effect=NoSchedule、high_priority_value=の3行です。
pending_reason=、taint_effect=、high_priority_value=の3行と一緒に、Pendingを絞り込む順序を書いてください。