Skip to content

Commit 33c64b3

Browse files
authored
Merge pull request kubernetes#128646 from pohly/dra-kubelet-separate-beta-api
DRA kubelet: separate beta and alpha gRPC APIs
2 parents e30492f + 9261a18 commit 33c64b3

File tree

10 files changed

+2924
-84
lines changed

10 files changed

+2924
-84
lines changed

pkg/kubelet/cm/dra/plugin/plugin.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (p *Plugin) NodePrepareResources(
128128
response, err = nodeClient.NodePrepareResources(ctx, req)
129129
case drapbv1alpha4.NodeService:
130130
nodeClient := drapbv1alpha4.NewNodeClient(conn)
131-
response, err = nodeClient.NodePrepareResources(ctx, req)
131+
response, err = drapbv1alpha4.V1Alpha4ClientWrapper{NodeClient: nodeClient}.NodePrepareResources(ctx, req)
132132
default:
133133
// Shouldn't happen, validateSupportedServices should only
134134
// return services we support here.
@@ -161,7 +161,7 @@ func (p *Plugin) NodeUnprepareResources(
161161
response, err = nodeClient.NodeUnprepareResources(ctx, req)
162162
case drapbv1alpha4.NodeService:
163163
nodeClient := drapbv1alpha4.NewNodeClient(conn)
164-
response, err = nodeClient.NodeUnprepareResources(ctx, req)
164+
response, err = drapbv1alpha4.V1Alpha4ClientWrapper{NodeClient: nodeClient}.NodeUnprepareResources(ctx, req)
165165
default:
166166
// Shouldn't happen, validateSupportedServices should only
167167
// return services we support here.

pkg/kubelet/cm/dra/plugin/plugin_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import (
3434
)
3535

3636
type fakeGRPCServer struct {
37-
drapbv1beta1.UnimplementedDRAPluginServer
3837
}
3938

4039
var _ drapbv1beta1.DRAPluginServer = &fakeGRPCServer{}
@@ -84,7 +83,7 @@ func setupFakeGRPCServer(service string) (string, tearDown, error) {
8483
case drapbv1beta1.DRAPluginService:
8584
drapbv1beta1.RegisterDRAPluginServer(s, fakeGRPCServer)
8685
case drapbv1alpha4.NodeService:
87-
drapbv1alpha4.RegisterNodeServer(s, fakeGRPCServer)
86+
drapbv1alpha4.RegisterNodeServer(s, drapbv1alpha4.V1Beta1ServerWrapper{DRAPluginServer: fakeGRPCServer})
8887
default:
8988
return "", nil, fmt.Errorf("unsupported gRPC service: %s", service)
9089
}

staging/src/k8s.io/dynamic-resource-allocation/kubeletplugin/draplugin.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,12 @@ type draPlugin struct {
272272
// If the plugin will be used to publish resources, [KubeClient] and [NodeName]
273273
// options are mandatory.
274274
//
275-
// By default, the DRA driver gets registered so that the plugin is compatible
276-
// with Kubernetes >= 1.32. To be compatible with Kubernetes >= 1.31, a driver
277-
// has to ask specifically to register only the alpha gRPC API, i.e. use:
278-
//
279-
// Start(..., NodeV1beta1(false))
280-
func Start(ctx context.Context, nodeServer interface{}, opts ...Option) (result DRAPlugin, finalErr error) {
275+
// The DRA driver decides which gRPC interfaces it implements. At least one
276+
// implementation of [drapbv1alpha4.NodeServer] or [drapbv1beta1.DRAPluginServer]
277+
// is required. Implementing drapbv1beta1.DRAPluginServer is recommended for
278+
// DRA driver targeting Kubernetes >= 1.32. To be compatible with Kubernetes 1.31,
279+
// DRA drivers must implement only [drapbv1alpha4.NodeServer].
280+
func Start(ctx context.Context, nodeServers []interface{}, opts ...Option) (result DRAPlugin, finalErr error) {
281281
logger := klog.FromContext(ctx)
282282
o := options{
283283
logger: klog.Background(),
@@ -338,15 +338,17 @@ func Start(ctx context.Context, nodeServer interface{}, opts ...Option) (result
338338
// Run the node plugin gRPC server first to ensure that it is ready.
339339
var supportedServices []string
340340
plugin, err := startGRPCServer(klog.NewContext(ctx, klog.LoggerWithName(logger, "dra")), o.grpcVerbosity, o.unaryInterceptors, o.streamInterceptors, o.draEndpoint, func(grpcServer *grpc.Server) {
341-
if nodeServer, ok := nodeServer.(drapbv1alpha4.NodeServer); ok && o.nodeV1alpha4 {
342-
logger.V(5).Info("registering v1alpha4.Node gGRPC service")
343-
drapbv1alpha4.RegisterNodeServer(grpcServer, nodeServer)
344-
supportedServices = append(supportedServices, drapbv1alpha4.NodeService)
345-
}
346-
if nodeServer, ok := nodeServer.(drapbv1beta1.DRAPluginServer); ok && o.nodeV1beta1 {
347-
logger.V(5).Info("registering v1beta1.DRAPlugin gRPC service")
348-
drapbv1beta1.RegisterDRAPluginServer(grpcServer, nodeServer)
349-
supportedServices = append(supportedServices, drapbv1beta1.DRAPluginService)
341+
for _, nodeServer := range nodeServers {
342+
if nodeServer, ok := nodeServer.(drapbv1alpha4.NodeServer); ok && o.nodeV1alpha4 {
343+
logger.V(5).Info("registering v1alpha4.Node gGRPC service")
344+
drapbv1alpha4.RegisterNodeServer(grpcServer, nodeServer)
345+
supportedServices = append(supportedServices, drapbv1alpha4.NodeService)
346+
}
347+
if nodeServer, ok := nodeServer.(drapbv1beta1.DRAPluginServer); ok && o.nodeV1beta1 {
348+
logger.V(5).Info("registering v1beta1.DRAPlugin gRPC service")
349+
drapbv1beta1.RegisterDRAPluginServer(grpcServer, nodeServer)
350+
supportedServices = append(supportedServices, drapbv1beta1.DRAPluginService)
351+
}
350352
}
351353
})
352354
if err != nil {
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha4
18+
19+
import (
20+
context "context"
21+
fmt "fmt"
22+
23+
grpc "google.golang.org/grpc"
24+
"k8s.io/apimachinery/pkg/runtime"
25+
"k8s.io/kubelet/pkg/apis/dra/v1beta1"
26+
)
27+
28+
var (
29+
localSchemeBuilder runtime.SchemeBuilder
30+
AddToScheme = localSchemeBuilder.AddToScheme
31+
)
32+
33+
// V1Beta1ServerWrapper implements the [NodeServer] interface by wrapping a [v1beta1.DRAPluginServer].
34+
type V1Beta1ServerWrapper struct {
35+
v1beta1.DRAPluginServer
36+
}
37+
38+
var _ NodeServer = V1Beta1ServerWrapper{}
39+
40+
func (w V1Beta1ServerWrapper) NodePrepareResources(ctx context.Context, req *NodePrepareResourcesRequest) (*NodePrepareResourcesResponse, error) {
41+
var convertedReq v1beta1.NodePrepareResourcesRequest
42+
if err := Convert_v1alpha4_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
43+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1alpha4 to v1beta1: %w", err)
44+
}
45+
resp, err := w.DRAPluginServer.NodePrepareResources(ctx, &convertedReq)
46+
if err != nil {
47+
return nil, err
48+
}
49+
var convertedResp NodePrepareResourcesResponse
50+
if err := Convert_v1beta1_NodePrepareResourcesResponse_To_v1alpha4_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
51+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1beta1 to v1alpha4: %w", err)
52+
}
53+
return &convertedResp, nil
54+
}
55+
56+
func (w V1Beta1ServerWrapper) NodeUnprepareResources(ctx context.Context, req *NodeUnprepareResourcesRequest) (*NodeUnprepareResourcesResponse, error) {
57+
var convertedReq v1beta1.NodeUnprepareResourcesRequest
58+
if err := Convert_v1alpha4_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
59+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1alpha4 to v1beta1: %w", err)
60+
}
61+
resp, err := w.DRAPluginServer.NodeUnprepareResources(ctx, &convertedReq)
62+
if err != nil {
63+
return nil, err
64+
}
65+
var convertedResp NodeUnprepareResourcesResponse
66+
if err := Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1alpha4_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
67+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1beta1 to v1alpha4: %w", err)
68+
}
69+
return &convertedResp, nil
70+
}
71+
72+
// V1Alpha4ServerWrapper implements the [v1beta1.DRAPluginServer] interface by wrapping a [NodeServer].
73+
type V1Alpha4ServerWrapper struct {
74+
NodeServer
75+
}
76+
77+
var _ v1beta1.DRAPluginServer = V1Alpha4ServerWrapper{}
78+
79+
func (w V1Alpha4ServerWrapper) NodePrepareResources(ctx context.Context, req *v1beta1.NodePrepareResourcesRequest) (*v1beta1.NodePrepareResourcesResponse, error) {
80+
var convertedReq NodePrepareResourcesRequest
81+
if err := Convert_v1beta1_NodePrepareResourcesRequest_To_v1alpha4_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
82+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1beta1 to v1alpha4: %w", err)
83+
}
84+
resp, err := w.NodeServer.NodePrepareResources(ctx, &convertedReq)
85+
if err != nil {
86+
return nil, err
87+
}
88+
var convertedResp v1beta1.NodePrepareResourcesResponse
89+
if err := Convert_v1alpha4_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
90+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1alpha4 to v1beta1: %w", err)
91+
}
92+
return &convertedResp, nil
93+
}
94+
95+
func (w V1Alpha4ServerWrapper) NodeUnprepareResources(ctx context.Context, req *v1beta1.NodeUnprepareResourcesRequest) (*v1beta1.NodeUnprepareResourcesResponse, error) {
96+
var convertedReq NodeUnprepareResourcesRequest
97+
if err := Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1alpha4_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
98+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1beta1 to v1alpha4: %w", err)
99+
}
100+
resp, err := w.NodeServer.NodeUnprepareResources(ctx, &convertedReq)
101+
if err != nil {
102+
return nil, err
103+
}
104+
var convertedResp v1beta1.NodeUnprepareResourcesResponse
105+
if err := Convert_v1alpha4_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
106+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1alpha4 to v1beta1: %w", err)
107+
}
108+
return &convertedResp, nil
109+
}
110+
111+
// V1Beta1ClientWrapper implements the [NodeClient] interface by wrapping a [v1beta1.DRAPluginClient].
112+
type V1Beta1ClientWrapper struct {
113+
v1beta1.DRAPluginClient
114+
}
115+
116+
var _ NodeClient = V1Beta1ClientWrapper{}
117+
118+
func (w V1Beta1ClientWrapper) NodePrepareResources(ctx context.Context, req *NodePrepareResourcesRequest, options ...grpc.CallOption) (*NodePrepareResourcesResponse, error) {
119+
var convertedReq v1beta1.NodePrepareResourcesRequest
120+
if err := Convert_v1alpha4_NodePrepareResourcesRequest_To_v1beta1_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
121+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1alpha4 to v1beta1: %w", err)
122+
}
123+
resp, err := w.DRAPluginClient.NodePrepareResources(ctx, &convertedReq, options...)
124+
if err != nil {
125+
return nil, err
126+
}
127+
var convertedResp NodePrepareResourcesResponse
128+
if err := Convert_v1beta1_NodePrepareResourcesResponse_To_v1alpha4_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
129+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1beta1 to v1alpha4: %w", err)
130+
}
131+
return &convertedResp, nil
132+
}
133+
134+
func (w V1Beta1ClientWrapper) NodeUnprepareResources(ctx context.Context, req *NodeUnprepareResourcesRequest, options ...grpc.CallOption) (*NodeUnprepareResourcesResponse, error) {
135+
var convertedReq v1beta1.NodeUnprepareResourcesRequest
136+
if err := Convert_v1alpha4_NodeUnprepareResourcesRequest_To_v1beta1_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
137+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1alpha4 to v1beta1: %w", err)
138+
}
139+
resp, err := w.DRAPluginClient.NodeUnprepareResources(ctx, &convertedReq, options...)
140+
if err != nil {
141+
return nil, err
142+
}
143+
var convertedResp NodeUnprepareResourcesResponse
144+
if err := Convert_v1beta1_NodeUnprepareResourcesResponse_To_v1alpha4_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
145+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1beta1 to v1alpha4: %w", err)
146+
}
147+
return &convertedResp, nil
148+
}
149+
150+
// V1Alpha4ClientWrapper implements the [v1beta1.DRAPluginClient] interface by wrapping a [NodeClient].
151+
type V1Alpha4ClientWrapper struct {
152+
NodeClient
153+
}
154+
155+
var _ v1beta1.DRAPluginClient = V1Alpha4ClientWrapper{}
156+
157+
func (w V1Alpha4ClientWrapper) NodePrepareResources(ctx context.Context, req *v1beta1.NodePrepareResourcesRequest, options ...grpc.CallOption) (*v1beta1.NodePrepareResourcesResponse, error) {
158+
var convertedReq NodePrepareResourcesRequest
159+
if err := Convert_v1beta1_NodePrepareResourcesRequest_To_v1alpha4_NodePrepareResourcesRequest(req, &convertedReq, nil); err != nil {
160+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesRequest from v1beta1 to v1alpha4: %w", err)
161+
}
162+
resp, err := w.NodeClient.NodePrepareResources(ctx, &convertedReq, options...)
163+
if err != nil {
164+
return nil, err
165+
}
166+
var convertedResp v1beta1.NodePrepareResourcesResponse
167+
if err := Convert_v1alpha4_NodePrepareResourcesResponse_To_v1beta1_NodePrepareResourcesResponse(resp, &convertedResp, nil); err != nil {
168+
return nil, fmt.Errorf("internal error converting NodePrepareResourcesResponse from v1alpha4 to v1beta1: %w", err)
169+
}
170+
return &convertedResp, nil
171+
}
172+
173+
func (w V1Alpha4ClientWrapper) NodeUnprepareResources(ctx context.Context, req *v1beta1.NodeUnprepareResourcesRequest, options ...grpc.CallOption) (*v1beta1.NodeUnprepareResourcesResponse, error) {
174+
var convertedReq NodeUnprepareResourcesRequest
175+
if err := Convert_v1beta1_NodeUnprepareResourcesRequest_To_v1alpha4_NodeUnprepareResourcesRequest(req, &convertedReq, nil); err != nil {
176+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesRequest from v1beta1 to v1alpha4: %w", err)
177+
}
178+
resp, err := w.NodeClient.NodeUnprepareResources(ctx, &convertedReq, options...)
179+
if err != nil {
180+
return nil, err
181+
}
182+
var convertedResp v1beta1.NodeUnprepareResourcesResponse
183+
if err := Convert_v1alpha4_NodeUnprepareResourcesResponse_To_v1beta1_NodeUnprepareResourcesResponse(resp, &convertedResp, nil); err != nil {
184+
return nil, fmt.Errorf("internal error converting NodeUnprepareResourcesResponse from v1alpha4 to v1beta1: %w", err)
185+
}
186+
return &convertedResp, nil
187+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package v1alpha4 contains a legacy implementation of the DRA gRPC
18+
// interface. Support for it in kubelet is provided via conversion.
19+
//
20+
// +k8s:conversion-gen=k8s.io/kubelet/pkg/apis/dra/v1beta1
21+
package v1alpha4

0 commit comments

Comments
 (0)