Skip to content

Commit c4091cb

Browse files
committed
Massive update for defaultOK: true instead of "no parentRefs".
Signed-off-by: Flynn <[email protected]>
1 parent a5fc0c8 commit c4091cb

File tree

1 file changed

+145
-77
lines changed

1 file changed

+145
-77
lines changed

geps/gep-3793/index.md

Lines changed: 145 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -245,45 +245,109 @@ There are three main aspects to the API design for default Gateways:
245245
3. Give anyone with read access to Routes (Ana, Chihiro, or Ian) a way to
246246
enumerate which Routes are bound to the default Gateways.
247247

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.
249252

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:
252290

253291
```yaml
254292
apiVersion: gateway.networking.k8s.io/v1
255293
kind: HTTPRoute
256294
metadata:
257295
name: my-route
258296
spec:
297+
defaultOK: true
259298
rules:
260299
- backendRefs:
261300
- name: my-service
262301
port: 80
263302
```
264303

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+
```
267325

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:
273329

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+
```
281346

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
284348

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:
287351

288352
```yaml
289353
status:
@@ -298,10 +362,17 @@ status:
298362
message: "Route is bound to default Gateway"
299363
```
300364

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.
305376

306377
#### 2. Controlling which Gateways accept Defaulted Routes
307378

@@ -319,10 +390,10 @@ type GatewaySpec struct {
319390
```
320391

321392
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:
326397

327398
```yaml
328399
status:
@@ -347,17 +418,16 @@ from its own namespace.
347418

348419
##### Behavior with No Default Gateway
349420

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.
354425

355-
##### Deleting the Default Gateway
426+
##### Deleting a Default Gateway
356427

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.
361431

362432
##### Multiple Default Gateways
363433

@@ -375,7 +445,7 @@ possible options here.
375445

376446
1. Don't bother with any enforcement logic.
377447

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_
379449
Gateways that have `spec.isDefault` set to `true`. Since Gateway API
380450
already allows a Route to be bound to multiple Gateways, and the Route
381451
`status` is already designed for it, this should function without
@@ -389,11 +459,10 @@ possible options here.
389459
`spec.isDefault` set to `true` is relatively straightforward.
390460

391461
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:
397466

398467
```yaml
399468
status:
@@ -407,38 +476,39 @@ possible options here.
407476
3. Perform conflict resolution as with Routes.
408477

409478
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.
413483

414484
The oldest default Gateway will update its `status` to reflect that it the
415485
default Gateway; all other Gateways with `spec.isDefault` set to `true`
416486
will update their `status` as in Option 2.
417487

418488
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:
420490

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
424494
Routes.
425495

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.
429499

430500
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.
435505

436506
Reluctantly, we must therefore conclude that option 1 is the only viable
437507
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.
442512

443513
##### Changes in Functionality
444514

@@ -451,11 +521,11 @@ that is explicitly specified in a Route's `parentRefs`.
451521

452522
At present, we do not propose any solution to this problem, other than to note
453523
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.
459529

460530
##### Listeners, ListenerSets, and Merging
461531

@@ -464,16 +534,16 @@ Gateway, not where the Gateway listens for traffic. As such, setting
464534
`spec.isDefault` MUST NOT alter a Gateway's behavior with respect to
465535
Listeners, ListenerSets, or merging.
466536

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
469539
is considered later, the guiding principle SHOULD be that `spec.isDefault`
470540
SHOULD NOT affect where a Gateway listens for traffic or whether it can be
471541
merged with other Gateways.
472542

473543
#### 4. Enumerating Routes Bound to Default Gateways
474544

475545
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
477547
`status.parents` of those Routes to see if the Route has been claimed. Since
478548
this will also show _which_ Gateways have claimed a given defaulted Route, it
479549
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
488558
SHOULD be able to show her which Routes are bound to which Gateways in every
489559
case, not just with default Gateways.
490560

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-
498561
### Gateway For Mesh (East/West)
499562

500563
Mesh traffic is defined by using a Service as a `parentRef` rather than a
501564
Gateway. As such, there is no case where a default Gateway would be used for
502565
mesh traffic.
503566

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+
504572
## Conformance Details
505573

506574
#### Feature Names

0 commit comments

Comments
 (0)