Skip to content

Scheduler Plugins

KNS-3 extends the standard Kubernetes scheduler with three plugins registered under the kns-3-scheduler profile. The scheduler binary is built in Go using the Kubernetes Scheduling Framework.

flowchart TD
    pod([Incoming Pod])
    filter["Filter<br/>CustomFilterPlugin<br/>exclude ineligible nodes"]
    prescore["PreScore<br/>CustomScorePlugin<br/>GET /simulate → cache results"]
    score["Score<br/>CustomScorePlugin<br/>assign score × 1000 per node"]
    normalize["NormalizeScore<br/>CustomScorePlugin<br/>rescale all scores to 0–100"]
    postbind["PostBind<br/>CustomBindPlugin<br/>log the binding"]

    pod --> filter
    filter --> prescore
    prescore --> score
    score --> normalize
    normalize --> postbind

Phase: Filter

Runs once per candidate node before scoring. Returns Unschedulable to exclude a node or Success to keep it.

Condition Result
Node has label scheduler=disabled Unschedulable
Pod has annotation kns-3-scheduler/qos: rigorous and node does not have label capability=rigorous Unschedulable
All other cases Success

Example: exclude a node from KNS-3 scheduling

Section titled “Example: exclude a node from KNS-3 scheduling”
Terminal window
kubectl label node <node-name> scheduler=disabled

Example: restrict a pod to rigorous-capable nodes

Section titled “Example: restrict a pod to rigorous-capable nodes”
metadata:
annotations:
kns-3-scheduler/qos: rigorous
Terminal window
kubectl label node <node-name> capability=rigorous

Phases: PreScore, Score, NormalizeScore

This plugin drives the network-aware ranking. It implements all three phases of the scoring extension point.

Called once after filtering, before any node is scored. The plugin:

  1. Clears any results cached from the previous scheduling cycle.
  2. Makes an HTTP GET request to http://127.0.0.1:80/simulate (the co-located simulator container).
  3. Stores the SimulationResponse in memory for use during the Score phase.

The request is retried up to 2 times with a 100 ms delay between attempts. A 5-second HTTP timeout is applied. If the simulation fails, scoring falls back to a score of 0 for all nodes rather than rejecting the pod.

Called once per candidate node. Looks up the node’s score field from the cached SimulationResponse.Results and returns int64(score × 1000).

The ×1000 multiplier preserves decimal separation between nodes before integer truncation. NormalizeScore rescales the values afterward.

Rescales all node scores linearly to the Kubernetes standard 0–100 range:

normalizedScore = (score - lowest) × 100 / (highest - lowest)

If all nodes have the same score (including when all are 0), every node receives the maximum score of 100 so that Kubernetes can still make a placement decision using other plugin weights.

The plugin calls GET /simulate on the simulator. See the FastAPI reference for the full endpoint specification and response schema.


Phase: PostBind

An informational plugin. After Kubernetes successfully binds the pod to the selected node, this plugin logs the binding at verbosity level 1:

KNS-3 bound pod to node node=worker-node-2

No additional action is taken; the actual binding is performed by the default bind plugin.


Plugins are registered in a KubeSchedulerConfiguration stored in the kns-3-scheduler-config ConfigMap:

apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: false
profiles:
- schedulerName: kns-3-scheduler
plugins:
filter:
enabled:
- name: CustomFilterPlugin
preScore:
enabled:
- name: CustomScorePlugin
score:
enabled:
- name: CustomScorePlugin
weight: 10
postBind:
enabled:
- name: CustomBindPlugin

The weight: 10 on CustomScorePlugin gives the network score strong influence relative to any default scoring plugins that may also be active.

The scheduler binary is started with:

Terminal window
kns-3-scheduler --config=/etc/kubernetes/scheduler-config.yaml --v=1