Skip to content

Commit a975f2e

Browse files
committed
Update pb.MaxAvailableComponentSetsRequest to hold namespace under root
Signed-off-by: RainbowMango <[email protected]>
1 parent 9da6343 commit a975f2e

File tree

12 files changed

+646
-186
lines changed

12 files changed

+646
-186
lines changed

pkg/estimator/client/accurate.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,7 @@ func (se *SchedulerEstimator) GetUnschedulableReplicas(
8989
})
9090
}
9191

92-
func (se *SchedulerEstimator) maxAvailableComponentSets(
93-
ctx context.Context,
94-
cluster string,
95-
namespace string,
96-
components []workv1alpha2.Component,
97-
) (int32, error) {
92+
func (se *SchedulerEstimator) maxAvailableComponentSets(ctx context.Context, cluster string, namespace string, components []workv1alpha2.Component) (int32, error) {
9893
client, err := se.cache.GetClient(cluster)
9994
if err != nil {
10095
return 0, err
@@ -103,6 +98,7 @@ func (se *SchedulerEstimator) maxAvailableComponentSets(
10398
pbReq := &pb.MaxAvailableComponentSetsRequest{
10499
Cluster: cluster,
105100
Components: make([]pb.Component, 0, len(components)),
101+
Namespace: namespace,
106102
}
107103

108104
for _, comp := range components {
@@ -115,7 +111,7 @@ func (se *SchedulerEstimator) maxAvailableComponentSets(
115111
pbReq.Components = append(pbReq.Components, pb.Component{
116112
Name: comp.Name,
117113
Replicas: comp.Replicas,
118-
ReplicaRequirements: toPBReplicaRequirements(cr, namespace),
114+
ReplicaRequirements: toPBReplicaRequirements(cr),
119115
})
120116
}
121117

@@ -126,10 +122,9 @@ func (se *SchedulerEstimator) maxAvailableComponentSets(
126122
return res.MaxSets, nil
127123
}
128124

129-
// toPBReplicaRequirements converts the API ComponentReplicaRequirements to the pb.ReplicaRequirements value.
130-
func toPBReplicaRequirements(cr *workv1alpha2.ComponentReplicaRequirements, namespace string) pb.ReplicaRequirements {
131-
var out pb.ReplicaRequirements
132-
out.Namespace = namespace
125+
// toPBReplicaRequirements converts the API ComponentReplicaRequirements to the pb.ComponentReplicaRequirements value.
126+
func toPBReplicaRequirements(cr *workv1alpha2.ComponentReplicaRequirements) pb.ComponentReplicaRequirements {
127+
var out pb.ComponentReplicaRequirements
133128
if cr == nil {
134129
return out
135130
}

pkg/estimator/pb/generated.pb.go

Lines changed: 506 additions & 71 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/estimator/pb/generated.proto

Lines changed: 25 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/estimator/pb/types.go

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,8 @@ type ReplicaRequirements struct {
6060
// Namespace represents the namespaces belonged to a ResourceRequest
6161
// +optional
6262
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`
63-
// PriorityClassName represents the priority class name for a given ResourceRequest
64-
// Resource quotas are introduced for multi tenants sharing a cluster
65-
// Besides estimate the replica based on nodes' resources, we need to consider the resource quota of a ResourceRequest
66-
// ResourceQuota have an associated set of scopes, one of them is priority class
63+
// PriorityClassName represents the priority class name for a given ResourceRequest.
64+
// It is used by the resource quota estimator to check quota constraints, as ResourceQuota supports priority class as a scope.
6765
// +optional
6866
PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,4,opt,name=priorityClassName"`
6967
}
@@ -124,10 +122,17 @@ type MaxAvailableComponentSetsRequest struct {
124122
// Cluster is the target cluster where the scheduling estimation is performed.
125123
// +required
126124
Cluster string `json:"cluster" protobuf:"bytes,1,opt,name=cluster"`
125+
127126
// Components lists the component types that form one full workload set,
128127
// along with their resource and replica requirements.
129128
// +required
130129
Components []Component `json:"components" protobuf:"bytes,2,rep,name=components"`
130+
131+
// Namespace is the namespace of the workload being estimated.
132+
// It is used by the accurate estimator to check the quota configurations
133+
// in the target member cluster.
134+
// +required
135+
Namespace string `json:"namespace" protobuf:"bytes,3,opt,name=namespace"`
131136
}
132137

133138
// Component defines the scheduling and resource requirements for a single
@@ -136,15 +141,33 @@ type Component struct {
136141
// Name is the identifier of the component within the workload set.
137142
// +required
138143
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
144+
139145
// ReplicaRequirements specifies the per-replica resource requirements
140146
// (CPU, memory, etc.) and scheduling constraints.
141147
// +required
142-
ReplicaRequirements ReplicaRequirements `json:"replicaRequirements" protobuf:"bytes,2,opt,name=replicaRequirements"`
148+
ReplicaRequirements ComponentReplicaRequirements `json:"replicaRequirements" protobuf:"bytes,2,opt,name=replicaRequirements"`
149+
143150
// Replicas is the number of replicas of this component required in a single workload set.
144151
// +required
145152
Replicas int32 `json:"replicas" protobuf:"varint,3,opt,name=replicas"`
146153
}
147154

155+
// ComponentReplicaRequirements represents the resource and scheduling requirements for each replica.
156+
type ComponentReplicaRequirements struct {
157+
// NodeClaim represents the NodeAffinity, NodeSelector and Tolerations required by each replica.
158+
// +optional
159+
NodeClaim *NodeClaim `json:"nodeClaim,omitempty" protobuf:"bytes,1,opt,name=nodeClaim"`
160+
161+
// ResourceRequest represents the resources required by each replica.
162+
// +optional
163+
ResourceRequest corev1.ResourceList `json:"resourceRequest,omitempty" protobuf:"bytes,2,rep,name=resourceRequest,casttype=k8s.io/api/core/v1.ResourceList,castkey=k8s.io/api/core/v1.ResourceName"`
164+
165+
// PriorityClassName represents the priority class name for a given ResourceRequest.
166+
// It is used by the resource quota estimator to check quota constraints, as ResourceQuota supports priority class as a scope.
167+
// +optional
168+
PriorityClassName string `json:"priorityClassName,omitempty" protobuf:"bytes,3,opt,name=priorityClassName"`
169+
}
170+
148171
// MaxAvailableComponentSetsResponse is the gRPC response message containing the
149172
// maximum number of complete component sets that can be scheduled.
150173
type MaxAvailableComponentSetsResponse struct {

pkg/estimator/server/estimate.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (es *AccurateSchedulerEstimatorServer) EstimateComponents(ctx context.Conte
8181
return 0, nil
8282
}
8383

84-
maxAvailableComponentSets, err := es.estimateComponents(ctx, snapShot, request.Components)
84+
maxAvailableComponentSets, err := es.estimateComponents(ctx, snapShot, request.Components, request.Namespace)
8585
if err != nil {
8686
return 0, err
8787
}
@@ -90,12 +90,8 @@ func (es *AccurateSchedulerEstimatorServer) EstimateComponents(ctx context.Conte
9090
return maxAvailableComponentSets, nil
9191
}
9292

93-
func (es *AccurateSchedulerEstimatorServer) estimateComponents(
94-
ctx context.Context,
95-
snapshot *schedcache.Snapshot,
96-
components []pb.Component,
97-
) (int32, error) {
98-
maxSets, ret := es.estimateFramework.RunEstimateComponentsPlugins(ctx, snapshot, components)
93+
func (es *AccurateSchedulerEstimatorServer) estimateComponents(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component, namespace string) (int32, error) {
94+
maxSets, ret := es.estimateFramework.RunEstimateComponentsPlugins(ctx, snapshot, components, namespace)
9995

10096
// No replicas can be scheduled on the cluster, skip further checks and return 0
10197
if ret.IsUnschedulable() {

pkg/estimator/server/framework/interface.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type Framework interface {
4444
// The integer represents the minimum calculated value of estimated component sets from each EstimateComponentsPlugin.
4545
// The Result contains code, reasons and error.
4646
// It is merged from all plugins' returned result codes.
47-
RunEstimateComponentsPlugins(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *Result)
47+
RunEstimateComponentsPlugins(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component, namespace string) (int32, *Result)
4848
// TODO(wengyao04): we can add filter and score plugin extension points if needed in the future
4949
}
5050

@@ -75,7 +75,7 @@ type EstimateComponentsPlugin interface {
7575
// The integer represents the estimated number of complete component sets that can be scheduled.
7676
// The Result contains code, reasons and error.
7777
// It is merged from all plugins' returned result codes.
78-
EstimateComponents(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *Result)
78+
EstimateComponents(ctx context.Context, snapshot *schedcache.Snapshot, components []pb.Component, namespace string) (int32, *Result)
7979
}
8080

8181
// Handle provides data and some tools that plugins can use. It is
@@ -108,7 +108,7 @@ const (
108108
// Unschedulable is used when a plugin finds the resource unschedulable.
109109
// The accompanying status message should explain why it is unschedulable.
110110
Unschedulable
111-
// Nooperation is used when a plugin is disabled or the plugin list is empty.
111+
// Noopperation is used when a plugin is disabled or the plugin list is empty.
112112
Noopperation
113113
// Error is used for internal plugin errors, unexpected input, etc.
114114
Error

pkg/estimator/server/framework/plugins/noderesource/noderesource.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func (pl *nodeResourceEstimator) nodeMaxAvailableReplica(node *schedulerframewor
112112

113113
// EstimateComponents estimates the maximum number of complete component sets that can be scheduled.
114114
// It returns the number of sets that can fit on the available node resources.
115-
func (pl *nodeResourceEstimator) EstimateComponents(_ context.Context, snapshot *schedcache.Snapshot, components []pb.Component) (int32, *framework.Result) {
115+
func (pl *nodeResourceEstimator) EstimateComponents(_ context.Context, snapshot *schedcache.Snapshot, components []pb.Component, _ string) (int32, *framework.Result) {
116116
if !pl.enabled {
117117
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
118118
return noNodeConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s is disabled", pl.Name()))

pkg/estimator/server/framework/plugins/noderesource/noderesource_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
5252
},
5353
components: []pb.Component{
5454
{
55-
ReplicaRequirements: pb.ReplicaRequirements{
55+
ReplicaRequirements: pb.ComponentReplicaRequirements{
5656
ResourceRequest: corev1.ResourceList{
5757
corev1.ResourceCPU: resource.MustParse("1"),
5858
corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -76,7 +76,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
7676
},
7777
components: []pb.Component{
7878
{
79-
ReplicaRequirements: pb.ReplicaRequirements{
79+
ReplicaRequirements: pb.ComponentReplicaRequirements{
8080
ResourceRequest: corev1.ResourceList{
8181
corev1.ResourceCPU: resource.MustParse("1"),
8282
corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -100,7 +100,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
100100
},
101101
components: []pb.Component{
102102
{
103-
ReplicaRequirements: pb.ReplicaRequirements{
103+
ReplicaRequirements: pb.ComponentReplicaRequirements{
104104
ResourceRequest: corev1.ResourceList{
105105
corev1.ResourceCPU: resource.MustParse("1"),
106106
corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -124,7 +124,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
124124
},
125125
components: []pb.Component{
126126
{
127-
ReplicaRequirements: pb.ReplicaRequirements{
127+
ReplicaRequirements: pb.ComponentReplicaRequirements{
128128
ResourceRequest: corev1.ResourceList{
129129
corev1.ResourceCPU: resource.MustParse("2"),
130130
corev1.ResourceMemory: resource.MustParse("2Gi"),
@@ -133,7 +133,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
133133
Replicas: 1,
134134
},
135135
{
136-
ReplicaRequirements: pb.ReplicaRequirements{
136+
ReplicaRequirements: pb.ComponentReplicaRequirements{
137137
ResourceRequest: corev1.ResourceList{
138138
corev1.ResourceCPU: resource.MustParse("3"),
139139
corev1.ResourceMemory: resource.MustParse("3Gi"),
@@ -162,7 +162,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
162162
},
163163
components: []pb.Component{
164164
{
165-
ReplicaRequirements: pb.ReplicaRequirements{
165+
ReplicaRequirements: pb.ComponentReplicaRequirements{
166166
ResourceRequest: corev1.ResourceList{
167167
corev1.ResourceCPU: resource.MustParse("3"),
168168
corev1.ResourceMemory: resource.MustParse("3Gi"),
@@ -171,7 +171,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
171171
Replicas: 2,
172172
},
173173
{
174-
ReplicaRequirements: pb.ReplicaRequirements{
174+
ReplicaRequirements: pb.ComponentReplicaRequirements{
175175
ResourceRequest: corev1.ResourceList{
176176
corev1.ResourceCPU: resource.MustParse("2"),
177177
corev1.ResourceMemory: resource.MustParse("2Gi"),
@@ -195,7 +195,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
195195
},
196196
components: []pb.Component{
197197
{
198-
ReplicaRequirements: pb.ReplicaRequirements{
198+
ReplicaRequirements: pb.ComponentReplicaRequirements{
199199
ResourceRequest: corev1.ResourceList{
200200
corev1.ResourceCPU: resource.MustParse("3"),
201201
corev1.ResourceMemory: resource.MustParse("3Gi"),
@@ -225,7 +225,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
225225
},
226226
components: []pb.Component{
227227
{
228-
ReplicaRequirements: pb.ReplicaRequirements{
228+
ReplicaRequirements: pb.ComponentReplicaRequirements{
229229
ResourceRequest: corev1.ResourceList{
230230
corev1.ResourceCPU: resource.MustParse("1"),
231231
corev1.ResourceMemory: resource.MustParse("2Gi"),
@@ -254,7 +254,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
254254
},
255255
components: []pb.Component{
256256
{
257-
ReplicaRequirements: pb.ReplicaRequirements{
257+
ReplicaRequirements: pb.ComponentReplicaRequirements{
258258
ResourceRequest: corev1.ResourceList{
259259
corev1.ResourceCPU: resource.MustParse("1"),
260260
corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -298,7 +298,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
298298
},
299299
components: []pb.Component{
300300
{
301-
ReplicaRequirements: pb.ReplicaRequirements{
301+
ReplicaRequirements: pb.ComponentReplicaRequirements{
302302
ResourceRequest: corev1.ResourceList{
303303
corev1.ResourceCPU: resource.MustParse("1"),
304304
corev1.ResourceMemory: resource.MustParse("1Gi"),
@@ -352,7 +352,7 @@ func TestNodeResourceEstimator_EstimateComponents(t *testing.T) {
352352
}
353353

354354
// Execute test
355-
result, status := pl.EstimateComponents(context.Background(), snapshot, tt.components)
355+
result, status := pl.EstimateComponents(context.Background(), snapshot, tt.components, "")
356356

357357
// Verify results
358358
if result != tt.expected {

pkg/estimator/server/framework/plugins/resourcequota/resourcequota.go

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ func (pl *resourceQuotaEstimator) Name() string {
9393
}
9494

9595
// Estimate estimates the replicas allowed by the ResourceQuota constraints.
96-
func (pl *resourceQuotaEstimator) Estimate(_ context.Context,
97-
_ *schedcache.Snapshot,
98-
replicaRequirements *pb.ReplicaRequirements) (int32, *framework.Result) {
96+
func (pl *resourceQuotaEstimator) Estimate(_ context.Context, _ *schedcache.Snapshot, replicaRequirements *pb.ReplicaRequirements) (int32, *framework.Result) {
9997
var replica int32 = noQuotaConstraint
10098
if !pl.enabled {
10199
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
@@ -136,20 +134,21 @@ func (pl *resourceQuotaEstimator) Estimate(_ context.Context,
136134
// selectors (e.g., priorityClassName), aggregates their resource requirements, and calculates how
137135
// many complete component sets can fit within the quota. The function returns the minimum allowed
138136
// sets across all ResourceQuotas to ensure all quota constraints are satisfied.
139-
func (pl *resourceQuotaEstimator) EstimateComponents(_ context.Context,
140-
_ *schedcache.Snapshot,
141-
components []pb.Component) (int32, *framework.Result) {
137+
func (pl *resourceQuotaEstimator) EstimateComponents(_ context.Context, _ *schedcache.Snapshot, components []pb.Component, namespace string) (int32, *framework.Result) {
142138
if !pl.enabled {
143139
klog.V(5).Info("Estimator Plugin", "name", Name, "enabled", pl.enabled)
144140
return noQuotaConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s is disabled", pl.Name()))
145141
}
146142

147143
if len(components) == 0 {
148-
klog.V(5).Infof("%s: received empty components list", pl.Name())
149-
return noQuotaConstraint, framework.NewResult(framework.Noopperation, fmt.Sprintf("%s received empty components list", pl.Name()))
144+
klog.V(5).Infof("%s: components list is empty, skipping resource quota check", pl.Name())
145+
return noQuotaConstraint, framework.NewResult(framework.Success, fmt.Sprintf("%s received empty components list", pl.Name()))
150146
}
151147

152-
namespace := components[0].ReplicaRequirements.Namespace
148+
if namespace == "" {
149+
klog.V(5).Infof("%s: namespace is empty, skipping resource quota check", pl.Name())
150+
return noQuotaConstraint, framework.NewResult(framework.Success)
151+
}
153152

154153
rqList, err := pl.rqLister.ResourceQuotas(namespace).List(labels.Everything())
155154
if err != nil {

0 commit comments

Comments
 (0)