Skip to content

Commit

Permalink
docs: gep 735 L4 traffic matching
Browse files Browse the repository at this point in the history
  • Loading branch information
shaneutt committed Nov 15, 2021
1 parent 01ecd5a commit 4f73e63
Showing 1 changed file with 202 additions and 0 deletions.
202 changes: 202 additions & 0 deletions site-src/geps/gep-735.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
# GEP-735: TCP and UDP addresses and port matching

* Issue: [#735](https://github.com/kubernetes-sigs/gateway-api/issues/735)
* Status: Provisional

## TLDR

Spec for matching source and destination addresses & ports on L4 APIs.

## Goals

- add matching rules for address/port to `TCPRoute`
- add matching rules for address/port to `UDPRoute`
- intentionally avoid type definitions that would make it hard to expand later

## Non-Goals

- defining match rules for source ports

## Introduction

While `TCPRoute` and `UDPRoute` currently support custom matching extensions,
there is desire among the community to include some "fundamental" matching
options in the spec that cover the most common requirements. In this GEP we
request address and port matching for these APIs in order to support a standard
for some of the commonplace setups of gateway implementations. Matching is
intended to be covered for both _source_ and _destination_ to enable a finer
level of tuning options for L4 traffic routing at a level below the `Gateway`.

When this GEP was started the intention was to cover source port matching but
the use cases for such were significantly less obvious than matching for other
types, and it seemed likely that a port _range_ would be wanted in that case.
Given the lack of strong requirements source ports were left out for this
iteration with the intention that it can be very easily added later to the
`TrafficMatches` type there's stronger requirements established.

## API

The API changes include the following new types:

- `NetworkMatch` to indicate the IP for address matching
- `TrafficMatches` to configure matching according to network address and ports

These types enable the port and address matching required, with some
active considerations about how to leave these open ended for later expansion.

### NetworkMatch Type

A new `NetworkMatch` type provides the targeting mechanism for match inclusion
of a given network address:

```go
type NetworkMatch struct {
// Address is an IP address which refers to either an IPv4 or IPv6 address.
//
// Examples: `127.0.0.1`, `::1`
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=45
Address string `json:"address"`
}
```

The purpose of calling this `NetworkMatch` and wrapping the single `IP` attribute in
a structure is to enable forward expansion in case later we're interested in
adding more specificity, such as perhaps the network mask or `/<int>` CIDR to
allow matching within a network range, instead of a specific IP address:

```go
type NetworkMatch struct {
Address string `json:"address"`
Mask *string `json:"mask"`
}
```

However for this iteration the goal is to keep the initial spec simple and to
the immediate goals so only `Address` is intended for inclusion until further
requirements develop.

### PortMatch Type

a new `PortMatch` type provides the targeting mechanism for match inclusion of
a given network port:

```go
type PortMatch struct {
// Port is a network port.
//
// Examples: `80`, `443`
//
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=5
Port PortNumber `json:"port"`
}
```

Similar to the `NetworkMatch` above, the purpose of wrapping the port in a
struct is to help make it easier to add functionality later without having
to publish a new API and conversions.

### TrafficMatches Type

Using the new `NetworkMatch` and `PortMatch` type, matches can be expressed in
topical lists on `TCPRoute` and `UDPRoute` using the new `TrafficMatches` type:

```go
type TrafficMatches struct {
// SourceAddresses indicates the originating (source) network
// addresses which are valid for routing traffic.
SourceAddresses []NetworkMatch `json:"sourceAddresses"`

// DestinationAddresses indicates the destination network addresses
// which are valid for routing traffic.
DestinationAddresses []NetworkMatch `json:"destinationAddresses"`

// DestinationPorts indicates the destination network ports that are
// valid for routing traffic.
DestinationPorts []PortMatch `json:"destinationPorts"`
```
This type becomes an optional field and shared by both `TCPRouteRule` and
`UDPRouteRule`:
```go
type TCPRouteRule struct {
// Matches add rules for filtering traffic to backends based on addresses
// and ports.
//
// +optional
Matches *TrafficMatches `json:"matches"`

// BackendRefs defines the backend(s) where matching requests should be
// sent. If unspecified or invalid (refers to a non-existent resource or a
// Service with no endpoints), the underlying implementation MUST actively
// reject connection attempts to this backend. Connection rejections must
// respect weight; if an invalid backend is requested to have 80% of
// connections, then 80% of connections must be rejected instead.
//
// Support: Core for Kubernetes Service
// Support: Custom for any other resource
//
// Support for weight: Extended
//
// +kubebuilder:validation:MinItems=1
// +kubebuilder:validation:MaxItems=16
BackendRefs []BackendRef `json:"backendRefs,omitempty"`
}
```
The above would make the following YAML examples possible:
```yaml
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: matching
spec:
rules:
- matches:
sourceAddresses:
- address: "192.168.1.1"
- address: "FE80::0202:B3FF:FE1E:8329"
destinationAddresses:
- address: "10.96.0.1"
destinationPorts:
- port: 8080
backendRefs:
- name: my-service
port: 8080
```
## Alternatives
### Pure Gateway Mode
Technically the existing specification supported this kind of matching through
`Gateway` object `Listeners` and it was considered to simply document that
further and expand upon it, but in a desire to better support more complex
setups that are becoming commonplace in the ecosystem (e.g. service mesh) there
was sufficient cause to add this functionality at the route level.
### Copying NetworkPolicy
After the first draft of this document we consulted the `NetworkPolicy` API to
determine if there were enough similarities to copy some of the semantics there
to here. Both the [existing API][k8s-net] and (at the time of writing) the
[upcoming API][pol-new] were reviewed. Ultimately some influence was taken from
`NetworkPolicyPort` to define the `PolicyMatch` structure here, but some ideas
such as binding ports and network addresses together in a single struct did not
seem necessary as the `RuleAction` present in policy did not seem applicable
for this work at the time. We may want to revisit this as the new policy work
merges and matures.
[k8s-net]:https://github.com/kubernetes/kubernetes/blob/1e6f3b5cd68049a3501782af8ff3ddd647d0b408/pkg/apis/networking/types.go#L95
[pol-new]:https://github.com/kubernetes/enhancements/pull/2522
## References
A related conversation in [#727][issue-727] ultimately instigated these
new requirements and may be helpful to review.
[issue-727]:https://github.com/kubernetes-sigs/gateway-api/issues/727

0 comments on commit 4f73e63

Please sign in to comment.