Skip to content

Commit 2cea078

Browse files
committed
Extend the Resource Interpreter interface for multi-components workload scheduling.
Signed-off-by: RainbowMango <[email protected]>
1 parent 980ee22 commit 2cea078

File tree

9 files changed

+212
-2
lines changed

9 files changed

+212
-2
lines changed

api/openapi-spec/swagger.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18469,10 +18469,28 @@
1846918469
}
1847018470
}
1847118471
},
18472+
"com.github.karmada-io.karmada.pkg.apis.config.v1alpha1.ComponentResourceRequirement": {
18473+
"description": "ComponentResourceRequirement holds the scripts for extracting the desired replica count and resource requirements for each component within a resource. This is particularly useful for resources that define multiple components (such as CRDs with multiple pod templates), but can also be used for single-component resources.",
18474+
"type": "object",
18475+
"required": [
18476+
"luaScript"
18477+
],
18478+
"properties": {
18479+
"luaScript": {
18480+
"description": "LuaScript holds the Lua script that is used to extract the desired replica count and resource requirements for each component of the resource.\n\nThe script should implement a function as follows:\n\n```\n luaScript: \u003e\n function GetComponents(desiredObj)\n local components = {}\n\n local jobManagerComponent = {\n name = \"jobmanager\"\n replicas = desiredObj.spec.jobManager.replicas\n }\n table.insert(components, jobManagerComponent)\n\n local taskManagerComponent = {\n name = \"taskmanager\"\n replicas = desiredObj.spec.taskManager.replicas\n }\n table.insert(components, taskManagerComponent)\n\n return components\n end\n```\n\nThe content of the LuaScript needs to be a whole function including both declaration and implementation.\n\nThe parameters will be supplied by the system:\n - desiredObj: the object represents the configuration to be applied\n to the member cluster.\n\nThe function expects one return value:\n - components: the resource requirements for each component.\nThe returned value will be set into a ResourceBinding or ClusterResourceBinding.",
18481+
"type": "string",
18482+
"default": ""
18483+
}
18484+
}
18485+
},
1847218486
"com.github.karmada-io.karmada.pkg.apis.config.v1alpha1.CustomizationRules": {
1847318487
"description": "CustomizationRules describes the interpretation rules.",
1847418488
"type": "object",
1847518489
"properties": {
18490+
"componentResource": {
18491+
"description": "ComponentResource describes the rules for Karmada to discover the resource requirements for multiple components from the given object. This is designed for CRDs with multiple components (e.g., FlinkDeployment), but can also be used for single-component resources like Deployment. If implemented, the controller will use this to obtain per-component replica and resource requirements, and will not call ReplicaResource. If not implemented, the controller will fall back to ReplicaResource for backward compatibility. This will only be used when the feature gate 'MultiplePodTemplatesScheduling' is enabled.",
18492+
"$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.config.v1alpha1.ComponentResourceRequirement"
18493+
},
1847618494
"dependencyInterpretation": {
1847718495
"description": "DependencyInterpretation describes the rules for Karmada to analyze the dependent resources. Karmada provides built-in rules for several standard Kubernetes types, see: https://karmada.io/docs/userguide/globalview/customizing-resource-interpreter/#interpretdependency If DependencyInterpretation is set, the built-in rules will be ignored.",
1847818496
"$ref": "#/definitions/com.github.karmada-io.karmada.pkg.apis.config.v1alpha1.DependencyInterpretation"

charts/karmada/_crds/bases/config/config.karmada.io_resourceinterpretercustomizations.yaml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,59 @@ spec:
6060
customizations:
6161
description: Customizations describe the interpretation rules.
6262
properties:
63+
componentResource:
64+
description: |-
65+
ComponentResource describes the rules for Karmada to discover the resource requirements
66+
for multiple components from the given object.
67+
This is designed for CRDs with multiple components (e.g., FlinkDeployment), but
68+
can also be used for single-component resources like Deployment.
69+
If implemented, the controller will use this to obtain per-component replica and resource
70+
requirements, and will not call ReplicaResource.
71+
If not implemented, the controller will fall back to ReplicaResource for backward compatibility.
72+
This will only be used when the feature gate 'MultiplePodTemplatesScheduling' is enabled.
73+
properties:
74+
luaScript:
75+
description: |-
76+
LuaScript holds the Lua script that is used to extract the desired replica count and resource
77+
requirements for each component of the resource.
78+
79+
The script should implement a function as follows:
80+
81+
```
82+
luaScript: >
83+
function GetComponents(desiredObj)
84+
local components = {}
85+
86+
local jobManagerComponent = {
87+
name = "jobmanager"
88+
replicas = desiredObj.spec.jobManager.replicas
89+
}
90+
table.insert(components, jobManagerComponent)
91+
92+
local taskManagerComponent = {
93+
name = "taskmanager"
94+
replicas = desiredObj.spec.taskManager.replicas
95+
}
96+
table.insert(components, taskManagerComponent)
97+
98+
return components
99+
end
100+
```
101+
102+
The content of the LuaScript needs to be a whole function including both
103+
declaration and implementation.
104+
105+
The parameters will be supplied by the system:
106+
- desiredObj: the object represents the configuration to be applied
107+
to the member cluster.
108+
109+
The function expects one return value:
110+
- components: the resource requirements for each component.
111+
The returned value will be set into a ResourceBinding or ClusterResourceBinding.
112+
type: string
113+
required:
114+
- luaScript
115+
type: object
63116
dependencyInterpretation:
64117
description: |-
65118
DependencyInterpretation describes the rules for Karmada to analyze the

pkg/apis/config/v1alpha1/resourceinterpretercustomization_types.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,17 @@ type CustomizationRules struct {
9797
// +optional
9898
ReplicaResource *ReplicaResourceRequirement `json:"replicaResource,omitempty"`
9999

100+
// ComponentResource describes the rules for Karmada to discover the resource requirements
101+
// for multiple components from the given object.
102+
// This is designed for CRDs with multiple components (e.g., FlinkDeployment), but
103+
// can also be used for single-component resources like Deployment.
104+
// If implemented, the controller will use this to obtain per-component replica and resource
105+
// requirements, and will not call ReplicaResource.
106+
// If not implemented, the controller will fall back to ReplicaResource for backward compatibility.
107+
// This will only be used when the feature gate 'MultiplePodTemplatesScheduling' is enabled.
108+
// +optional
109+
ComponentResource *ComponentResourceRequirement `json:"componentResource,omitempty"`
110+
100111
// ReplicaRevision describes the rules for Karmada to revise the resource's replica.
101112
// It would be useful for those CRD resources that declare workload types like
102113
// Deployment.
@@ -203,6 +214,51 @@ type ReplicaResourceRequirement struct {
203214
LuaScript string `json:"luaScript"`
204215
}
205216

217+
// ComponentResourceRequirement holds the scripts for extracting the desired replica count
218+
// and resource requirements for each component within a resource. This is particularly useful for
219+
// resources that define multiple components (such as CRDs with multiple pod templates), but can also
220+
// be used for single-component resources.
221+
type ComponentResourceRequirement struct {
222+
// LuaScript holds the Lua script that is used to extract the desired replica count and resource
223+
// requirements for each component of the resource.
224+
//
225+
// The script should implement a function as follows:
226+
//
227+
// ```
228+
// luaScript: >
229+
// function GetComponents(desiredObj)
230+
// local components = {}
231+
//
232+
// local jobManagerComponent = {
233+
// name = "jobmanager"
234+
// replicas = desiredObj.spec.jobManager.replicas
235+
// }
236+
// table.insert(components, jobManagerComponent)
237+
//
238+
// local taskManagerComponent = {
239+
// name = "taskmanager"
240+
// replicas = desiredObj.spec.taskManager.replicas
241+
// }
242+
// table.insert(components, taskManagerComponent)
243+
//
244+
// return components
245+
// end
246+
// ```
247+
//
248+
// The content of the LuaScript needs to be a whole function including both
249+
// declaration and implementation.
250+
//
251+
// The parameters will be supplied by the system:
252+
// - desiredObj: the object represents the configuration to be applied
253+
// to the member cluster.
254+
//
255+
// The function expects one return value:
256+
// - components: the resource requirements for each component.
257+
// The returned value will be set into a ResourceBinding or ClusterResourceBinding.
258+
// +required
259+
LuaScript string `json:"luaScript"`
260+
}
261+
206262
// ReplicaRevision holds the scripts for revising the desired replicas.
207263
type ReplicaRevision struct {
208264
// LuaScript holds the Lua script that is used to revise replicas in the desired specification.

pkg/apis/config/v1alpha1/zz_generated.deepcopy.go

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

pkg/detector/detector_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,10 @@ func (m *mockRESTMapper) ResourceSingularizer(resource string) (string, error) {
10441044
// mockResourceInterpreter is a mock implementation of the ResourceInterpreter interface
10451045
type mockResourceInterpreter struct{}
10461046

1047+
func (m *mockResourceInterpreter) GetComponents(_ *unstructured.Unstructured) ([]workv1alpha2.ComponentRequirements, error) {
1048+
return nil, nil
1049+
}
1050+
10471051
func (m *mockResourceInterpreter) Start(_ context.Context) error {
10481052
return nil
10491053
}

pkg/features/features.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ const (
105105
ContextualLogging = logsv1.ContextualLogging
106106

107107
// MultiplePodTemplatesScheduling enables enhanced, resource-aware scheduling for workloads with multiple pod templates.
108-
// When enabled, the scheduler and resource interpreter will use the new 'GetComponentReplicas' hook and 'components' field
108+
// When enabled, the scheduler and resource interpreter will use the new 'GetComponents' hook and 'components' field
109109
// to support accurate resource estimation and scheduling for complex CRDs (e.g., FlinkDeployments, RayJob, VolcanoJob) that consist of
110110
// multiple components with different resource requirements. This allows for more precise FederatedResourceQuota
111111
// calculations and better placement decisions.

pkg/generated/openapi/zz_generated.openapi.go

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/resourceinterpreter/default/native/default.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package native
1818

1919
import (
20+
"errors"
2021
"fmt"
2122

2223
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -110,6 +111,11 @@ func (e *DefaultInterpreter) ReviseReplica(object *unstructured.Unstructured, re
110111
return handler(object, replica)
111112
}
112113

114+
// GetComponents returns the resource requirements for multiple components from the given object.
115+
func (e *DefaultInterpreter) GetComponents(_ *unstructured.Unstructured) ([]workv1alpha2.ComponentRequirements, error) {
116+
return nil, errors.New("no plan to implement this method yet")
117+
}
118+
113119
// Retain returns the objects that based on the "desired" object but with values retained from the "observed" object.
114120
func (e *DefaultInterpreter) Retain(desired *unstructured.Unstructured, observed *unstructured.Unstructured) (retained *unstructured.Unstructured, err error) {
115121
klog.V(4).Infof("Retain object: %v %s/%s with build-in interpreter.", desired.GroupVersionKind(), desired.GetNamespace(), desired.GetName())

0 commit comments

Comments
 (0)