@@ -245,45 +245,109 @@ There are three main aspects to the API design for default Gateways:
245
245
3 . Give anyone with read access to Routes (Ana, Chihiro, or Ian) a way to
246
246
enumerate which Routes are bound to the default Gateways.
247
247
248
- #### 1. Binding a Route to a Default Gateway
248
+ We will describe each of these aspects in turn, laying out changes to Gateway
249
+ API behaviors and resources that are necessary to support them. ** Any behavior
250
+ not explicitly discussed in this GEP is intended to remain unchanged;** the
251
+ GEP covers ** all** intended changes to Gateway API behavior.
249
252
250
- For Ana to indicate that a Route should use a default Gateway, she MUST
251
- leave ` parentRefs ` empty in the ` spec ` of the Route, for example:
253
+ #### 1. Creating a Defaulted Route
254
+
255
+ Since Ana must be able to choose whether a Route is defaulted or not, marking
256
+ a Route as defaulted must be an active configuration step she takes, rather
257
+ than any kind of implicit behavior. To that end, the ` CommonRouteSpec `
258
+ resource will gain a new field, ` defaultOK ` :
259
+
260
+ ``` go
261
+ type CommonRouteSpec struct {
262
+ // ... other fields ...
263
+ DefaultOK *bool ` json:"defaultOK,omitempty"`
264
+ }
265
+ ```
266
+
267
+ For Ana to indicate that a Route should use a default Gateway, she MUST set
268
+ ` defaultOK ` to ` true ` in the ` spec ` of the Route:
269
+
270
+ ``` yaml
271
+ ...
272
+ spec :
273
+ defaultOK : true
274
+ ` ` `
275
+
276
+ A Route MAY include explicit ` parentRefs` in addition to setting `defaultOK`
277
+ to `true`. In this case, the Route will be a candidate for being bound to
278
+ default Gateways, but it will also be bound to its explicitly-specified
279
+ Gateways. This allows Ana to create a single Route that handles N/S traffic
280
+ via the default Gateways and also handles E/W traffic via a Service, for
281
+ example.
282
+
283
+ All other characteristics of a defaulted Route MUST behave the same as if all
284
+ default Gateways were explicitly specified in `parentRefs`.
285
+
286
+ # #### Examples
287
+
288
+ **Simple N/S Route**: The following HTTPRoute would route _all_ HTTP traffic
289
+ arriving at any default Gateway to `my-service` on port 80 :
252
290
253
291
` ` ` yaml
254
292
apiVersion: gateway.networking.k8s.io/v1
255
293
kind: HTTPRoute
256
294
metadata:
257
295
name: my-route
258
296
spec:
297
+ defaultOK: true
259
298
rules:
260
299
- backendRefs:
261
300
- name: my-service
262
301
port: 80
263
302
` ` `
264
303
265
- would route _all_ HTTP traffic arriving at any default Gateway to ` my-service`
266
- on port 80.
304
+ **N/S and E/W Route**: The following HTTPRoute would be bound to both any
305
+ default Gateways and to a Service named `face` in the `faces` namespace,
306
+ permitting a single Route to handle both N/S traffic (via the default Gateway)
307
+ and E/W traffic (via the Service) :
308
+
309
+ ` ` ` yaml
310
+ apiVersion: gateway.networking.k8s.io/v1
311
+ kind: HTTPRoute
312
+ metadata:
313
+ name: ns-ew-route
314
+ spec:
315
+ defaultOK: true
316
+ parentRefs:
317
+ - kind: Service
318
+ name: face
319
+ namespace: faces
320
+ rules:
321
+ - backendRefs:
322
+ - name: face
323
+ port: 80
324
+ ` ` `
267
325
268
- Note that Ana MUST omit `parentRefs` entirely : specifying an empty array for
269
- ` parentRefs` MUST fail validation. If a Route with an empty array for
270
- ` parentRefs` somehow exists in the cluster, all Gateways in the cluster MUST
271
- refuse to accept it. (Omitting `parentRefs` entirely will work much more
272
- cleanly with GitOps tools than specifying an empty array.)
326
+ **Multiple Gateways**: A defaulted Route MAY include both a `DefaultGateway`
327
+ and other specific named Gateways, although this is not expected to be common
328
+ in practice :
273
329
274
- Note also that if Ana specifies _any_ `parentRefs`, a default Gateway MUST NOT
275
- claim the Route unless of the `parentRefs` explicitly names that particular
276
- Gateway. To do otherwise makes it impossible for Ana to define mesh-only
277
- Routes, or to specify a Route that is meant to use only a specific Gateway
278
- that is not the default. This implies that for Ana to specify a Route intended
279
- to serve both north/south and east/west roles, she MUST explicitly specify the
280
- Gateway in `parentRefs`, even if that Gateway happens to be a default Gateway.
330
+ ` ` ` yaml
331
+ apiVersion: gateway.networking.k8s.io/v1
332
+ kind: HTTPRoute
333
+ metadata:
334
+ name: multi-gateway-route
335
+ spec:
336
+ defaultOK: true
337
+ parentRefs:
338
+ - kind: Gateway
339
+ name: my-gateway
340
+ namespace: default
341
+ rules:
342
+ - backendRefs:
343
+ - name: my-service
344
+ port: 80
345
+ ` ` `
281
346
282
- All other characteristics of a Route using a default Gateway MUST behave the
283
- same as if the default Gateway(s) were explicitly specified in `parentRefs`.
347
+ # #### `status` for a Defaulted Route
284
348
285
- A default Gateway MUST use `status.parents` to announce that it has bound the
286
- Route, for example :
349
+ When a defaulted Route is claimed by a default Gateway, the Gateway MUST use
350
+ `status.parents` to announce that it has claimed the Route, for example :
287
351
288
352
` ` ` yaml
289
353
status:
@@ -298,10 +362,17 @@ status:
298
362
message: "Route is bound to default Gateway"
299
363
` ` `
300
364
301
- A default Gateway MUST NOT rewrite the `parentRefs` of a Route using the
302
- default Gateway; it MUST leave `parentRefs` empty. This becomes important if
303
- the set of default Gateways changes, or (in some situations) if GitOps tools
304
- are in play.
365
+ # #### Other Considerations
366
+
367
+ A default Gateway MUST NOT modify the `parentRefs` of a defaulted Route to
368
+ indicate that the Route has been claimed by a default Gateway. This becomes
369
+ important if the set of default Gateways changes, or (in some situations) if
370
+ GitOps tools are in play.
371
+
372
+ If there are no default Gateways in the cluster, `defaultOK` MUST be treated
373
+ as if it were set to `false` in all Routes, parallel to the situation where a
374
+ Route specifies a Gateway by name, but no Gateway of that name exists in the
375
+ cluster.
305
376
306
377
# ### 2. Controlling which Gateways accept Defaulted Routes
307
378
@@ -319,10 +390,10 @@ type GatewaySpec struct {
319
390
```
320
391
321
392
If ` spec.isDefault ` is set to ` true ` , the Gateway MUST claim Routes that have
322
- specified no ` parentRefs ` (subject to the usual Gateway API rules about which
323
- Routes may be bound to a Gateway), and it MUST update its own ` status ` with a
324
- ` condition ` of type ` DefaultGateway ` and ` status ` true to indicate that it is
325
- the default Gateway, for example:
393
+ specified ` defaultOK ` ` true ` (subject to the usual Gateway API rules about
394
+ which Routes may be bound to a Gateway), and it MUST update its own ` status `
395
+ with a ` condition ` of type ` DefaultGateway ` and ` status ` true to indicate that
396
+ it is a default Gateway, for example:
326
397
327
398
``` yaml
328
399
status :
@@ -347,17 +418,16 @@ from its own namespace.
347
418
348
419
# #### Behavior with No Default Gateway
349
420
350
- If no Gateway has `spec.isDefault` set to `true`, then the behavior is exactly
351
- the same as for Gateway API 1.3 : all Routes MUST specify `parentRefs` in order
352
- to function , and no Gateway will claim Routes that do not specify
353
- ` parentRefs ` .
421
+ If no Gateway has `spec.isDefault` set to `true`, then all Routes MUST specify
422
+ ` parentRefs ` entries with specific Gateways in order to be accepted by
423
+ Gateways , and all Gateways MUST treat `defaultOK` as if it were set to `false`
424
+ in all Routes .
354
425
355
- # #### Deleting the Default Gateway
426
+ # #### Deleting a Default Gateway
356
427
357
- Deleting the default Gateway MUST behave the same as deleting any other
358
- Gateway : all Routes that were bound to the default Gateway MUST be unbound,
359
- and the `Accepted` conditions in the `status` of those Routes SHOULD be
360
- removed.
428
+ Deleting a default Gateway MUST behave the same as deleting any other Gateway :
429
+ all Routes that were bound to that Gateway MUST be unbound, and the `Accepted`
430
+ conditions in the `status` of those Routes SHOULD be removed.
361
431
362
432
# #### Multiple Default Gateways
363
433
@@ -375,7 +445,7 @@ possible options here.
375
445
376
446
1. Don't bother with any enforcement logic.
377
447
378
- In this case, a Route with no `parentRefs` specified will be bound to _all_
448
+ In this case, a Route that sets `defaultOK` will be bound to _all_
379
449
Gateways that have `spec.isDefault` set to `true`. Since Gateway API
380
450
already allows a Route to be bound to multiple Gateways, and the Route
381
451
` status` is already designed for it, this should function without
@@ -389,11 +459,10 @@ possible options here.
389
459
` spec.isDefault` set to `true` is relatively straightforward.
390
460
391
461
In this case, every Gateway with `spec.isDefault` set to `true` would
392
- simply refuse to accept Routes with no `parentRefs` specified, behaving as
393
- if no Gateway has been chosen as the default. Each Gateway would also
394
- update its `status` with a `condition` of type `DefaultGateway` and
395
- ` status` false to indicate that it is not the default Gateway, for
396
- example :
462
+ treat `defaultOK` as `false` in every Route, behaving as if no Gateway had
463
+ ` spec.isDefault` set. Each Gateway would also update its `status` with a
464
+ ` condition` of type `DefaultGateway` and `status` false to indicate that
465
+ it is not the default Gateway, for example :
397
466
398
467
` ` ` yaml
399
468
status:
@@ -407,38 +476,39 @@ possible options here.
407
476
3. Perform conflict resolution as with Routes.
408
477
409
478
In this case, the oldest Gateway with `spec.isDefault` set to `true` will
410
- be considered the only default Gateway. That oldest Gateway will accept all
411
- Routes with no `parentRefs` specified, while all other Gateways with
412
- ` spec.isDefault` set to `true` will ignore those Routes.
479
+ be considered the only default Gateway. That oldest Gateway will be the
480
+ only one that honors `defaultOK` in Routes, and all other Gateways with
481
+ ` spec.isDefault` set to `true` will treat `defaultOK` as `false` in every
482
+ Route.
413
483
414
484
The oldest default Gateway will update its `status` to reflect that it the
415
485
default Gateway; all other Gateways with `spec.isDefault` set to `true`
416
486
will update their `status` as in Option 2.
417
487
418
488
Unfortunately, option 2 will almost certainly cause downtime in any case where
419
- Chihiro wants to change the default Gateway :
489
+ Chihiro wants to change the implementation behind a default Gateway :
420
490
421
- - If Chihiro deletes the default Gateway before creating the new one, then all
422
- routes using the default Gateway will be unbound during the time that
423
- there's no default Gateway , resulting in errors for any requests using those
491
+ - If Chihiro deletes the old Gateway resource before creating the new one,
492
+ then all routes using that Gateway will be unbound during the time between
493
+ deletion and recreation , resulting in errors for any requests using those
424
494
Routes.
425
495
426
- - If Chihiro creates the new default Gateway before deleting the old one, then
427
- all Routes using the default Gateway are still unbound during the time that
428
- both Gateways exist.
496
+ - If Chihiro creates the new Gateway resource before deleting the old one,
497
+ then all Routes using the old default Gateway will still be unbound during
498
+ the time that both Gateways exist.
429
499
430
500
Option 3 gives Chihiro a way to change the default Gateway without downtime :
431
- when they create the new default Gateway, it will not take effect until the
432
- old default Gateway is deleted. However, it doesn't give Chihiro any way to
433
- test the Routes through the new default Gateway before deleting the old
434
- Gateway.
501
+ when they create the new default Gateway resource , it will not take effect
502
+ until the old default Gateway resource is deleted. However, it doesn't give
503
+ Chihiro any way to test the Routes through the new default Gateway before
504
+ deleting the old Gateway.
435
505
436
506
Reluctantly, we must therefore conclude that option 1 is the only viable
437
507
choice. Therefore : Gateways MUST NOT attempt to enforce a single default
438
- Gateway, and MUST allow Routes with no `parentRefs ` to bind to _all_ Gateways
439
- that have `spec.isDefault` set to `true`. This is simplest to implement, it
440
- permits zero-downtime changes to the default Gateway, and it allows for
441
- testing of the new default Gateway before the old one is deleted.
508
+ Gateway, and MUST allow Routes that set `defaultOK ` to `true` to bind to _all_
509
+ Gateways that have `spec.isDefault` set to `true`. This is simplest to
510
+ implement, it permits zero-downtime changes to the default Gateway, and it
511
+ allows for testing of the new default Gateway before the old one is deleted.
442
512
443
513
# #### Changes in Functionality
444
514
@@ -451,11 +521,11 @@ that is explicitly specified in a Route's `parentRefs`.
451
521
452
522
At present, we do not propose any solution to this problem, other than to note
453
523
that `gwctl` or similar tools SHOULD be able to show Ana not just the Gateways
454
- to which a Route is bound, but also the features supported by those Gateways,
455
- to at least help Ana understand if she is trying to use Gateways that don't
456
- support a feature that she needs. This is a definitely an area for future
457
- work, and it is complicated by the fact that Ana may not have access to read
458
- Gateway resources in the cluster at all.
524
+ to which a Route is bound, but also the features supported by those Gateways.
525
+ This will at least give Ana some visibility into whether she's trying to use
526
+ Gateways that don't support a feature that she needs. This is a definitely an
527
+ area for future work, and it is complicated by the fact that Ana may not have
528
+ access to read Gateway resources in the cluster at all.
459
529
460
530
# #### Listeners, ListenerSets, and Merging
461
531
@@ -464,16 +534,16 @@ Gateway, not where the Gateway listens for traffic. As such, setting
464
534
` spec.isDefault` MUST NOT alter a Gateway's behavior with respect to
465
535
Listeners, ListenerSets, or merging.
466
536
467
- In the future, we may want to consider allowing a default ListenerSet rather
468
- than only a default Gateway , but that is not in scope for this GEP. Even if it
537
+ In the future, we may want to consider allowing default ListenerSets rather
538
+ than only default Gateways , but that is not in scope for this GEP. Even if it
469
539
is considered later, the guiding principle SHOULD be that `spec.isDefault`
470
540
SHOULD NOT affect where a Gateway listens for traffic or whether it can be
471
541
merged with other Gateways.
472
542
473
543
# ### 4. Enumerating Routes Bound to Default Gateways
474
544
475
545
To enumerate Routes bound to the default Gateways, any of Ana, Chihiro, or Ian
476
- can look for Routes with no `parentRefs` specified , and then check the
546
+ can look for Routes that set `defaultOK` to `true` , and then check the
477
547
` status.parents` of those Routes to see if the Route has been claimed. Since
478
548
this will also show _which_ Gateways have claimed a given defaulted Route, it
479
549
neatly solves the problem of allowing Ana to determine which default
@@ -488,19 +558,17 @@ whether or not default Gateways are in play; `gwctl` or something similar
488
558
SHOULD be able to show her which Routes are bound to which Gateways in every
489
559
case, not just with default Gateways.
490
560
491
- # #### Open Questions
492
-
493
- Should the Gateway also add a `condition` explicitly expressing that the Route
494
- has been claimed by the default Gateway, perhaps with `type : DefaultGateway`?
495
- This could help tooling like `gwctl` more easily enumerate Routes bound to the
496
- default Gateway.
497
-
498
561
# ## Gateway For Mesh (East/West)
499
562
500
563
Mesh traffic is defined by using a Service as a `parentRef` rather than a
501
564
Gateway. As such, there is no case where a default Gateway would be used for
502
565
mesh traffic.
503
566
567
+ As noted above, a Route MAY both set `defaultOK` to `true` _and_ include a
568
+ ` Service` ` parentRef` , allowing a single Route to handle both N/S and E/W
569
+ traffic. In this case, the Route will be bound to both the default Gateway and
570
+ the mesh, and the `status` will show both parents.
571
+
504
572
# # Conformance Details
505
573
506
574
# ### Feature Names
0 commit comments