GEP-957: Destination Port Matching

  • Issue: #957
  • Status: Experimental

Note: This GEP is exempt from the Probationary Period rules of our GEP overview as it existed before those rules did, and so it has been explicitly grandfathered in.

TLDR

Add a new port field to ParentRef to support port matching in Routes.

Goals

  • Support port matching in routes based on the destination port number of the request.

Non-Goals

  • Support port matching based on port name.

Introduction

Port matching is a common service mesh use case where traffic policies/rules need to be applied to traffic to certain destination ports. For ingress, while the API today already supports attaching a route to a specific listener, it may be useful to support attaching routes to listener(s) on a specified port. This allows route authors to apply networking behaviors on a fixed port.

API

The proposal is to add a new field Port to ParentRef:

  1. type ParentRef struct {
  2. ...
  3. // Port is the network port this Route targets. It can be interpreted
  4. // differently based on the type of parent resource:
  5. //
  6. // Gateway: All listeners listening on the specified port that also support
  7. // this kind of Route(and select this Route). It's not recommended to set
  8. // `Port` unless the networking behaviors specified in a Route must
  9. // apply to a specific port as opposed to a listener(s) whose port(s) may
  10. // be changed.
  11. // When both Port and SectionName are specified, the name and port of the
  12. // selected listener must match both specified values.
  13. //
  14. // Implementations MAY choose to support other parent resources.
  15. // Implementations supporting other types of parent resources MUST clearly
  16. // document how/if Port is interpreted.
  17. //
  18. // For the purpose of status, an attachment is considered successful as
  19. // long as the parent resource accepts it partially. For example, Gateway
  20. // listeners can restrict which Routes can attach to them by Route kind,
  21. // namespace, or hostname. If 1 of 2 Gateway listeners accept attachment from
  22. // the referencing Route, the Route MUST be considered successfully
  23. // attached. If no Gateway listeners accept attachment from this Route, the
  24. // Route MUST be considered detached from the Gateway.
  25. //
  26. // Support: Core
  27. //
  28. // +optional
  29. Port *PortNumber `json:"port,omitempty"`
  30. ...
  31. }

The following example shows how an HTTPRoute could be applied to port 8000. In this example, the HTTPRoute will be attached to listeners foo and bar on port 8000 but not listener baz on port 8080.

  1. kind: HTTPRoute
  2. metadata:
  3. name: example
  4. namespace: example
  5. spec:
  6. parentRef:
  7. - name: my-gateway
  8. port: 8000
  9. ...
  10. ---
  11. kind: Gateway
  12. metadata:
  13. name: my-gateway
  14. namespace: example
  15. spec:
  16. listeners:
  17. - name: foo
  18. port: 8000
  19. protocol: HTTP
  20. ...
  21. - name: bar
  22. port: 8000
  23. protocol: HTTP
  24. ...
  25. - name: baz
  26. port: 8080
  27. ...

The following example shows how a TCPRoute could be attached to an Mesh CRD to route all traffic in a service mesh whose original destination port is 8000 to port 8080 of service foo.

  1. kind: TCPRoute
  2. metadata:
  3. name: example
  4. namespace: example
  5. spec:
  6. parentRef:
  7. - name: my-mesh
  8. group: example.io
  9. kind: Mesh
  10. port: 8000
  11. rules:
  12. - backendRefs
  13. - name: foo
  14. port: 8080

Alternatives

1. Use SectionName in ParentRef for port matching

Port matching can be supported if SectionName accepts port numbers in addition to listener names. This approach results in a less explicit API when a ParentRef points to a resource that is not Gateway. For example, an implementation may attach a route to an Mesh CRD. In this case, it’s less inituitive to set ParentRef.SectionName to 443 to express route all traffic whose destination port is 443 to .... It also complicates the validation on SectionName in order to differentiate between a listener name and a port number.

2. Update TrafficMatches to support port matching

TrafficMatches was proposed in gep-735 to support TCP and UDP address matching. TrafficMatches can be extended to support port matching. TrafficMatches will need to be added to HTTPRoute/TLSRoute if the feature is desired there.

While this proposal works for mesh, it may be confusing for ingress because a user can specify port matching behavior in a route that is incompatible with the listeners the route attaches to. For example, a user can specify a match on port 443 in a route while the route only attaches to a listener on port 80.