スケジューラの起動プロセスにおいて、デフォルトで有効になるスケジューリングアルゴリズムや設定の読み込みロジックを理解することは、カスタムスケジューラ開発やトラブルシューティングに不可欠である。ここでは Kubernetes v1.13 をベースに、kube-scheduler の初期化フローとアルゴリズム登録メカニズムを解説する。
--config フラグによる設定読み込み
kube-scheduler は --config フラグで指定された YAML ファイルから設定を読み込む。このファイルにはスケジューラの動作に関わるほとんどのパラメータが含まれる。コマンドラインフラグは非推奨となっており、設定ファイルが優先される。
cmd/kube-scheduler/app/options/options.go で定義される Options 構造体は、CLI 引数と設定ファイルパスを保持する:
type Options struct {
ComponentConfig kubeschedulerconfig.KubeSchedulerConfiguration
ConfigFile string
WriteConfigTo string
Master string
// ... 認証・認可・リーダー選出などの設定
}
ApplyTo() メソッドは、--config の有無に応じて設定を適用する:
func (o *Options) ApplyTo(c *schedulerappconfig.Config) error {
if len(o.ConfigFile) == 0 {
c.ComponentConfig = o.ComponentConfig
// 非推奨フラグの適用(省略)
} else {
cfg, err := loadConfigFromFile(o.ConfigFile)
if err != nil {
return err
}
c.ComponentConfig = *cfg
// 設定ファイルからの非セキュアサービング設定適用
}
return nil
}
Feature Gate によるアルゴリズム制御
起動時に algorithmprovider.ApplyFeatureGates() が呼び出され、機能ゲートに基づいてスケジューリングアルゴリズムが動的に調整される。
パッケージ初期化時にデフォルトプロバイダが登録される:
// pkg/scheduler/algorithmprovider/defaults/defaults.go
func init() {
registerAlgorithmProvider(defaultPredicates(), defaultPriorities())
}
registerAlgorithmProvider は内部で factory.RegisterAlgorithmProvider を呼び出し、アルゴリズム名とそのキー集合をマップに格納する:
var algorithmProviderMap = make(map[string]AlgorithmProviderConfig)
func RegisterAlgorithmProvider(name string, predicateKeys, priorityKeys sets.String) {
algorithmProviderMap[name] = AlgorithmProviderConfig{
FitPredicateKeys: predicateKeys,
PriorityFunctionKeys: priorityKeys,
}
}
機能ゲートが有効な場合、特定のアルゴリズムが追加または削除される例:
func ApplyFeatureGates() {
if utilfeature.DefaultFeatureGate.Enabled(features.TaintNodesByCondition) {
factory.RemoveFitPredicate(predicates.CheckNodeConditionPred)
factory.RegisterMandatoryFitPredicate(predicates.PodToleratesNodeTaintsPred, predicates.PodToleratesNodeTaints)
factory.InsertPredicateKeyToAlgorithmProviderMap(predicates.PodToleratesNodeTaintsPred)
}
}
Scheduler インスタンスの生成
scheduler.New() はスケジューラのエントリポイントであり、アルゴリズムソース(Provider または Policy)に基づいて設定を構築する。
アルゴリズムソースは以下のいずれかを指定:
type SchedulerAlgorithmSource struct {
Policy *SchedulerPolicySource
Provider *string
}
Provider モードの場合、登録済みのアルゴリズムプロバイダ(例: "DefaultProvider")からキー集合を取得し、実際の関数に変換する:
func (c *configFactory) CreateFromProvider(providerName string) (*Config, error) {
provider, err := GetAlgorithmProvider(providerName)
if err != nil {
return nil, err
}
return c.CreateFromKeys(provider.FitPredicateKeys, provider.PriorityFunctionKeys, nil)
}
CreateFromKeys 内で、キーに対応するプレディケート関数とプライオリティ関数が解決され、GenericScheduler に注入される:
predicateFuncs, _ := c.GetPredicates(predicateKeys)
priorityConfigs, _ := c.GetPriorityFunctionConfigs(priorityKeys)
algo := core.NewGenericScheduler(
c.schedulerCache,
c.equivalencePodCache,
c.podQueue,
predicateFuncs,
predicateMetaProducer,
priorityConfigs,
priorityMetaProducer,
// ...
)
デフォルトで有効なアルゴリズム
defaultPredicates() と defaultPriorities() により、以下のようなアルゴリズムが標準で登録される:
- プレディケート(フィルタリング):
NoVolumeZoneConflict,NoDiskConflict,Predicates.GeneralPredicatesなど - プライオリティ(スコアリング):
LeastRequestedPriority,SelectorSpreadPriority,InterPodAffinityPriorityなど
これらのアルゴリズムは、機能ゲートの状態やカスタム設定によって動的に変更可能であり、スケジューラの柔軟性を支えている。