Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Design: Endpoint slice support #5703

Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions design/endpoint-slice-support.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Contour k8s EndpointSlice support

Contour currently supports Kubernetes endpoints.
This document proposes a process to enable support for k8s EndpointSlices and, eventually, migrate to exclusively using it.

## Goals

- Contour will support k8s EndpointSlices.
- The EndpointSlices will be gated by a feature flag in the Contour config.
- Kubernetes endpoints will still be the default mode of operation.
clayton-gonsalves marked this conversation as resolved.
Show resolved Hide resolved

## Non-goals

- Removal of k8s endpoints.
- Support advanced features such as topology aware routing/hints offered by k8s endpoints.
clayton-gonsalves marked this conversation as resolved.
Show resolved Hide resolved

## Background

See [#2696](https://github.com/projectcontour/contour/issues/2696)

Before the introduction of the EndpointSlices, the only method for a service to expose the IP addresses and ports of the pads it fronted was through Kubernetes endpoints.

However, Kubernetes endpoints have a few challenges with scaling, such as
- transmission of the entire endpoint object even if one endpoint changes, leading to network contention and heavy recalculation on the consumers of this data.
- As of k8s v1.22, a hard limit of 1000 addresses per endpoint object.
- No topology aware information for more intelligent routing.

To solve the above problems, EndpointSlices was introduced in 1.16 and, as of k8s v1.21 in [stable state](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/).


## High-Level Design

A feature flag will gate the usage of EndpointSlices, and the implementation will use the same pattern as used in the `endpointtranslator.go` with a few differences listed in the detailed design.

## Detailed Design
clayton-gonsalves marked this conversation as resolved.
Show resolved Hide resolved
clayton-gonsalves marked this conversation as resolved.
Show resolved Hide resolved

### Contour Configuration changes
EndpointSlices will be configured by a boolean feature flag, which defaults to false and allows users to opt to use EndpointSlices.

```yaml
...
server:
xds-server-type: contour
use-endpoint-slice: true
...
```

```go
type Parameters struct {
// useEndpointSlice configures contour to fetch endpoint data
// from k8s EndpointSlices. defaults to false and reading endpoint
// data from the k8s endpoints.
useEndpointSlice bool
}
```
### Implementation

#### Context
The implementation of k8s EndpointSlices is fundamentally different from how EndpointSlices work.

Below is an example of a Kubernetes service represented in as endpoint and EndpointSlice objects

endpoints
```
NAME ENDPOINTS AGE
ingress-conformance-echo 10.244.0.10:3000,10.244.0.153:3000,10.244.0.154:3000 + 7 more... 3d
```

EndpointSlice
```
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
ingress-conformance-echo-8bcrv IPv4 3000 10.244.0.156,10.244.0.157 18h
ingress-conformance-echo-dr6d2 IPv4 3000 10.244.0.158,10.244.0.159 18h
ingress-conformance-echo-dt27v IPv4 3000 10.244.0.153,10.244.0.154 2d14h
ingress-conformance-echo-l2j48 IPv4 3000 10.244.0.10,10.244.0.155 3d
ingress-conformance-echo-z4bcw IPv4 3000 10.244.0.160,10.244.0.161 18h
```

#### EndpointSlice cache

Because of the above mentioned differences, there is a need to adapt the cache logic from `endpointtranslator.go` such as;

Instead of using `endpoints map[types.NamespacedName]*v1.Endpoints`, use the below format with a nested map `k,v` where `k` is the EndpointSlice name and the `v` is the EndpointSlice itself.

```go
type EndpointSliceCache struct {
endpointSlice: map[types.NamespacedName]map[string]*discoveryv1.EndpointSlice{},
}
```

The above structure lets us keep track of each EndpointSlice and change/update/delete an endpoint without shuffling all the existing endpoints.

#### EndpointSlice conditions
The EndpointSlice has information about the condition of the endpoint, namely, `ready`, `serving` and `terminating`. The EndpointSlice implementation will only support the `ready` condition.
This means that only pods with `ready` status will be considered since `ready` on the EndpointSlice maps to `ready` status on the pods. This also keep contour inline with the existing implementation.

refer [ready status](https://kubernetes.io/docs/concepts/services-networking/endpoint-slices/#ready)

#### FQDN Address types
FQDN address types on EndpointSlices will not be supported. Contour will continue to support `externalName` service types.

## Tests

To ensure the feature is well tested, this feature will have
- e2e tests
clayton-gonsalves marked this conversation as resolved.
Show resolved Hide resolved
- unit tests
- daily build run with EndpointSlices enabled.

## Migration Plan

Once we have enough consensus on the correctness and performance, we can make the move to EndpointSlices permanent and deprecate use of endpoints. This can be a combination of daily builds, burn time and feedback from the community.


## Alternatives Considered

N/A