Skip to content

Commit a3c3876

Browse files
authored
feat(supervisor): add node affinity rules for large machine worker pool scheduling (#2869)
**Background** Runs with `large-1x` or `large-2x` machine presets are disproportionally affected by scheduling delays during peak times. This is in part caused by the fact that the worker pool is shared for all runs, meaning large runs compete with smaller runs for available capacity. Because large runs require significantly more CPU and memory, they are harder for the scheduler to bin-pack onto existing nodes, often requiring a node with a significant amount of free resources or waiting for a new node to spin up entirely. This effect is amplified during peak times when nodes are already densely packed with smaller workloads, leaving insufficient contiguous resources for large runs. Also, large runs make up a small percentage of the total runs. **Changes** This PR adds Kubernetes node affinity settings to separate large and standard machine workloads across node pools. - Controlled via `KUBERNETES_LARGE_MACHINE_POOL_LABEL` env var (disabled when not set) - Large machine presets (large-*) get a soft preference to schedule on the large pool, with fallback to standard nodes - Non-large machines are excluded from the large pool via required anti-affinity - This ensures the large machine pool is reserved for large workloads while allowing large workloads to spill over to standard nodes if needed
1 parent 7a94908 commit a3c3876

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

apps/supervisor/src/env.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ const Env = z.object({
9191
KUBERNETES_MEMORY_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(1), // Ratio of memory limit, so 1 = 100% of memory limit
9292
KUBERNETES_MEMORY_OVERHEAD_GB: z.coerce.number().min(0).optional(), // Optional memory overhead to add to the limit in GB
9393
KUBERNETES_SCHEDULER_NAME: z.string().optional(), // Custom scheduler name for pods
94+
KUBERNETES_LARGE_MACHINE_POOL_LABEL: z.string().optional(), // if set, large-* presets affinity for machinepool=<value>
9495

9596
// Placement tags settings
9697
PLACEMENT_TAGS_ENABLED: BoolEnv.default(false),

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export class KubernetesWorkloadManager implements WorkloadManager {
9595
},
9696
spec: {
9797
...this.addPlacementTags(this.#defaultPodSpec, opts.placementTags),
98+
affinity: this.#getNodeAffinity(opts.machine),
9899
terminationGracePeriodSeconds: 60 * 60,
99100
containers: [
100101
{
@@ -356,4 +357,55 @@ export class KubernetesWorkloadManager implements WorkloadManager {
356357
},
357358
};
358359
}
360+
361+
#isLargeMachine(preset: MachinePreset): boolean {
362+
return preset.name.startsWith("large-");
363+
}
364+
365+
#getNodeAffinity(preset: MachinePreset): k8s.V1Affinity | undefined {
366+
if (!env.KUBERNETES_LARGE_MACHINE_POOL_LABEL) {
367+
return undefined;
368+
}
369+
370+
if (this.#isLargeMachine(preset)) {
371+
// soft preference for the large-machine pool, falls back to standard if unavailable
372+
return {
373+
nodeAffinity: {
374+
preferredDuringSchedulingIgnoredDuringExecution: [
375+
{
376+
weight: 100,
377+
preference: {
378+
matchExpressions: [
379+
{
380+
key: "node.cluster.x-k8s.io/machinepool",
381+
operator: "In",
382+
values: [env.KUBERNETES_LARGE_MACHINE_POOL_LABEL],
383+
},
384+
],
385+
},
386+
},
387+
],
388+
},
389+
};
390+
}
391+
392+
// not schedulable in the large-machine pool
393+
return {
394+
nodeAffinity: {
395+
requiredDuringSchedulingIgnoredDuringExecution: {
396+
nodeSelectorTerms: [
397+
{
398+
matchExpressions: [
399+
{
400+
key: "node.cluster.x-k8s.io/machinepool",
401+
operator: "NotIn",
402+
values: [env.KUBERNETES_LARGE_MACHINE_POOL_LABEL],
403+
},
404+
],
405+
},
406+
],
407+
},
408+
},
409+
};
410+
}
359411
}

0 commit comments

Comments
 (0)