Skip to content

capacity plugin support DRA - #5058

Merged
volcano-sh-bot merged 2 commits into
volcano-sh:masterfrom
xu-wentao:feat-capacity-dra
May 22, 2026
Merged

capacity plugin support DRA#5058
volcano-sh-bot merged 2 commits into
volcano-sh:masterfrom
xu-wentao:feat-capacity-dra

Conversation

@xu-wentao

@xu-wentao xu-wentao commented Feb 25, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?

/kind feature

What this PR does / why we need it:

This PR introduces Dynamic Resource Allocation (DRA) quota support into the Volcano scheduler's [capacity] plugin.
Key features include:

  1. DRA Quota Management: Allows administrators to define logical quotas for any DRA devices (e.g., specific GPUs, RDMA) per Volcano queue.
  2. Scheduling Enforcement: Prevents jobs and tasks that exceed the queue's DRA capabilities from being enqueued or allocated. Supports both discrete device counts and consumable capacities (e.g., partial GPU memory allocation).
  3. Hierarchical Queue Support: Accurately calculates and propagates DRA resource usage across queue hierarchies.
  4. Pass-through Mode: For DeviceClasses that are not explicitly configured in a Queue's limits, the plugin operates in a "pass-through" mode, allowing tasks to use them without imposing quota restrictions.
    This enhancement ensures fair and controlled distribution of customized DRA resources across multitenant clusters.

Which issue(s) this PR fixes:

Fixes #

Special notes for your reviewer:

  • The DRA quota and consumable capacity checks are controlled by the DynamicResourceAllocationEnable and DRAConsumableCapacityEnable feature flags/plugin arguments.

Does this PR introduce a user-facing change?

Support Dynamic Resource Allocation (DRA) resource quota management in the capacity scheduling plugin.

Copilot AI review requested due to automatic review settings February 25, 2026 09:41
@volcano-sh-bot volcano-sh-bot added the kind/feature Categorizes issue or PR as related to a new feature. label Feb 25, 2026
@volcano-sh-bot volcano-sh-bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Feb 25, 2026
@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello @xu-wentao, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly extends the Volcano scheduler's capacity plugin by integrating comprehensive support for Kubernetes Dynamic Resource Allocation (DRA). The primary goal is to provide robust queue-level quota management for specialized hardware resources, enabling cluster administrators to enforce fair and controlled distribution of these resources in multi-tenant environments. The changes encompass defining new API types for DRA quotas, implementing the logic for aggregating and checking DRA resource requests, and ensuring compatibility with existing hierarchical queue semantics, alongside comprehensive testing and documentation.

Highlights

  • Dynamic Resource Allocation (DRA) Quota Management: Introduced the ability to define logical quotas for Kubernetes DRA devices (e.g., GPUs, RDMA) at the Volcano queue level.
  • Scheduling Enforcement: Implemented mechanisms to prevent jobs and tasks from being enqueued or allocated if they exceed the queue's configured DRA capabilities, supporting both discrete device counts and consumable capacities.
  • Hierarchical Queue Support: Enhanced the capacity plugin to accurately calculate and propagate DRA resource usage across hierarchical queue structures.
  • Pass-through Mode for Unconfigured Devices: Added a "pass-through" mode for DeviceClasses not explicitly configured in a queue's limits, allowing tasks to utilize them without imposing quota restrictions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • docs/design/capacity-dra-support.md
    • Documented the design, motivation, goals, and implementation details for DRA resource quota support in the capacity plugin.
  • docs/user-guide/how_to_use_dra_quota.md
    • Provided a user guide for configuring and utilizing DRA quotas, including examples and troubleshooting tips.
  • pkg/scheduler/api/job_info.go
    • Introduced DRAResreq to TaskInfo for tracking aggregated DRA resource requests.
    • Added DRAResource struct with utility methods for cloning, adding, subtracting, and calculating minimum DRA resources.
  • pkg/scheduler/cache/cache.go
    • Integrated a resourceClaimCache and implemented buildTaskDRAResreq to process and aggregate DRA requests from Pods' ResourceClaims.
  • pkg/scheduler/cache/cache_dra_test.go
    • Added unit tests for buildTaskDRAResreq to ensure correct aggregation of DRA resource requests.
  • pkg/scheduler/cache/cache_mock.go
    • Updated mock informer initialization to include the resourceClaimCache.
  • pkg/scheduler/cache/event_handlers.go
    • Modified NewTaskInfo to populate DRA resource requests for new tasks.
  • pkg/scheduler/plugins/capacity/capacity.go
    • Implemented DRA quota enforcement logic, including new fields for enabling DRA features.
    • Added draQuotaAttr for tracking and functions to check and update allocated DRA resources within queues.
  • pkg/scheduler/plugins/capacity/capacity_dra_test.go
    • Added comprehensive unit tests for the capacity plugin's DRA functionality, covering various allocation and quota scenarios.
  • pkg/scheduler/uthelper/helper.go
    • Ensured cache synchronization in test helper functions for reliable testing.
  • pkg/scheduler/util/test_utils.go
    • Added a helper method to QueueWrapper for easily setting DRA quotas in test queues.
  • staging/src/volcano.sh/apis/pkg/apis/scheduling/types.go
    • Extended QueueSpec with DRAQuota and DRAResourceQuota definitions for API compatibility.
  • staging/src/volcano.sh/apis/pkg/apis/scheduling/v1beta1/types.go
    • Updated QueueSpec with DRAQuota and DRAResourceQuota definitions for the v1beta1 API.
  • staging/src/volcano.sh/apis/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go
    • Generated conversion logic for the new DRA quota types between API versions.
  • test/e2e/dra/dra_quota_test.go
    • Introduced end-to-end tests to validate DRA quota functionality in a live cluster environment.
  • test/e2e/stress/queue.go
    • Adjusted queue creation in stress tests to accommodate the new DRA quota parameter.
  • test/e2e/util/dra.go
    • Added a utility function CreateResourceClaim for creating Kubernetes ResourceClaims in E2E tests.
  • test/e2e/util/job.go
    • Modified job and task specifications to include support for ResourceClaims.
  • test/e2e/util/queue.go
    • Updated queue utility functions to manage DRA quota configurations.
  • test/e2e/util/util.go
    • Extended the test context with a DRAQuota map for E2E test setup.
  • volcano.sh/apis/pkg/client/batch/v1alpha1/cronjob.go
    • Added new generated client file for CronJob in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/batch/v1alpha1/expansion_generated.go
    • Added new generated expansion file for CronJob and Job in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/batch/v1alpha1/job.go
    • Added new generated client file for Job in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/bus/v1alpha1/command.go
    • Added new generated client file for Command in bus/v1alpha1.
  • volcano.sh/apis/pkg/client/bus/v1alpha1/expansion_generated.go
    • Added new generated expansion file for Command in bus/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/batch/interface.go
    • Added new generated informer interface for batch group.
  • volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/cronjob.go
    • Added new generated informer for CronJob in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/interface.go
    • Added new generated informer interface for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/job.go
    • Added new generated informer for Job in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/bus/interface.go
    • Added new generated informer interface for bus group.
  • volcano.sh/apis/pkg/client/externalversions/bus/v1alpha1/command.go
    • Added new generated informer for Command in bus/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/bus/v1alpha1/interface.go
    • Added new generated informer interface for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/externalversions/factory.go
    • Added new generated shared informer factory.
  • volcano.sh/apis/pkg/client/externalversions/generic.go
    • Added new generated generic informer.
  • volcano.sh/apis/pkg/client/externalversions/internalinterfaces/factory_interfaces.go
    • Added new generated internal interfaces for informer factory.
  • volcano.sh/apis/pkg/client/externalversions/scheduling/interface.go
    • Added new generated informer interface for scheduling group.
  • volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/interface.go
    • Added new generated informer interface for scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/podgroup.go
    • Added new generated informer for PodGroup in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/queue.go
    • Added new generated informer for Queue in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/scheduling/v1beta1/expansion_generated.go
    • Added new generated expansion file for PodGroup and Queue in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/scheduling/v1beta1/podgroup.go
    • Added new generated client file for PodGroup in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/scheduling/v1beta1/queue.go
    • Added new generated client file for Queue in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/clientset.go
    • Added new generated clientset.
  • volcano.sh/apis/pkg/client/versioned/fake/clientset_generated.go
    • Added new generated fake clientset.
  • volcano.sh/apis/pkg/client/versioned/fake/doc.go
    • Added new generated fake clientset doc.
  • volcano.sh/apis/pkg/client/versioned/fake/register.go
    • Added new generated fake clientset register.
  • volcano.sh/apis/pkg/client/versioned/scheme/doc.go
    • Added new generated scheme doc.
  • volcano.sh/apis/pkg/client/versioned/scheme/register.go
    • Added new generated scheme register.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/batch_client.go
    • Added new generated typed client for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/cronjob.go
    • Added new generated typed client for CronJob in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/doc.go
    • Added new generated typed client doc for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/doc.go
    • Added new generated fake typed client doc for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_batch_client.go
    • Added new generated fake typed client for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_cronjob.go
    • Added new generated fake typed client for CronJob in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_job.go
    • Added new generated fake typed client for Job in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/generated_expansion.go
    • Added new generated expansion for batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/job.go
    • Added new generated typed client for Job in batch/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/bus_client.go
    • Added new generated typed client for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/command.go
    • Added new generated typed client for Command in bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/doc.go
    • Added new generated typed client doc for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/doc.go
    • Added new generated fake typed client doc for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/fake_bus_client.go
    • Added new generated fake typed client for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/fake_command.go
    • Added new generated fake typed client for Command in bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/generated_expansion.go
    • Added new generated expansion for bus/v1alpha1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/doc.go
    • Added new generated typed client doc for scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/doc.go
    • Added new generated fake typed client doc for scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_podgroup.go
    • Added new generated fake typed client for PodGroup in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_queue.go
    • Added new generated fake typed client for Queue in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_scheduling_client.go
    • Added new generated fake typed client for scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/generated_expansion.go
    • Added new generated expansion for scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/podgroup.go
    • Added new generated typed client for PodGroup in scheduling/v1beta1.
  • volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/queue.go
    • Added new generated typed client for Queue in scheduling/v1beta1.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces Dynamic Resource Allocation (DRA) quota support into the Volcano scheduler's capacity plugin. The changes are extensive, touching API definitions, documentation, core scheduler cache logic, the capacity plugin, and tests. The implementation follows the design document well and adds a significant new capability for managing specialized resources like GPUs.

My review has identified one high-severity correctness issue related to a side effect in a resource calculation function, which could lead to incorrect scheduling behavior. I've also found a minor typo in the design document. Overall, this is a well-structured and comprehensive feature addition.

Comment on lines +1422 to +1481
func (ji *JobInfo) GetMinDRAResources() map[string]*DRAResource {
if len(ji.Tasks) == 0 {
return nil
}

result := make(map[string]*DRAResource)

// Since DRA requests can vary per task/pod, we aggregate them based on TaskMinAvailable
for _, task := range ji.Tasks {
if task.DRAResreq == nil {
continue
}

// Calculate how many times this task type needs to run
taskType := task.TaskRole
minNum, ok := ji.TaskMinAvailable[taskType]
if !ok || minNum <= 0 {
// If TaskMinAvailable is not set, default to 1 for this task if it is part of the job's minAvailable
// However, for precise minimum calculation, we only count the first occurrence for each TaskRole
// and multiply it by minNum
continue
}

// Only process one sample task per TaskRole to represent that type
// Set minNum to 0 so we don't process it again
ji.TaskMinAvailable[taskType] = 0

for deviceClass, res := range task.DRAResreq {
if _, exists := result[deviceClass]; !exists {
result[deviceClass] = &DRAResource{
Count: 0,
Capacity: make(map[string]resource.Quantity),
}
}

result[deviceClass].Count += res.Count * int64(minNum)
for dim, cap := range res.Capacity {
totalCap := cap.DeepCopy()
// resource.Quantity has no Multiply func, so we parse memory/cpu as MilliValues
// For exact values we can just use set
// Since Quantity can represent fractional, we will loop to add
for i := int32(0); i < minNum-1; i++ {
totalCap.Add(cap)
}

if existing, exists := result[deviceClass].Capacity[dim]; exists {
existing.Add(totalCap)
result[deviceClass].Capacity[dim] = existing
} else {
result[deviceClass].Capacity[dim] = totalCap
}
}
}
}

if len(result) == 0 {
return nil
}
return result
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The function GetMinDRAResources modifies ji.TaskMinAvailable by setting values to 0. This is a side effect that makes the function non-idempotent. If this function is called multiple times on the same JobInfo object within a scheduling cycle, subsequent calls will produce incorrect results (likely nil), which could lead to incorrect scheduling decisions. Get... functions should generally be read-only and not modify their receiver's state.

To fix this, please use a local map to track which task roles have been processed, instead of modifying ji.TaskMinAvailable.

func (ji *JobInfo) GetMinDRAResources() map[string]*DRAResource {
	if len(ji.Tasks) == 0 {
		return nil
	}

	result := make(map[string]*DRAResource)
	processedRoles := make(map[string]struct{})

	// Since DRA requests can vary per task/pod, we aggregate them based on TaskMinAvailable
	for _, task := range ji.Tasks {
		if task.DRAResreq == nil {
			continue
		}

		taskType := task.TaskRole
		if _, ok := processedRoles[taskType]; ok {
			continue
		}

		// Calculate how many times this task type needs to run
		minNum, ok := ji.TaskMinAvailable[taskType]
		if !ok || minNum <= 0 {
			// If TaskMinAvailable is not set, default to 1 for this task if it is part of the job's minAvailable
			// However, for precise minimum calculation, we only count the first occurrence for each TaskRole
			// and multiply it by minNum
			continue
		}

		// Only process one sample task per TaskRole to represent that type
		processedRoles[taskType] = struct{}{}

		for deviceClass, res := range task.DRAResreq {
			if _, exists := result[deviceClass]; !exists {
				result[deviceClass] = &DRAResource{
					Count:    0,
					Capacity: make(map[string]resource.Quantity),
				}
			}

			result[deviceClass].Count += res.Count * int64(minNum)
			for dim, cap := range res.Capacity {
				totalCap := cap.DeepCopy()
				// resource.Quantity has no Multiply func, so we parse memory/cpu as MilliValues
				// For exact values we can just use set
				// Since Quantity can represent fractional, we will loop to add
				for i := int32(0); i < minNum-1; i++ {
					totalCap.Add(cap)
				}

				if existing, exists := result[deviceClass].Capacity[dim]; exists {
					existing.Add(totalCap)
					result[deviceClass].Capacity[dim] = existing
				} else {
					result[deviceClass].Capacity[dim] = totalCap
				}
			}
		}
	}

	if len(result) == 0 {
		return nil
	}
	return result
}

Comment thread docs/design/capacity-dra-support.md Outdated
| Field | Semantics | Enforcement |
|-------|-----------|-------------|
| `dra.capability` | Hard limit, cannot exceed | Allocation rejected if quota would be exceeded |
| `dra.deserved` | Future extensibility | Currenly NOT supported for elasticity/preemption in capacity plugin |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a typo here. "Currenly" should be "Currently".

Suggested change
| `dra.deserved` | Future extensibility | Currenly NOT supported for elasticity/preemption in capacity plugin |
| `dra.deserved` | Future extensibility | Currently NOT supported for elasticity/preemption in capacity plugin |

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Dynamic Resource Allocation (DRA) quota modeling to Queue APIs and wires DRA request accounting/enforcement into the scheduler capacity plugin, with accompanying unit/e2e tests and documentation.

Changes:

  • Extend QueueSpec (internal + v1beta1) with spec.dra quotas (count + optional consumable capacity) and add conversions.
  • Track per-task DRA requests (via ResourceClaims) in scheduler cache and enforce queue DRA capability in the capacity plugin (allocate + enqueue paths, incl. hierarchical propagation).
  • Add DRA-focused tests and user/design docs.

Reviewed changes

Copilot reviewed 73 out of 73 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/scheduling_client.go New generated scheduling typed client (appears misplaced; see comments).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/queue.go New generated Queue typed client (appears misplaced; see comments).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/podgroup.go New generated PodGroup typed client (appears misplaced; see comments).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/generated_expansion.go New generated expansion interfaces (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_scheduling_client.go New generated fake scheduling client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_queue.go New generated fake Queue client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/fake_podgroup.go New generated fake PodGroup client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/fake/doc.go New generated fake package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/scheduling/v1beta1/doc.go New generated package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/generated_expansion.go New generated expansion interfaces (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/fake_command.go New generated fake Command client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/fake_bus_client.go New generated fake bus client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/fake/doc.go New generated fake package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/doc.go New generated package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/command.go New generated Command typed client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/bus/v1alpha1/bus_client.go New generated bus typed client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/job.go New generated Job typed client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/generated_expansion.go New generated expansion interfaces (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_job.go New generated fake Job client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_cronjob.go New generated fake CronJob client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/fake_batch_client.go New generated fake batch client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/fake/doc.go New generated fake package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/doc.go New generated package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/cronjob.go New generated CronJob typed client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/typed/batch/v1alpha1/batch_client.go New generated batch typed client (appears misplaced).
volcano.sh/apis/pkg/client/versioned/scheme/register.go New generated scheme registration (appears misplaced).
volcano.sh/apis/pkg/client/versioned/scheme/doc.go New generated scheme package doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/fake/register.go New generated fake scheme registration (appears misplaced).
volcano.sh/apis/pkg/client/versioned/fake/doc.go New generated fake clientset doc (appears misplaced).
volcano.sh/apis/pkg/client/versioned/fake/clientset_generated.go New generated fake clientset (appears misplaced).
volcano.sh/apis/pkg/client/versioned/clientset.go New generated clientset (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/scheduling/v1beta1/queue.go New generated lister (appears misplaced).
volcano.sh/apis/pkg/client/scheduling/v1beta1/podgroup.go New generated lister (appears misplaced).
volcano.sh/apis/pkg/client/scheduling/v1beta1/expansion_generated.go New generated lister expansions (appears misplaced).
volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/queue.go New generated informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/podgroup.go New generated informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/scheduling/v1beta1/interface.go New generated informer interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/scheduling/interface.go New generated informer group interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/internalinterfaces/factory_interfaces.go New generated informer internal interfaces (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/generic.go New generated generic informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/factory.go New generated shared informer factory (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/bus/v1alpha1/interface.go New generated bus informer interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/bus/v1alpha1/command.go New generated Command informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/bus/interface.go New generated bus group informer interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/job.go New generated Job informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/interface.go New generated batch informer interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/batch/v1alpha1/cronjob.go New generated CronJob informer (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/externalversions/batch/interface.go New generated batch group informer interface (appears misplaced; invalid imports).
volcano.sh/apis/pkg/client/bus/v1alpha1/expansion_generated.go New generated bus lister expansions (appears misplaced).
volcano.sh/apis/pkg/client/bus/v1alpha1/command.go New generated bus lister (appears misplaced).
volcano.sh/apis/pkg/client/batch/v1alpha1/job.go New generated batch lister (appears misplaced).
volcano.sh/apis/pkg/client/batch/v1alpha1/expansion_generated.go New generated batch lister expansions (appears misplaced).
volcano.sh/apis/pkg/client/batch/v1alpha1/cronjob.go New generated batch lister (appears misplaced).
test/e2e/util/util.go Extend e2e test context/options with per-queue DRA quota config.
test/e2e/util/queue.go Allow creating queues with spec.dra in e2e utilities (signature change).
test/e2e/util/job.go Allow setting pod.spec.resourceClaims via e2e job/task specs.
test/e2e/util/dra.go Add helper to create ResourceClaims in e2e tests.
test/e2e/stress/queue.go Update stress test to new CreateQueue signature (adds nil DRA arg).
test/e2e/dra/dra_quota_test.go New e2e coverage for DRA quota enforcement scenarios.
staging/src/volcano.sh/apis/pkg/apis/scheduling/v1beta1/zz_generated.conversion.go Add conversions for QueueSpec.DRA + DRAQuota/DRAResourceQuota.
staging/src/volcano.sh/apis/pkg/apis/scheduling/v1beta1/types.go Add v1beta1 API types for spec.dra quotas.
staging/src/volcano.sh/apis/pkg/apis/scheduling/types.go Add internal API types for spec.dra quotas.
pkg/scheduler/util/test_utils.go Add QueueWrapper helper to set QueueSpec.DRA in unit tests.
pkg/scheduler/uthelper/helper.go Wait for scheduler cache sync in unit-test harness.
pkg/scheduler/plugins/capacity/capacity_dra_test.go New unit tests for capacity plugin DRA quota behavior.
pkg/scheduler/plugins/capacity/capacity.go Implement DRA quota tracking + enforcement (allocate + enqueue paths, hierarchical propagation).
pkg/scheduler/cache/event_handlers.go Populate TaskInfo.DRAResreq when building TaskInfo from Pod.
pkg/scheduler/cache/cache_mock.go Ensure mock cache initializes ResourceClaim assume-cache for tests.
pkg/scheduler/cache/cache_dra_test.go New unit test for building task DRA requests from ResourceClaims.
pkg/scheduler/cache/cache.go Add ResourceClaim cache + buildTaskDRAResreq aggregation logic.
pkg/scheduler/api/job_info.go Add DRAResource model, task cloning support, and job min-DRA computation.
docs/user-guide/how_to_use_dra_quota.md New user guide for configuring/using queue DRA quotas.
docs/design/capacity-dra-support.md New design doc describing DRA quota support in capacity plugin.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread pkg/scheduler/cache/cache_dra_test.go Outdated
Comment on lines +51 to +54
// A simpler way often used in k8s tests:
featureGate := utilfeature.DefaultFeatureGate.(k8sfeature.MutableFeatureGate)
if err := featureGate.SetFromMap(map[string]bool{string(kubefeatures.DynamicResourceAllocation): true}); err != nil {
t.Logf("Failed to enable DynamicResourceAllocation feature gate: %v", err)

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test does an unchecked type assertion utilfeature.DefaultFeatureGate.(k8sfeature.MutableFeatureGate), which will panic if the default gate isn’t mutable in a given test environment. Use featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, kubefeatures.DynamicResourceAllocation, true) (or at least guard the assertion) to make the test robust.

Copilot uses AI. Check for mistakes.
Comment thread docs/design/capacity-dra-support.md Outdated
| Field | Semantics | Enforcement |
|-------|-----------|-------------|
| `dra.capability` | Hard limit, cannot exceed | Allocation rejected if quota would be exceeded |
| `dra.deserved` | Future extensibility | Currenly NOT supported for elasticity/preemption in capacity plugin |

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Spelling: CurrenlyCurrently.

Suggested change
| `dra.deserved` | Future extensibility | Currenly NOT supported for elasticity/preemption in capacity plugin |
| `dra.deserved` | Future extensibility | Currently NOT supported for elasticity/preemption in capacity plugin |

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +26
import (
batchv1alpha1 "clientset/versioned/typed/batch/v1alpha1"
busv1alpha1 "clientset/versioned/typed/bus/v1alpha1"
schedulingv1beta1 "clientset/versioned/typed/scheduling/v1beta1"
fmt "fmt"
http "net/http"

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generated clientset code under volcano.sh/apis/pkg/client/... uses import paths like clientset/versioned/typed/... and clientset/versioned/scheme, but there is no clientset/... package in this repo/module. As-is, these files won’t compile under the main volcano.sh/volcano module. These generated clients should either be removed (if the canonical client lives under staging/src/volcano.sh/apis/pkg/client/...) or regenerated with correct module import paths (e.g. volcano.sh/apis/pkg/client/clientset/versioned/...).

Copilot uses AI. Check for mistakes.
Comment on lines +21 to +25
import (
batch "informers/externalversions/batch"
bus "informers/externalversions/bus"
internalinterfaces "informers/externalversions/internalinterfaces"
scheduling "informers/externalversions/scheduling"

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This informer factory code imports informers/externalversions/..., but that package path does not exist in this repo/module (the existing generated informers are under volcano.sh/apis/pkg/client/informers/externalversions/... in staging). This will fail to compile; please remove these duplicate generated informers or regenerate them with the correct import paths/output directory.

Copilot uses AI. Check for mistakes.
Comment thread pkg/scheduler/cache/cache.go Outdated
Comment on lines +1790 to +1806
if !utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DynamicResourceAllocation) || len(pod.Spec.ResourceClaims) == 0 {
return nil
}

result := make(map[string]*schedulingapi.DRAResource)
consumableCapacityEnabled := utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DRAConsumableCapacity)

for _, podClaim := range pod.Spec.ResourceClaims {
if podClaim.ResourceClaimName == nil {
continue
}
claimName := *podClaim.ResourceClaimName
obj, err := sc.resourceClaimCache.Get(pod.Namespace + "/" + claimName)
if err != nil || obj == nil {
klog.V(4).Infof("Failed to get ResourceClaim %s/%s: %v", pod.Namespace, claimName, err)
continue
}

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildTaskDRAResreq silently ignores missing/unsynced ResourceClaims (it logs and continues). That can permanently leave TaskInfo.DRAResreq empty for pods that do request DRA devices, which bypasses queue DRA quota enforcement. Consider failing task creation when any referenced claim can’t be retrieved (propagate an error via NewTaskInfo), or marking the task as unschedulable until the claim is present, rather than treating it as ‘no DRA request’. Also add a nil-guard for sc.resourceClaimCache to avoid panics when DRA is enabled but the cache isn’t initialized in some test/mocked cache setups.

Copilot uses AI. Check for mistakes.
Comment thread pkg/scheduler/api/job_info.go Outdated
Comment on lines +1435 to +1448
// Calculate how many times this task type needs to run
taskType := task.TaskRole
minNum, ok := ji.TaskMinAvailable[taskType]
if !ok || minNum <= 0 {
// If TaskMinAvailable is not set, default to 1 for this task if it is part of the job's minAvailable
// However, for precise minimum calculation, we only count the first occurrence for each TaskRole
// and multiply it by minNum
continue
}

// Only process one sample task per TaskRole to represent that type
// Set minNum to 0 so we don't process it again
ji.TaskMinAvailable[taskType] = 0

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GetMinDRAResources mutates ji.TaskMinAvailable (ji.TaskMinAvailable[taskType] = 0) while computing a derived value. This introduces side effects that can break later scheduling logic that relies on TaskMinAvailable remaining intact. Use a local seenTaskRoles set (or copy of TaskMinAvailable) to ensure each TaskRole is only processed once, without modifying the JobInfo state.

Copilot uses AI. Check for mistakes.
Comment thread pkg/scheduler/api/job_info.go Outdated
Comment on lines +1437 to +1443
minNum, ok := ji.TaskMinAvailable[taskType]
if !ok || minNum <= 0 {
// If TaskMinAvailable is not set, default to 1 for this task if it is part of the job's minAvailable
// However, for precise minimum calculation, we only count the first occurrence for each TaskRole
// and multiply it by minNum
continue
}

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says to default to 1 when TaskMinAvailable isn’t set, but the current behavior is to continue, which can undercount the job’s minimum DRA needs and allow oversize jobs to be enqueued. If the intent is ‘default 1’, implement that fallback (and still ensure you only process one representative task per TaskRole).

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +45
func Test_capacityPlugin_DRA(t *testing.T) {
// Enable DRA feature gate
utilfeature.DefaultMutableFeatureGate.Set(fmt.Sprintf("%s=true", kubefeatures.DynamicResourceAllocation))

Copilot AI Feb 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test enables the global DynamicResourceAllocation feature gate via utilfeature.DefaultMutableFeatureGate.Set(...) but doesn’t restore the original value, which can leak into other tests and cause order-dependent failures. Prefer featuregatetesting.SetFeatureGateDuringTest (as used elsewhere in the repo) or explicitly defer resetting the gate to its prior state.

Copilot uses AI. Check for mistakes.
@JesseStutler

Copy link
Copy Markdown
Member

Would you be willing to share on tomorrow's Asia community meeting? The meeting time is 15:00 UTC+8

@JesseStutler

JesseStutler commented Apr 7, 2026

Copy link
Copy Markdown
Member

@xu-wentao Any update on the PR? :)

@xu-wentao
xu-wentao force-pushed the feat-capacity-dra branch 4 times, most recently from 457c170 to 49a4244 Compare April 8, 2026 17:34
@xu-wentao

Copy link
Copy Markdown
Contributor Author

@xu-wentao Any update on the PR? :)

Yes, I have updated the implemention of the DRA metioned here, we can discuss thie design again.

@JesseStutler

Copy link
Copy Markdown
Member

Please resolve the CI failure and sign off your commits, and there are also conflict codes that you need to resolve @xu-wentao

Comment thread process.md Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment thread .gitignore

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do add a volcano.sh ignore item?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The folder volcano.sh is not in this project, but if we run make generate-code will create this folder automatilly, If we no need to upload it, maybe ignore it is a way i think?

@xu-wentao
xu-wentao force-pushed the feat-capacity-dra branch 3 times, most recently from a336583 to 4f7d588 Compare April 13, 2026 14:27
dynamicResourceAllocationEnable := utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DynamicResourceAllocation)
draConsumableCapacityEnable := utilfeature.DefaultFeatureGate.Enabled(kubefeatures.DRAConsumableCapacity)

arguments.GetBool(&dynamicResourceAllocationEnable, DynamicResourceAllocationEnable)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should sync to the user guide to allow users know there are such arguments for capacity plugins, default is controlled by feature gate values

spec:
reclaimable: true
capability:
"cores.deviceclass/hami-core-gpu.project-hami.io": "800"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be best to further clarify the scenario for consumable capacity here. If consumable capacity is specified, then [dims].deviceclass/xxx should be configured as count * capacity, right? This could be explained to guide users.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should also update the inqueued attr when the pg can be enqueued (especially for simultaneously submit jobs it's useful): https://github.com/volcano-sh/volcano/blob/da719bb3b636ecce560798d9ec0f19c74e3b412c/pkg/scheduler/plugins/capacity/capacity. go#L271


DRA quota is expressed directly in the queue `ResourceList` using reserved key formats.

### Key Formats

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the scenario of consumable capacity, I may have a worry. For example, if a card has virtualization, then one ResourceSlice corresponds to multiple slices inside, right? So currently your design is flattened at the deviceclass level, regardless of how many slices a ResourceSlice has, we configure a total amount. For instance, if there are 2 cards (in the same ResourceSlice), each card has 8Gi of GPU memory, and the total I configure on the queue is 16Gi. If I configure 16Gi at the deviceclass level on the queue, and a podgroup requests 2 pods with 10Gi + 4Gi respectively, then one pod actually cannot be scheduled. However, it gets through the queue validation and occupies inqueue resources. Is this acceptable?

I think the current design is fine, but I believe there might be a potential issue, similar to how node had fragmented resources before. However, the queue check still passed, but I don't know if users would report such a problem. I think it could be stated as a constraint in the design doc or user guide doc

// For exact values we can just use set
// Since Quantity can represent fractional, we will loop to add
for i := int32(0); i < minNum-1; i++ {
totalCap.Add(cap)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Consumable Capacity, it should also be multiplied by count to get the total capacity resource, right? For example, a single pod requires 2 * 8Gi of GPU memory, and there are 2 pods in total, so the total requirement should be 32Gi, not 8Gi * 2 pods = 16Gi?

Comment thread pkg/scheduler/cache/cache_dra_test.go Outdated
@@ -0,0 +1,245 @@
/*
Copyright 2024 The Volcano Authors.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All should change to -> 2026 The Volcano Authors

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we construct a Driver that can produce ResourceSlices containing multiple devices, each device with a capacity? I'd like to see such use case if it's possible

@JesseStutler

Copy link
Copy Markdown
Member

Please also resolve the conflicts and sign off the commits
BTW do you have screenshots of the actual successful allocation report, for example:

  1. The queue quota can actually block the pod, preventing it from being scheduled.
  2. Successfully assigned, the queue status displays the status after dra assignment.
    Would be better to see the actual effect :D
    @xu-wentao

@xu-wentao
xu-wentao force-pushed the feat-capacity-dra branch 4 times, most recently from 6c0a9f5 to e8506cb Compare May 5, 2026 05:26
@JesseStutler

Copy link
Copy Markdown
Member

There is a conflict @xu-wentao Please rebase to the latest codes and push again, thanks

@JesseStutler

JesseStutler commented May 21, 2026

Copy link
Copy Markdown
Member

/ok-to-test
Let me first resolve it and trigger the CIs, still needs to force push again in your local

@volcano-sh-bot volcano-sh-bot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. do-not-merge/contains-merge-commits labels May 21, 2026
func (cp *capacityPlugin) queueAllocatableWithReserved(attr *queueAttr, candidate *api.TaskInfo, queue *api.QueueInfo, draEnabled bool, consumableCapacityEnabled bool) bool {
if draEnabled && attr.dra != nil && candidate.DRAResreq != nil {
if !checkDRAAllocatable(attr.dra, candidate.DRAResreq, consumableCapacityEnabled) {
candidateDRA := incrementalTaskDRA(attr, candidate)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this line inside the draEnabled judgement is better

@JesseStutler

Copy link
Copy Markdown
Member

#5058 (comment) I think you should still open the feature gate for the volcano scheduler:

E2E_TYPE=DRA FEATURE_GATES="DynamicResourceAllocation=true,DRAConsumableCapacity=true" ./hack/run-e2e-kind.sh 

Only open the feature gate in the kind config is opened for the kube-scheduler, not for the volcano scheduler @xu-wentao

Signed-off-by: xuwentao <cutenear1993@yahoo.com>
Signed-off-by: xuwentao <cutenear1993@yahoo.com>
@xu-wentao
xu-wentao force-pushed the feat-capacity-dra branch from e08866b to 5ba79f3 Compare May 22, 2026 05:08
@JesseStutler JesseStutler moved this from Triaging to In progress in Volcano Release Tracking May 22, 2026
@JesseStutler JesseStutler moved this from In progress to In review in Volcano Release Tracking May 22, 2026
@JesseStutler

Copy link
Copy Markdown
Member

/approve
/lgtm
Thank you so much for your great work!

@volcano-sh-bot volcano-sh-bot added the lgtm Indicates that a PR is ready to be merged. label May 22, 2026
@volcano-sh-bot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JesseStutler

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@volcano-sh-bot volcano-sh-bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 22, 2026
@volcano-sh-bot
volcano-sh-bot merged commit f20d4f9 into volcano-sh:master May 22, 2026
26 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in Volcano Release Tracking May 22, 2026
gucardona added a commit to gucardona/volcano that referenced this pull request Jul 7, 2026
A Pod ADD event can reach the scheduler before its referenced PVC ADD
reaches the PVC informer — for example when a Pod is created together
with an OnDemand PVC in quick succession (Spark's k8s scheduler-backend
does exactly this for executor pods with `claimName=OnDemand`).

Since v1.15.0, the resulting `looking up PVC ... not found` error from
NewTaskInfo permanently strands the pod:

    addPod → NewTaskInfo → addPodCSIVolumesToTask
      → pvcInformer.Lister().Get(pvcName) returns not-found
      → klog.Errorf(...)
      → sc.resyncTask(pi)        // enqueues taskKey into errTasks
      → return err               // task never enters sc.Jobs

    processResyncTask → errTasks.Get() → parseErrTaskKey → getTaskByUID
      → "failed to find task <uid>"
      → errTasks.Forget(taskKey) // permanent
      → return                   // never reaches retryResyncTask

There is no PVC-informer AddFunc that re-queues stuck pods, and the
pod's resourceVersion never advances before scheduling, so
`UpdatePod → deletePod + addPod` never fires. Executor pods stay
Pending; the PVC stays Pending with `WaitForPodScheduled`.

Before volcano-sh#5058, `addPod`'s error branch fell through to `sc.addTask(pi)`
even after `NewTaskInfo` returned an error, so the incomplete task
lived in `sc.Jobs` and processResyncTask could find it by UID on the
next tick and call syncTask, which refetches the pod from the apiserver
— by which point the PVC informer has synced. volcano-sh#5058 added a DRA-specific
happy path using the correct `addTask + resyncTask + return nil`
pattern, but also added a generic `return err` that removed the
implicit recovery for PVC-not-found.

Extend the DRA branch to PVC-not-found errors, using the same pattern.
Change getPodCSIVolumes to wrap the lister error with %w so callers
can classify it with errors.Is / apierrors.IsNotFound instead of
matching on the message string.

Adds `TestAddPodWithUnresolvedPVCCachesTaskForResync` mirroring the
existing DRA counterpart.

Version scope: only v1.15.0 is affected. Verified with
`git merge-base --is-ancestor 5ba79f3 <tag>` — every v1.14.x tag
through v1.14.3 (released after v1.15.0) is clean; v1.15.0-alpha.0 is
also clean.

Signed-off-by: Gustavo Parcianello <gustavo.parcianello@sap.com>
gucardona added a commit to gucardona/volcano that referenced this pull request Jul 7, 2026
A Pod ADD event can reach the scheduler before its referenced PVC ADD
reaches the PVC informer — for example when a Pod is created together
with an OnDemand PVC in quick succession (Spark's k8s scheduler-backend
does exactly this for executor pods with `claimName=OnDemand`).

Since v1.15.0, the resulting `looking up PVC ... not found` error from
NewTaskInfo permanently strands the pod:

    addPod → NewTaskInfo → addPodCSIVolumesToTask
      → pvcInformer.Lister().Get(pvcName) returns not-found
      → klog.Errorf(...)
      → sc.resyncTask(pi)        // enqueues taskKey into errTasks
      → return err               // task never enters sc.Jobs

    processResyncTask → errTasks.Get() → parseErrTaskKey → getTaskByUID
      → "failed to find task <uid>"
      → errTasks.Forget(taskKey) // permanent
      → return                   // never reaches retryResyncTask

There is no PVC-informer AddFunc that re-queues stuck pods, and the
pod's resourceVersion never advances before scheduling, so
`UpdatePod → deletePod + addPod` never fires. Executor pods stay
Pending; the PVC stays Pending with `WaitForPodScheduled`.

Before volcano-sh#5058, `addPod`'s error branch fell through to `sc.addTask(pi)`
even after `NewTaskInfo` returned an error, so the incomplete task
lived in `sc.Jobs` and processResyncTask could find it by UID on the
next tick and call syncTask, which refetches the pod from the apiserver
— by which point the PVC informer has synced. volcano-sh#5058 added a DRA-specific
happy path using the correct `addTask + resyncTask + return nil`
pattern, but also added a generic `return err` that removed the
implicit recovery for PVC-not-found.

Extend the DRA branch to PVC-not-found errors, using the same pattern.
Change getPodCSIVolumes to wrap the lister error with %w so callers
can classify it with errors.Is / apierrors.IsNotFound instead of
matching on the message string.

Adds `TestAddPodWithUnresolvedPVCCachesTaskForResync` mirroring the
existing DRA counterpart.

Version scope: only v1.15.0 is affected. Verified with
`git merge-base --is-ancestor 5ba79f3 <tag>` — every v1.14.x tag
through v1.14.3 (released after v1.15.0) is clean; v1.15.0-alpha.0 is
also clean.

Signed-off-by: Gustavo Parcianello <gustavo.parcianello@sap.com>
gucardona added a commit to gucardona/volcano that referenced this pull request Jul 8, 2026
A Pod ADD event can reach the scheduler before its referenced PVC ADD
reaches the PVC informer — for example when a Pod is created together
with an OnDemand PVC in quick succession (Spark's k8s scheduler-backend
does exactly this for executor pods with `claimName=OnDemand`).

Since v1.15.0, the resulting `looking up PVC ... not found` error from
NewTaskInfo permanently strands the pod:

    addPod → NewTaskInfo → addPodCSIVolumesToTask
      → pvcInformer.Lister().Get(pvcName) returns not-found
      → klog.Errorf(...)
      → sc.resyncTask(pi)        // enqueues taskKey into errTasks
      → return err               // task never enters sc.Jobs

    processResyncTask → errTasks.Get() → parseErrTaskKey → getTaskByUID
      → "failed to find task <uid>"
      → errTasks.Forget(taskKey) // permanent
      → return                   // never reaches retryResyncTask

There is no PVC-informer AddFunc that re-queues stuck pods, and the
pod's resourceVersion never advances before scheduling, so
`UpdatePod → deletePod + addPod` never fires. Executor pods stay
Pending; the PVC stays Pending with `WaitForPodScheduled`.

Before volcano-sh#5058, `addPod`'s error branch fell through to `sc.addTask(pi)`
even after `NewTaskInfo` returned an error, so the incomplete task
lived in `sc.Jobs` and processResyncTask could find it by UID on the
next tick and call syncTask, which refetches the pod from the apiserver
— by which point the PVC informer has synced. volcano-sh#5058 added a DRA-specific
happy path using the correct `addTask + resyncTask + return nil`
pattern, but also added a generic `return err` that removed the
implicit recovery for PVC-not-found.

Extend the DRA branch to PVC-not-found errors, using the same pattern.
Change getPodCSIVolumes to wrap the lister error with %w so callers
can classify it with errors.Is / apierrors.IsNotFound instead of
matching on the message string.

Adds `TestAddPodWithUnresolvedPVCCachesTaskForResync` mirroring the
existing DRA counterpart.

Version scope: only v1.15.0 is affected. Verified with
`git merge-base --is-ancestor 5ba79f3 <tag>` — every v1.14.x tag
through v1.14.3 (released after v1.15.0) is clean; v1.15.0-alpha.0 is
also clean.

Signed-off-by: Gustavo Parcianello <gustavo.parcianello@sap.com>
gucardona added a commit to gucardona/volcano that referenced this pull request Jul 16, 2026
A Pod ADD event can reach the scheduler before its referenced PVC ADD
reaches the PVC informer — for example when a Pod is created together
with an OnDemand PVC in quick succession (Spark's k8s scheduler-backend
does exactly this for executor pods with `claimName=OnDemand`).

Since v1.15.0, the resulting `looking up PVC ... not found` error from
NewTaskInfo permanently strands the pod:

    addPod → NewTaskInfo → addPodCSIVolumesToTask
      → pvcInformer.Lister().Get(pvcName) returns not-found
      → klog.Errorf(...)
      → sc.resyncTask(pi)        // enqueues taskKey into errTasks
      → return err               // task never enters sc.Jobs

    processResyncTask → errTasks.Get() → parseErrTaskKey → getTaskByUID
      → "failed to find task <uid>"
      → errTasks.Forget(taskKey) // permanent
      → return                   // never reaches retryResyncTask

There is no PVC-informer AddFunc that re-queues stuck pods, and the
pod's resourceVersion never advances before scheduling, so
`UpdatePod → deletePod + addPod` never fires. Executor pods stay
Pending; the PVC stays Pending with `WaitForPodScheduled`.

Before volcano-sh#5058, `addPod`'s error branch fell through to `sc.addTask(pi)`
even after `NewTaskInfo` returned an error, so the incomplete task
lived in `sc.Jobs` and processResyncTask could find it by UID on the
next tick and call syncTask, which refetches the pod from the apiserver
— by which point the PVC informer has synced. volcano-sh#5058 added a DRA-specific
happy path using the correct `addTask + resyncTask + return nil`
pattern, but also added a generic `return err` that removed the
implicit recovery for PVC-not-found.

Extend the DRA branch to PVC-not-found errors, using the same pattern.
Change getPodCSIVolumes to wrap the lister error with %w so callers
can classify it with errors.Is / apierrors.IsNotFound instead of
matching on the message string.

Adds `TestAddPodWithUnresolvedPVCCachesTaskForResync` mirroring the
existing DRA counterpart.

Version scope: only v1.15.0 is affected. Verified with
`git merge-base --is-ancestor 5ba79f3 <tag>` — every v1.14.x tag
through v1.14.3 (released after v1.15.0) is clean; v1.15.0-alpha.0 is
also clean.

Signed-off-by: Gustavo Parcianello <gustavo.parcianello@sap.com>
gitGurugu pushed a commit to gitGurugu/LFX-Term-2 that referenced this pull request Aug 4, 2026
A Pod ADD event can reach the scheduler before its referenced PVC ADD
reaches the PVC informer — for example when a Pod is created together
with an OnDemand PVC in quick succession (Spark's k8s scheduler-backend
does exactly this for executor pods with `claimName=OnDemand`).

Since v1.15.0, the resulting `looking up PVC ... not found` error from
NewTaskInfo permanently strands the pod:

    addPod → NewTaskInfo → addPodCSIVolumesToTask
      → pvcInformer.Lister().Get(pvcName) returns not-found
      → klog.Errorf(...)
      → sc.resyncTask(pi)        // enqueues taskKey into errTasks
      → return err               // task never enters sc.Jobs

    processResyncTask → errTasks.Get() → parseErrTaskKey → getTaskByUID
      → "failed to find task <uid>"
      → errTasks.Forget(taskKey) // permanent
      → return                   // never reaches retryResyncTask

There is no PVC-informer AddFunc that re-queues stuck pods, and the
pod's resourceVersion never advances before scheduling, so
`UpdatePod → deletePod + addPod` never fires. Executor pods stay
Pending; the PVC stays Pending with `WaitForPodScheduled`.

Before volcano-sh#5058, `addPod`'s error branch fell through to `sc.addTask(pi)`
even after `NewTaskInfo` returned an error, so the incomplete task
lived in `sc.Jobs` and processResyncTask could find it by UID on the
next tick and call syncTask, which refetches the pod from the apiserver
— by which point the PVC informer has synced. volcano-sh#5058 added a DRA-specific
happy path using the correct `addTask + resyncTask + return nil`
pattern, but also added a generic `return err` that removed the
implicit recovery for PVC-not-found.

Extend the DRA branch to PVC-not-found errors, using the same pattern.
Change getPodCSIVolumes to wrap the lister error with %w so callers
can classify it with errors.Is / apierrors.IsNotFound instead of
matching on the message string.

Adds `TestAddPodWithUnresolvedPVCCachesTaskForResync` mirroring the
existing DRA counterpart.

Version scope: only v1.15.0 is affected. Verified with
`git merge-base --is-ancestor 5ba79f3 <tag>` — every v1.14.x tag
through v1.14.3 (released after v1.15.0) is clean; v1.15.0-alpha.0 is
also clean.

Signed-off-by: Gustavo Parcianello <gustavo.parcianello@sap.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. kind/feature Categorizes issue or PR as related to a new feature. lgtm Indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants