スケジューラの基本動作
Kubernetes におけるスケジューラは、マスターノード上で動作する独立したプロセスであり、API サーバーと連携して Pod の配置を決定します。主な役割は、PodSpec.NodeName が未設定の Pod を監視し、クラスタ内の適切なノードを選定した後、バインディング情報を API サーバーへ送信することです。
このプロセスにより、スケジューラは Pod とノードの紐付けを完了させ、コンテナの実行環境を確立します。
ソースコードの構成レイヤー
スケジューラのソースコードは、おおむね以下の 3 つの階層に分類できます。
- エントリーポイント:
cmd/kube-scheduler/scheduler.goに位置し、プロセス起動時の初期化処理を担当します。 - スケジューリングフレームワーク:
pkg/scheduler/scheduler.goで定義され、アルゴリズム実行の全体フローを制御します。 - コアアルゴリズム:
pkg/scheduler/core/generic_scheduler.goに実装され、実際にノードの選定計算を行うロジックを含みます。
スケジューリングアルゴリズムのフロー
Pod に対するノードの選定は、 filtering(过滤)と scoring(优先级)の 2 段階のプロセスを経て行われます。具体的な流れは以下の通りです。
対象 Pod の入力
+---------------------------------------+
| クラスタ内の全ノードリスト (Candidates) |
| [ Node-A ] [ Node-B ] [ Node-C ] |
+---------------------------------------+
|
v (Predicates による过滤)
+---------------------------------------+
| 条件を満たさないノードを除外 (例:资源不足) |
+---------------------------------------+
|
v
+---------------------------------------+
| 候補ノードリスト (Feasible Nodes) |
| [ Node-A ] [ Node-B ] |
+---------------------------------------+
|
v (Priorities によるスコアリング)
+---------------------------------------+
| 各ノードのスコア計算 |
| Node-A: 15 点 |
| Node-B: 40 点 |
+---------------------------------------+
|
v
最高スコアのノードを選択 (Node-B)
この仕組みにより、まず実行不可能なノードを排除し、次に残ったノードの中から最適なものを選定します。
Predicates と Priorities 戦略
選定プロセスで使用される戦略は、大きく 2 つに区分されます。
- Predicates: ノードが Pod の実行要件を満たしているかを判定する过滤関数です。メモリ不足やポート競合などが検出された場合、対象ノードは除外されます。
- Priorities: 过滤を通過したノードに対して優先度を付与する関数です。リソース配分の均衡やサービス分散などを評価基準とし、スコアに基づいてランク付けを行います。
これらの実装は、それぞれ pkg/scheduler/algorithm/predicates および pkg/scheduler/algorithm/priorities パッケージに格納されています。
ポリシーのカスタマイズと拡張
デフォルトのスケジューリング挙動は、内部の defaultPredicates() および defaultPriorities() 関数で定義されています。しかし、運用要件に応じて独自の戦略を追加したり、既存の戦略の重みを変更したりすることが可能です。
例えば、特定のリソース配分戦略を重視する場合、設定ファイルを用いてデフォルト動作を上書きできます。これは起動時のフラグ --policy-config-file を使用することで適用されます。
以下は、ポリシー設定ファイルの構成例です。ここでは優先度の重み付けを変更し、特定の过滤条件をカスタマイズしています。
{
"kind": "Policy",
"apiVersion": "v1",
"predicates": [
{"name": "PodFitsResources"},
{"name": "NoDiskConflict"},
{"name": "MatchNodeSelector"},
{"name": "HostName"},
{"name": "PodFitsHostPorts"}
],
"priorities": [
{"name": "LeastRequestedPriority", "weight": 2},
{"name": "BalancedResourceAllocation", "weight": 5},
{"name": "ServiceSpreadingPriority", "weight": 1},
{"name": "EqualPriority", "weight": 1}
],
"hardPodAffinitySymmetricWeight": 10,
"alwaysCheckAllPredicates": false
}
このように設定ファイルを通じて、过滤ルールやスコアリングの重みを調整することで、クラスタの特性に合わせたスケジューリング動作を実現できます。