5
5
"fmt"
6
6
"net"
7
7
"sort"
8
+ "sync/atomic"
8
9
"time"
9
10
10
11
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -26,15 +27,17 @@ import (
26
27
"google.golang.org/grpc"
27
28
"google.golang.org/grpc/keepalive"
28
29
29
- clusterservice "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3"
30
- discoverygrpc "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
31
- endpointservice "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3"
32
- listenerservice "github.com/envoyproxy/go-control-plane/envoy/service/listener/v3"
33
- routeservice "github.com/envoyproxy/go-control-plane/envoy/service/route/v3"
34
- runtimeservice "github.com/envoyproxy/go-control-plane/envoy/service/runtime/v3"
35
- secretservice "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3"
36
- envoyproxycache "github.com/envoyproxy/go-control-plane/pkg/cache/v3"
37
- envoyproxyserver "github.com/envoyproxy/go-control-plane/pkg/server/v3"
30
+ clusterv3 "github.com/envoyproxy/go-control-plane/envoy/service/cluster/v3"
31
+ discoveryv3 "github.com/envoyproxy/go-control-plane/envoy/service/discovery/v3"
32
+ endpointv3 "github.com/envoyproxy/go-control-plane/envoy/service/endpoint/v3"
33
+ listenerv3 "github.com/envoyproxy/go-control-plane/envoy/service/listener/v3"
34
+ routev3 "github.com/envoyproxy/go-control-plane/envoy/service/route/v3"
35
+ runtimev3 "github.com/envoyproxy/go-control-plane/envoy/service/runtime/v3"
36
+ secretv3 "github.com/envoyproxy/go-control-plane/envoy/service/secret/v3"
37
+ envoyproxytypes "github.com/envoyproxy/go-control-plane/pkg/cache/types"
38
+ cachev3 "github.com/envoyproxy/go-control-plane/pkg/cache/v3"
39
+ resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
40
+ serverv3 "github.com/envoyproxy/go-control-plane/pkg/server/v3"
38
41
)
39
42
40
43
const (
@@ -69,10 +72,11 @@ type Controller struct {
69
72
grpcroutequeue workqueue.TypedRateLimitingInterface [string ]
70
73
71
74
// envoyproxy control plane
72
- xdscache envoyproxycache .SnapshotCache
73
- xdsserver envoyproxyserver .Server
75
+ xdscache cachev3 .SnapshotCache
76
+ xdsserver serverv3 .Server
74
77
xdsLocalAddress string
75
78
xdsLocalPort int
79
+ xdsVersion atomic.Uint64
76
80
77
81
tunnelManager * tunnels.TunnelManager
78
82
}
@@ -146,33 +150,28 @@ func New(
146
150
_ , err = httprouteInformer .Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
147
151
AddFunc : func (obj interface {}) {
148
152
httproute := obj .(* gatewayv1.HTTPRoute )
149
- if ! c .isOwned (httproute .Spec .ParentRefs , httproute .Namespace ) {
150
- return
151
- }
152
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (obj )
153
- if err == nil {
154
- c .httproutequeue .Add (key )
155
- }
153
+ c .processGateways (httproute .Spec .ParentRefs , httproute .Namespace )
156
154
},
157
155
UpdateFunc : func (oldObj , newObj interface {}) {
158
156
httproute := newObj .(* gatewayv1.HTTPRoute )
159
- if ! c .isOwned (httproute .Spec .ParentRefs , httproute .Namespace ) {
160
- return
161
- }
162
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (newObj )
163
- if err == nil {
164
- c .httproutequeue .Add (key )
165
- }
157
+ c .processGateways (httproute .Spec .ParentRefs , httproute .Namespace )
166
158
},
167
159
DeleteFunc : func (obj interface {}) {
168
- httproute := obj .(* gatewayv1.HTTPRoute )
169
- if ! c .isOwned (httproute .Spec .ParentRefs , httproute .Namespace ) {
170
- return
171
- }
172
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (obj )
173
- if err == nil {
174
- c .httproutequeue .Add (key )
160
+ httproute , ok := obj .(* gatewayv1.HTTPRoute )
161
+ if ! ok {
162
+ // If we reached here it means the pod was deleted but its final state is unrecorded.
163
+ tombstone , ok := obj .(cache.DeletedFinalStateUnknown )
164
+ if ! ok {
165
+ runtime .HandleError (fmt .Errorf ("couldn't get object from tombstone %#v" , obj ))
166
+ return
167
+ }
168
+ httproute , ok = tombstone .Obj .(* gatewayv1.HTTPRoute )
169
+ if ! ok {
170
+ runtime .HandleError (fmt .Errorf ("tombstone contained object that is not a GRPCRoute: %#v" , obj ))
171
+ return
172
+ }
175
173
}
174
+ c .processGateways (httproute .Spec .ParentRefs , httproute .Namespace )
176
175
},
177
176
})
178
177
if err != nil {
@@ -182,33 +181,28 @@ func New(
182
181
_ , err = grpcrouteInformer .Informer ().AddEventHandler (cache.ResourceEventHandlerFuncs {
183
182
AddFunc : func (obj interface {}) {
184
183
grpcroute := obj .(* gatewayv1.GRPCRoute )
185
- if ! c .isOwned (grpcroute .Spec .ParentRefs , grpcroute .Namespace ) {
186
- return
187
- }
188
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (obj )
189
- if err == nil {
190
- c .grpcroutequeue .Add (key )
191
- }
184
+ c .processGateways (grpcroute .Spec .ParentRefs , grpcroute .Namespace )
192
185
},
193
186
UpdateFunc : func (oldObj , newObj interface {}) {
194
187
grpcroute := newObj .(* gatewayv1.GRPCRoute )
195
- if ! c .isOwned (grpcroute .Spec .ParentRefs , grpcroute .Namespace ) {
196
- return
197
- }
198
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (newObj )
199
- if err == nil {
200
- c .grpcroutequeue .Add (key )
201
- }
188
+ c .processGateways (grpcroute .Spec .ParentRefs , grpcroute .Namespace )
202
189
},
203
190
DeleteFunc : func (obj interface {}) {
204
- grpcroute := obj .(* gatewayv1.GRPCRoute )
205
- if ! c .isOwned (grpcroute .Spec .ParentRefs , grpcroute .Namespace ) {
206
- return
207
- }
208
- key , err := cache .DeletionHandlingMetaNamespaceKeyFunc (obj )
209
- if err == nil {
210
- c .grpcroutequeue .Add (key )
191
+ grpcroute , ok := obj .(* gatewayv1.GRPCRoute )
192
+ if ! ok {
193
+ // If we reached here it means the pod was deleted but its final state is unrecorded.
194
+ tombstone , ok := obj .(cache.DeletedFinalStateUnknown )
195
+ if ! ok {
196
+ runtime .HandleError (fmt .Errorf ("couldn't get object from tombstone %#v" , obj ))
197
+ return
198
+ }
199
+ grpcroute , ok = tombstone .Obj .(* gatewayv1.GRPCRoute )
200
+ if ! ok {
201
+ runtime .HandleError (fmt .Errorf ("tombstone contained object that is not a GRPCRoute: %#v" , obj ))
202
+ return
203
+ }
211
204
}
205
+ c .processGateways (grpcroute .Spec .ParentRefs , grpcroute .Namespace )
212
206
},
213
207
})
214
208
if err != nil {
@@ -272,8 +266,8 @@ func (c *Controller) Run(ctx context.Context) error {
272
266
273
267
klog .Info ("Starting Envoy proxy controller" )
274
268
// Create a cache
275
- c .xdscache = envoyproxycache .NewSnapshotCache (false , envoyproxycache .IDHash {}, nil )
276
- c .xdsserver = envoyproxyserver .NewServer (ctx , c .xdscache , nil )
269
+ c .xdscache = cachev3 .NewSnapshotCache (false , cachev3 .IDHash {}, nil )
270
+ c .xdsserver = serverv3 .NewServer (ctx , c .xdscache , nil )
277
271
278
272
var grpcOptions []grpc.ServerOption
279
273
grpcOptions = append (grpcOptions ,
@@ -289,13 +283,13 @@ func (c *Controller) Run(ctx context.Context) error {
289
283
)
290
284
grpcServer := grpc .NewServer (grpcOptions ... )
291
285
292
- discoverygrpc .RegisterAggregatedDiscoveryServiceServer (grpcServer , c .xdsserver )
293
- endpointservice .RegisterEndpointDiscoveryServiceServer (grpcServer , c .xdsserver )
294
- clusterservice .RegisterClusterDiscoveryServiceServer (grpcServer , c .xdsserver )
295
- routeservice .RegisterRouteDiscoveryServiceServer (grpcServer , c .xdsserver )
296
- listenerservice .RegisterListenerDiscoveryServiceServer (grpcServer , c .xdsserver )
297
- secretservice .RegisterSecretDiscoveryServiceServer (grpcServer , c .xdsserver )
298
- runtimeservice .RegisterRuntimeDiscoveryServiceServer (grpcServer , c .xdsserver )
286
+ discoveryv3 .RegisterAggregatedDiscoveryServiceServer (grpcServer , c .xdsserver )
287
+ endpointv3 .RegisterEndpointDiscoveryServiceServer (grpcServer , c .xdsserver )
288
+ clusterv3 .RegisterClusterDiscoveryServiceServer (grpcServer , c .xdsserver )
289
+ routev3 .RegisterRouteDiscoveryServiceServer (grpcServer , c .xdsserver )
290
+ listenerv3 .RegisterListenerDiscoveryServiceServer (grpcServer , c .xdsserver )
291
+ secretv3 .RegisterSecretDiscoveryServiceServer (grpcServer , c .xdsserver )
292
+ runtimev3 .RegisterRuntimeDiscoveryServiceServer (grpcServer , c .xdsserver )
299
293
300
294
address , err := GetControlPlaneAddress ()
301
295
if err != nil {
@@ -320,7 +314,7 @@ func (c *Controller) Run(ctx context.Context) error {
320
314
c .xdsLocalAddress = address
321
315
c .xdsLocalPort = tcpAddr .Port
322
316
go func () {
323
- klog .Infof ("management server listening on %d\n " , c .xdsLocalPort )
317
+ klog .Infof ("XDS management server listening on %s % d\n " , c . xdsLocalAddress , c .xdsLocalPort )
324
318
if err = grpcServer .Serve (listener ); err != nil {
325
319
klog .Infoln (err )
326
320
}
@@ -340,40 +334,39 @@ func (c *Controller) Run(ctx context.Context) error {
340
334
341
335
for i := 0 ; i < workers ; i ++ {
342
336
go wait .UntilWithContext (ctx , c .runGatewayWorker , time .Second )
343
- go wait .UntilWithContext (ctx , c .runHTTPRouteWorker , time .Second )
344
- go wait .UntilWithContext (ctx , c .runGRPCrouteWorker , time .Second )
345
337
}
346
338
347
339
<- ctx .Done ()
348
340
klog .Info ("Stopping Gateway API controller" )
349
341
return nil
350
342
}
351
343
352
- func (c * Controller ) isOwned (references []gatewayv1.ParentReference , localNamespace string ) bool {
344
+ // processGateways enqueues all referenced gateways from the Parent References
345
+ func (c * Controller ) processGateways (references []gatewayv1.ParentReference , localNamespace string ) {
353
346
for _ , ref := range references {
354
- if ref .Group == nil || ref .Kind == nil {
355
- continue
356
- }
357
347
namespace := localNamespace
358
348
if ref .Namespace != nil {
359
349
namespace = string (* ref .Namespace )
360
350
}
361
- if string ( * ref .Group ) != "gateway.networking.k8s.io" && string (* ref .Group ) != "" {
351
+ if ref .Group != nil && string (* ref .Group ) != "gateway.networking.k8s.io " {
362
352
continue
363
353
}
364
- if string (* ref .Kind ) != "Gateway" {
354
+
355
+ if ref .Kind != nil && string (* ref .Kind ) != "Gateway" {
365
356
continue
366
357
}
367
358
368
359
gw , err := c .gatewayLister .Gateways (namespace ).Get (string (ref .Name ))
369
360
if err != nil {
361
+ klog .Infof ("fail to obtain referenced gateway %s/%s : %v" , namespace , ref .Name , err )
370
362
continue
371
363
}
372
- if gw .Spec .GatewayClassName == GWClassName {
373
- return true
364
+ if gw .Spec .GatewayClassName != GWClassName {
365
+ klog .V (2 ).Infof ("gateway %s/%s not managed by this controller" , namespace , ref .Name )
366
+ continue
374
367
}
368
+ c .gatewayqueue .Add (gw .Namespace + "/" + gw .Name )
375
369
}
376
- return false
377
370
}
378
371
379
372
// UpdateConditionIfChanged updates or insert a condition if it has been changed.
@@ -453,3 +446,26 @@ func GetControlPlaneAddress() (string, error) {
453
446
454
447
return "" , fmt .Errorf ("no suitable global unicast IPv4 address found on any active non-loopback interface" )
455
448
}
449
+
450
+ // UpdateXDSServer changes the resource snapshot held by the XDS server, which
451
+ // updates connected clients as required.
452
+ func (c * Controller ) UpdateXDSServer (ctx context.Context , nodeid string , resources map [resourcev3.Type ][]envoyproxytypes.Resource ) error {
453
+ c .xdsVersion .Add (1 )
454
+
455
+ // Create a snapshot with the passed in resources.
456
+ snapshot , err := cachev3 .NewSnapshot (fmt .Sprintf ("%d" , c .xdsVersion .Load ()), resources )
457
+ if err != nil {
458
+ return fmt .Errorf ("failed to create new snapshot cache: %v" , err )
459
+
460
+ }
461
+ if err := snapshot .Consistent (); err != nil {
462
+ return fmt .Errorf ("failed to create new resource snapshot: %v" , err )
463
+ }
464
+
465
+ // Update the cache with the new resource snapshot.
466
+ if err := c .xdscache .SetSnapshot (ctx , nodeid , snapshot ); err != nil {
467
+ return fmt .Errorf ("failed to update resource snapshot in management server: %v" , err )
468
+ }
469
+ klog .V (4 ).Infof ("Updated snapshot cache with resource snapshot..." )
470
+ return nil
471
+ }
0 commit comments