mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-06-08 16:30:57 -04:00
Merge pull request #135048 from yliaog/beta_promo
DRA Extended Resource: promote to Beta in 1.36
This commit is contained in:
commit
f5bafe93ac
27 changed files with 180 additions and 76 deletions
6
api/openapi-spec/swagger.json
generated
6
api/openapi-spec/swagger.json
generated
|
|
@ -16024,7 +16024,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
@ -17371,7 +17371,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
@ -18544,7 +18544,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
|
|||
|
|
@ -730,7 +730,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
|
|||
|
|
@ -716,7 +716,7 @@
|
|||
"x-kubernetes-list-type": "atomic"
|
||||
},
|
||||
"extendedResourceName": {
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"description": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
"type": "string"
|
||||
},
|
||||
"selectors": {
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
|
|||
|
||||
DRAExtendedResource: {
|
||||
{Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Alpha},
|
||||
{Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.Beta},
|
||||
},
|
||||
|
||||
DRAPartitionableDevices: {
|
||||
|
|
|
|||
6
pkg/generated/openapi/zz_generated.openapi.go
generated
6
pkg/generated/openapi/zz_generated.openapi.go
generated
|
|
@ -47636,7 +47636,7 @@ func schema_k8sio_api_resource_v1_DeviceClassSpec(ref common.ReferenceCallback)
|
|||
},
|
||||
"extendedResourceName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
|
@ -50144,7 +50144,7 @@ func schema_k8sio_api_resource_v1beta1_DeviceClassSpec(ref common.ReferenceCallb
|
|||
},
|
||||
"extendedResourceName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
|
@ -52316,7 +52316,7 @@ func schema_k8sio_api_resource_v1beta2_DeviceClassSpec(ref common.ReferenceCallb
|
|||
},
|
||||
"extendedResourceName": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
Description: "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -123,9 +123,18 @@ func (pl *BalancedAllocation) SignPod(ctx context.Context, pod *v1.Pod) ([]fwk.S
|
|||
EnablePodLevelResources: pl.enablePodLevelResources,
|
||||
EnableDRAExtendedResource: pl.enableDRAExtendedResource,
|
||||
}
|
||||
|
||||
if pl.enableDRAExtendedResource {
|
||||
return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources enabled")
|
||||
podRequest := computePodResourceRequest(pod, opts)
|
||||
for rName, rQuant := range podRequest.ScalarResources {
|
||||
// Skip in case request quantity is zero
|
||||
if rQuant == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if shouldDelegateResourceToDRA(rName, nil, pl.draManager, opts) {
|
||||
return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources are used in the cluster")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []fwk.SignFragment{
|
||||
|
|
@ -187,6 +196,7 @@ func NewBalancedAllocation(_ context.Context, baArgs runtime.Object, h fwk.Handl
|
|||
useRequested: true,
|
||||
resources: args.Resources,
|
||||
enableInPlacePodLevelResourcesVerticalScaling: fts.EnableInPlacePodLevelResourcesVerticalScaling,
|
||||
draManager: h.SharedDRAManager(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
"k8s.io/kubernetes/pkg/scheduler/backend/cache"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/dynamicresources"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/feature"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/runtime"
|
||||
st "k8s.io/kubernetes/pkg/scheduler/testing"
|
||||
|
|
@ -359,16 +360,19 @@ func testNodeResourcesBalancedAllocation(tCtx ktesting.TContext) {
|
|||
}
|
||||
|
||||
func TestBalancedAllocationSignPod(t *testing.T) {
|
||||
testBalancedAllocationSignPod(ktesting.Init(t))
|
||||
}
|
||||
func testBalancedAllocationSignPod(tCtx ktesting.TContext) {
|
||||
tests := map[string]struct {
|
||||
name string
|
||||
pod *v1.Pod
|
||||
enableDRAExtendedResource bool
|
||||
expectedFragments []fwk.SignFragment
|
||||
expectedStatusCode fwk.Code
|
||||
name string
|
||||
pod *v1.Pod
|
||||
disableDRAExtendedResource bool
|
||||
expectedFragments []fwk.SignFragment
|
||||
expectedStatusCode fwk.Code
|
||||
}{
|
||||
"pod with CPU and memory requests": {
|
||||
pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(),
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(
|
||||
st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(), ResourceRequestsOptions{})},
|
||||
|
|
@ -376,8 +380,8 @@ func TestBalancedAllocationSignPod(t *testing.T) {
|
|||
expectedStatusCode: fwk.Success,
|
||||
},
|
||||
"best-effort pod with no requests": {
|
||||
pod: st.MakePod().Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
pod: st.MakePod().Obj(),
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Obj(), ResourceRequestsOptions{})},
|
||||
},
|
||||
|
|
@ -387,7 +391,7 @@ func TestBalancedAllocationSignPod(t *testing.T) {
|
|||
pod: st.MakePod().
|
||||
Container("container1").Req(cpuAndMemory("500m", "1000")).
|
||||
Container("container2").Req(cpuAndMemory("1500m", "3000")).Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().
|
||||
Container("container1").Req(cpuAndMemory("500m", "1000")).
|
||||
|
|
@ -396,34 +400,68 @@ func TestBalancedAllocationSignPod(t *testing.T) {
|
|||
expectedStatusCode: fwk.Success,
|
||||
},
|
||||
"DRA extended resource enabled - returns unschedulable": {
|
||||
pod: st.MakePod().Req(cpuAndMemory("1000m", "2000")).Obj(),
|
||||
enableDRAExtendedResource: true,
|
||||
expectedFragments: nil,
|
||||
expectedStatusCode: fwk.Unschedulable,
|
||||
pod: st.MakePod().Req(
|
||||
map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(),
|
||||
disableDRAExtendedResource: false,
|
||||
expectedFragments: nil,
|
||||
expectedStatusCode: fwk.Unschedulable,
|
||||
},
|
||||
"DRA extended resource disabled": {
|
||||
pod: st.MakePod().Req(
|
||||
map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(),
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().
|
||||
Container("container1").Req(
|
||||
map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(), ResourceRequestsOptions{})},
|
||||
},
|
||||
expectedStatusCode: fwk.Success,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
tCtx.SyncTest(name, func(tCtx ktesting.TContext) {
|
||||
runOpts := []runtime.Option{}
|
||||
var testDRAManager *dynamicresources.DefaultDRAManager
|
||||
if !test.disableDRAExtendedResource {
|
||||
testDRAManager = newTestDRAManager(tCtx, deviceClassWithExtendResourceName)
|
||||
runOpts = append(runOpts, runtime.WithSharedDRAManager(testDRAManager))
|
||||
}
|
||||
fh, _ := runtime.NewFramework(tCtx, nil, nil, runOpts...)
|
||||
defer func() {
|
||||
tCtx.Cancel("test has completed")
|
||||
runtime.WaitForShutdown(fh)
|
||||
}()
|
||||
|
||||
p, err := NewBalancedAllocation(ctx, &config.NodeResourcesBalancedAllocationArgs{}, nil, feature.Features{
|
||||
EnableDRAExtendedResource: test.enableDRAExtendedResource,
|
||||
p, err := NewBalancedAllocation(tCtx, &config.NodeResourcesBalancedAllocationArgs{}, fh, feature.Features{
|
||||
EnableDRAExtendedResource: !test.disableDRAExtendedResource,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create plugin: %v", err)
|
||||
tCtx.Fatalf("failed to create plugin: %v", err)
|
||||
}
|
||||
|
||||
ba := p.(*BalancedAllocation)
|
||||
fragments, status := ba.SignPod(ctx, test.pod)
|
||||
fragments, status := ba.SignPod(tCtx, test.pod)
|
||||
|
||||
if status.Code() != test.expectedStatusCode {
|
||||
t.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message())
|
||||
tCtx.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message())
|
||||
}
|
||||
|
||||
if test.expectedStatusCode == fwk.Success {
|
||||
if diff := cmp.Diff(test.expectedFragments, fragments); diff != "" {
|
||||
t.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff)
|
||||
tCtx.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -177,8 +177,18 @@ func (pl *Fit) SignPod(ctx context.Context, pod *v1.Pod) ([]fwk.SignFragment, *f
|
|||
EnableDRAExtendedResource: pl.enableDRAExtendedResource,
|
||||
}
|
||||
if pl.enableDRAExtendedResource {
|
||||
return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources enabled")
|
||||
podRequest := computePodResourceRequest(pod, opts)
|
||||
for rName, rQuant := range podRequest.ScalarResources {
|
||||
// Skip in case request quantity is zero
|
||||
if rQuant == 0 {
|
||||
continue
|
||||
}
|
||||
if shouldDelegateResourceToDRA(rName, nil, pl.draManager, opts) {
|
||||
return nil, fwk.NewStatus(fwk.Unschedulable, "signature disabled when dra extended resources are used in the cluster")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(pod, opts)},
|
||||
}, nil
|
||||
|
|
@ -243,8 +253,10 @@ func shouldDelegateResourceToDRA(rName v1.ResourceName, nodeInfo fwk.NodeInfo, d
|
|||
return false
|
||||
}
|
||||
|
||||
if allocatable := nodeInfo.GetAllocatable().GetScalarResources()[rName]; allocatable > 0 {
|
||||
return false
|
||||
if nodeInfo != nil {
|
||||
if allocatable := nodeInfo.GetAllocatable().GetScalarResources()[rName]; allocatable > 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if draManager == nil {
|
||||
|
|
|
|||
|
|
@ -2173,19 +2173,22 @@ func testHaveAnyRequestedResourcesIncreased(tCtx ktesting.TContext) {
|
|||
}
|
||||
|
||||
func TestFitSignPod(t *testing.T) {
|
||||
testFitSignPod(ktesting.Init(t))
|
||||
}
|
||||
func testFitSignPod(tCtx ktesting.TContext) {
|
||||
tests := map[string]struct {
|
||||
name string
|
||||
pod *v1.Pod
|
||||
enableDRAExtendedResource bool
|
||||
expectedFragments []fwk.SignFragment
|
||||
expectedStatusCode fwk.Code
|
||||
name string
|
||||
pod *v1.Pod
|
||||
disableDRAExtendedResource bool
|
||||
expectedFragments []fwk.SignFragment
|
||||
expectedStatusCode fwk.Code
|
||||
}{
|
||||
"pod with CPU and memory requests": {
|
||||
pod: st.MakePod().Req(map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
}).Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Req(map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
|
|
@ -2195,8 +2198,8 @@ func TestFitSignPod(t *testing.T) {
|
|||
expectedStatusCode: fwk.Success,
|
||||
},
|
||||
"best-effort pod with no requests": {
|
||||
pod: st.MakePod().Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
pod: st.MakePod().Obj(),
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Obj(), ResourceRequestsOptions{})},
|
||||
},
|
||||
|
|
@ -2210,7 +2213,7 @@ func TestFitSignPod(t *testing.T) {
|
|||
v1.ResourceCPU: "1500m",
|
||||
v1.ResourceMemory: "3000",
|
||||
}).Obj(),
|
||||
enableDRAExtendedResource: false,
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().Container("container1").Req(map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "500m",
|
||||
|
|
@ -2224,37 +2227,66 @@ func TestFitSignPod(t *testing.T) {
|
|||
},
|
||||
"DRA extended resource enabled - returns unschedulable": {
|
||||
pod: st.MakePod().Req(map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(),
|
||||
enableDRAExtendedResource: true,
|
||||
expectedFragments: nil,
|
||||
expectedStatusCode: fwk.Unschedulable,
|
||||
disableDRAExtendedResource: false,
|
||||
expectedFragments: nil,
|
||||
expectedStatusCode: fwk.Unschedulable,
|
||||
},
|
||||
"DRA extended resource disabled": {
|
||||
pod: st.MakePod().Req(
|
||||
map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(),
|
||||
disableDRAExtendedResource: true,
|
||||
expectedFragments: []fwk.SignFragment{
|
||||
{Key: fwk.ResourcesSignerName, Value: computePodResourceRequest(st.MakePod().
|
||||
Container("container1").Req(
|
||||
map[v1.ResourceName]string{
|
||||
v1.ResourceCPU: "1000m",
|
||||
v1.ResourceMemory: "2000",
|
||||
v1.ResourceName(extendedResourceName): "1",
|
||||
}).Obj(), ResourceRequestsOptions{})},
|
||||
},
|
||||
expectedStatusCode: fwk.Success,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
tCtx.SyncTest(name, func(tCtx ktesting.TContext) {
|
||||
runOpts := []runtime.Option{}
|
||||
var testDRAManager *dynamicresources.DefaultDRAManager
|
||||
if !test.disableDRAExtendedResource {
|
||||
testDRAManager = newTestDRAManager(tCtx, deviceClassWithExtendResourceName)
|
||||
runOpts = append(runOpts, runtime.WithSharedDRAManager(testDRAManager))
|
||||
}
|
||||
fh, _ := runtime.NewFramework(tCtx, nil, nil, runOpts...)
|
||||
defer func() {
|
||||
tCtx.Cancel("test has completed")
|
||||
runtime.WaitForShutdown(fh)
|
||||
}()
|
||||
|
||||
fh, _ := runtime.NewFramework(ctx, nil, nil)
|
||||
p, err := NewFit(ctx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, fh, plfeature.Features{
|
||||
EnableDRAExtendedResource: test.enableDRAExtendedResource,
|
||||
p, err := NewFit(tCtx, &config.NodeResourcesFitArgs{ScoringStrategy: defaultScoringStrategy}, fh, plfeature.Features{
|
||||
EnableDRAExtendedResource: !test.disableDRAExtendedResource,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create plugin: %v", err)
|
||||
tCtx.Fatalf("failed to create plugin: %v", err)
|
||||
}
|
||||
|
||||
fit := p.(*Fit)
|
||||
fragments, status := fit.SignPod(ctx, test.pod)
|
||||
fragments, status := fit.SignPod(tCtx, test.pod)
|
||||
|
||||
if status.Code() != test.expectedStatusCode {
|
||||
t.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message())
|
||||
tCtx.Errorf("unexpected status code, want: %v, got: %v, message: %v", test.expectedStatusCode, status.Code(), status.Message())
|
||||
}
|
||||
|
||||
if test.expectedStatusCode == fwk.Success {
|
||||
if diff := cmp.Diff(test.expectedFragments, fragments); diff != "" {
|
||||
t.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff)
|
||||
tCtx.Errorf("unexpected fragments, diff (-want,+got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ func createHandlerWithConfig(kubeClient kubernetes.Interface, informerFactory in
|
|||
if config == nil {
|
||||
config = &resourcequotaapi.Configuration{}
|
||||
}
|
||||
quotaConfiguration, err := install.NewQuotaConfigurationForAdmission(nil, nil)
|
||||
quotaConfiguration, err := install.NewQuotaConfigurationForAdmission(informerFactory, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -944,6 +944,13 @@ items:
|
|||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- resource.k8s.io
|
||||
resources:
|
||||
- resourceclaims
|
||||
verbs:
|
||||
- create
|
||||
- delete
|
||||
- apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
|
|
|
|||
|
|
@ -707,7 +707,7 @@ message DeviceClassSpec {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -1832,7 +1832,7 @@ type DeviceClassSpec struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ var map_DeviceClassSpec = map[string]string{
|
|||
"": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.",
|
||||
"selectors": "Each selector must be satisfied by a device which is claimed via this class.",
|
||||
"config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
}
|
||||
|
||||
func (DeviceClassSpec) SwaggerDoc() map[string]string {
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ message DeviceClassSpec {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -1856,7 +1856,7 @@ type DeviceClassSpec struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ var map_DeviceClassSpec = map[string]string{
|
|||
"": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.",
|
||||
"selectors": "Each selector must be satisfied by a device which is claimed via this class.",
|
||||
"config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
}
|
||||
|
||||
func (DeviceClassSpec) SwaggerDoc() map[string]string {
|
||||
|
|
|
|||
|
|
@ -710,7 +710,7 @@ message DeviceClassSpec {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -1843,7 +1843,7 @@ type DeviceClassSpec struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
// +optional
|
||||
// +featureGate=DRAExtendedResource
|
||||
// +k8s:alpha(since: "1.36")=+k8s:optional
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ var map_DeviceClassSpec = map[string]string{
|
|||
"": "DeviceClassSpec is used in a [DeviceClass] to define what can be allocated and how to configure it.",
|
||||
"selectors": "Each selector must be satisfied by a device which is claimed via this class.",
|
||||
"config": "Config defines configuration parameters that apply to each device that is claimed via this class. Some classses may potentially be satisfied by multiple drivers, so each instance of a vendor configuration applies to exactly one driver.\n\nThey are passed to the driver, but are not considered while allocating the claim.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is an alpha field.",
|
||||
"extendedResourceName": "ExtendedResourceName is the extended resource name for the devices of this class. The devices of this class can be used to satisfy a pod's extended resource requests. It has the same format as the name of a pod's extended resource. It should be unique among all the device classes in a cluster. If two device classes have the same name, then the class created later is picked to satisfy a pod's extended resource requests. If two classes are created at the same time, then the name of the class lexicographically sorted first is picked.\n\nThis is a beta field.",
|
||||
}
|
||||
|
||||
func (DeviceClassSpec) SwaggerDoc() map[string]string {
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
ExtendedResourceName *string `json:"extendedResourceName,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
ExtendedResourceName *string `json:"extendedResourceName,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ type DeviceClassSpecApplyConfiguration struct {
|
|||
// If two classes are created at the same time, then the name of the class
|
||||
// lexicographically sorted first is picked.
|
||||
//
|
||||
// This is an alpha field.
|
||||
// This is a beta field.
|
||||
ExtendedResourceName *string `json:"extendedResourceName,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
| DRADeviceBindingConditions | | | 1.34– | | | | DRAResourceClaimDeviceStatus<br>DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRADeviceBindingConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceBindingConditions%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRADeviceTaintRules | | | 1.35– | | | | DRADeviceTaints | [code](https://cs.k8s.io/?q=%5CbDRADeviceTaintRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceTaintRules%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRADeviceTaints | | | 1.33– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRADeviceTaints%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRADeviceTaints%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRAExtendedResource | | | 1.34– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRAExtendedResource | :ballot_box_with_check: 1.36+ | | 1.34–1.35 | 1.36– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAExtendedResource%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRAPartitionableDevices | | | 1.33– | | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAPartitionableDevices%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAPartitionableDevices%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRAPrioritizedList | :ballot_box_with_check: 1.34+ | | 1.33 | 1.34– | | | DynamicResourceAllocation | [code](https://cs.k8s.io/?q=%5CbDRAPrioritizedList%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAPrioritizedList%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
| DRAResourceClaimDeviceStatus | :ballot_box_with_check: 1.33+ | | 1.32 | 1.33– | | | | [code](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbDRAResourceClaimDeviceStatus%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
|
||||
|
|
|
|||
|
|
@ -543,6 +543,10 @@
|
|||
lockToDefault: false
|
||||
preRelease: Alpha
|
||||
version: "1.34"
|
||||
- default: true
|
||||
lockToDefault: false
|
||||
preRelease: Beta
|
||||
version: "1.36"
|
||||
- name: DRAPartitionableDevices
|
||||
versionedSpecs:
|
||||
- default: false
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ func TestQuota(t *testing.T) {
|
|||
|
||||
discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources
|
||||
listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
|
@ -322,7 +322,7 @@ plugins:
|
|||
|
||||
discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources
|
||||
listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
|
@ -451,7 +451,7 @@ plugins:
|
|||
|
||||
discoveryFunc := clientset.Discovery().ServerPreferredNamespacedResources
|
||||
listerFuncForResource := generic.ListerFuncForResourceFunc(informers.ForResource)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, nil)
|
||||
qc, err := quotainstall.NewQuotaConfigurationForControllers(listerFuncForResource, informers)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue