Resource Flavor
Resources in a cluster are typically not homogeneous. Resources could differ in:
- Pricing and availability (for example, spot versus on-demand VMs)
- Architecture (for example, x86 versus ARM CPUs)
- Brands and models (for example, Radeon 7000 versus Nvidia A100 versus T4 GPUs)
A ResourceFlavor is an object that represents these resource variations and allows you to associate them with cluster nodes through labels, taints and tolerations.
Note
If the resources in your cluster are homogeneous, you can use an empty ResourceFlavor instead of adding labels to custom ResourceFlavors.ResourceFlavor tolerations for automatic scheduling
Requires Kubernetes 1.23 or newer
This approach may be best for teams that wish to schedule pods onto the appropriate nodes automatically. However, a limitation arises when multiple types of specialized hardware are present, such as two different nvidia.com/gpu resources present in the cluster, i.e., T4 and A100 GPUs. The system may not differentiate between them, meaning the pods could be scheduled on any of both types of hardware.
To associate a ResourceFlavor with a subset of nodes of your cluster, you can configure the .spec.nodeLabels field with matching node labels that uniquely identify the nodes.
If you are using cluster autoscaler (or equivalent controllers), make sure that the controller is configured to add those labels when adding new nodes.
To guarantee that the Pods in the Workload run on the nodes associated to the flavor that Kueue selected, Kueue performs the following steps:
When admitting a
Workload, Kueue evaluates the.nodeSelectorand.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecutionfields in the PodSpecs of yourWorkloadagainst theResourceFlavor’s.spec.nodeLabels.ResourceFlavorsthat conflict with theWorkload’s node selector or required node affinity cannot be assigned to aWorkload’s PodSet (see How Kueue evaluates node selectors and node affinity for details).Once the
Workloadis admitted:Kueue adds the
ResourceFlavor’s.spec.nodeLabelsto the.nodeSelectorof the underlyingWorkloadPod templates if theWorkloaddid not already specify those labels as part of its.nodeSelector.For example, for a
batch/v1.Job, Kueue adds the labels to the.spec.template.spec.nodeSelectorfield. This guarantees that theWorkload’s Pods can only be scheduled on the nodes targeted by the flavor that Kueue assigned to theWorkload(provided flavors assigned across different resource groups do not define conflicting values for the same label key).Kueue adds the
.spec.tolerationsto the underlyingWorkloadPod templates.For example, for a
batch/v1.Job, Kueue adds the tolerations to the.spec.template.spec.tolerationsfield. This allows theWorkload’s Pods to be scheduled on nodes having specific taints.
How Kueue evaluates node selectors and node affinity
Unlike kube-scheduler, which evaluates a Node against the Pod’s complete .nodeSelector and .affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution, Kueue evaluates each ResourceFlavor using only the label keys declared in that flavor’s .spec.nodeLabels:
- Per-flavor key filtering: When evaluating a candidate
ResourceFlavor, Kueue filters the Pod’s.nodeSelectorandrequiredDuringSchedulingIgnoredDuringExecutionmatchExpressionsdown to the keys present in thatResourceFlavor’s.spec.nodeLabels(not the union of keys across all flavors in theClusterQueueresourceGroup). - Non-contradiction matching: Label keys on the Pod that are not declared in the candidate
ResourceFlavor’s.spec.nodeLabelsare ignored during flavor assignment. This allows aWorkloadto constrain scheduling to specific nodes within a flavor (for example, usingkubernetes.io/hostnameor rack labels) without being rejected during flavor selection. After Kueue admits theWorkloadand injects the matched flavor’s.spec.nodeLabels,kube-schedulerenforces the complete.nodeSelectorandnodeAffinityagainst actualNodeobjects. - Node affinity terms: Because
nodeSelectorTermsunderrequiredDuringSchedulingIgnoredDuringExecutionare combined with a logicalOR, if removing unrecognized keys leaves anynodeSelectorTermempty, thenodeAffinityconstraint is treated as satisfied for thatResourceFlavorand matching reduces to.nodeSelector.
For example, consider a Workload Pod with .nodeSelector: {pool: gpu, kubernetes.io/hostname: node-1}. In the table below, the Kubernetes Node evaluation column reflects a candidate node carrying only the labels of that candidate ResourceFlavor:
ResourceFlavor .spec.nodeLabels | Kueue flavor evaluation | Kubernetes Node evaluation | Resulting Pod .nodeSelector after admission |
|---|---|---|---|
{pool: gpu} | Match (kubernetes.io/hostname is not in the flavor’s keys and is ignored) | Reject (missing kubernetes.io/hostname: node-1) | {pool: gpu, kubernetes.io/hostname: node-1} |
{pool: gpu, tier: standard} | Match (pool matches; tier is not contradicted) | Reject (missing kubernetes.io/hostname: node-1) | {pool: gpu, tier: standard, kubernetes.io/hostname: node-1} |
{pool: gpu, kubernetes.io/hostname: node-1} | Match (all flavor keys match) | Match | {pool: gpu, kubernetes.io/hostname: node-1} |
{pool: cpu} | Reject (pool: cpu contradicts pool: gpu) | Reject (pool mismatch and missing kubernetes.io/hostname) | Not admitted to this flavor |
{} (empty ResourceFlavor) | Match (no keys checked) | Reject (missing both keys) | {pool: gpu, kubernetes.io/hostname: node-1} |
Warning
Because each ResourceFlavor ignores .nodeSelector keys that it does not declare in its own .spec.nodeLabels, avoid using different label keys to distinguish mutually exclusive sibling flavors in the same resourceGroup.
For example, if flavor-on-demand defines .spec.nodeLabels: {gpu: l4, on-demand: "true"} and flavor-spot defines .spec.nodeLabels: {gpu: l4, spot: "true"}, a Workload with .nodeSelector: {gpu: l4, spot: "true"} will still match flavor-on-demand (because flavor-on-demand does not declare the spot key and therefore ignores spot: "true").
To ensure a Workload only matches the intended ResourceFlavor, use one of the following patterns:
- Share a common label key across sibling flavors with distinct values, such as
provisioning: on-demandonflavor-on-demandandprovisioning: spotonflavor-spot. Because both flavors declare theprovisioningkey,flavor-on-demandevaluatesprovisioning: spotand rejects the mismatch. - Configure
.spec.nodeTaintson unwanted sibling flavors withNoScheduleorNoExecutetaints that neither theWorkloadnor those flavors’.spec.tolerationstolerate. Add matching tolerations to theWorkloadfor taints on the intended flavor. See ResourceFlavor taints for user-selective scheduling.
A sample ResourceFlavor of this type looks like the following:
apiVersion: kueue.x-k8s.io/v1beta2
kind: ResourceFlavor
metadata:
name: "spot"
spec:
nodeLabels:
instance-type: spot
tolerations:
- key: "spot-taint" ## The key of the node taint.
operator: "Exists"
effect: "NoSchedule" ## Supported effects are NoSchedule, NoExecute, and PreferNoSchedule.
When defining a ResourceFlavor as above, you should set the following values:
- The
.metadata.namefield, which is required to reference a ResourceFlavor from a ClusterQueue in the.spec.resourceGroups[*].flavors[*].namefield. spec.nodeLabelsassociates the ResourceFlavor with a node or subset of nodes.spec.tolerationsadds the specified tolerations to the pods that require GPUs.
ResourceFlavor taints for user-selective scheduling
This approach may be best for teams that wish to schedule their Workload to a specific hardware type selectively. An additional ResourceFlavor can be created per type of special hardware with a different set of taints and tolerations. The user can then add the tolerations to their Workload to schedule the pods onto the appropriate node.
By adding the taint at the ResourceFlavor level, we ensure that only workloads that explicitly tolerate that taint can consume the quota.
Taints on the ResourceFlavor work similarly to Node taints,
but only support the NoExecute and NoSchedule effects, while PreferNoSchedule is ignored.
For Kueue to admit a Workload to use the ResourceFlavor, the PodSpecs in the Workload should have a toleration for it.
On the other hand, when the ResourceFlavor has also set the matching tolerations in .spec.tolerations,
then the taints are not considered during admission.
As opposed to the behavior for ResourceFlavor tolerations for automatic scheduling, Kueue does not add tolerations for the flavor taints.
A sample ResourceFlavor looks like the following:
apiVersion: kueue.x-k8s.io/v1beta2
kind: ResourceFlavor
metadata:
name: "spot"
spec:
nodeLabels:
instance-type: spot
nodeTaints:
- effect: NoSchedule ## Supported effects are NoSchedule and NoExecute, while PreferNoSchedule is ignored.
key: spot
value: "true"
When defining a ResourceFlavor as above, you should set the following values:
- The
.metadata.namefield, which is required to reference a ResourceFlavor from a ClusterQueue in the.spec.resourceGroups[*].flavors[*].namefield. spec.nodeLabelsassociates the ResourceFlavor with a node or subset of nodes.spec.nodeTaintsrestricts usage of a ResourceFlavor. These taints should typically match the taints of the Nodes associated with the ResourceFlavor.
Empty ResourceFlavor
If your cluster has homogeneous resources, or if you don’t need to manage quotas for the different flavors of a resource separately, you can create a ResourceFlavor without any labels or taints. Such ResourceFlavor is called an empty ResourceFlavor and its definition looks like the following:
What’s next?
- Learn about cluster queues.
- Read the API reference for
ResourceFlavor
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.