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

Add support for endpoint slices #5745

Merged
merged 5 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
35 changes: 35 additions & 0 deletions .github/workflows/build_daily.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,38 @@ jobs:
steps: ${{ toJson(steps) }}
channel: '#contour-ci-notifications'
if: ${{ failure() && github.ref == 'refs/heads/main' }}
e2e-endpoint-slices:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
# * Module download cache
# * Build cache (Linux)
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-${{ github.job }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-${{ github.job }}-go-
- uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
cache: false
- name: add deps to path
run: |
./hack/actions/install-kubernetes-toolchain.sh $GITHUB_WORKSPACE/bin
echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
- name: e2e tests
env:
CONTOUR_E2E_IMAGE: ghcr.io/projectcontour/contour:main
CONTOUR_E2E_USE_ENDPOINT_SLICES: true
run: |
make setup-kind-cluster run-e2e cleanup-kind
- uses: act10ns/slack@v2
with:
status: ${{ job.status }}
steps: ${{ toJson(steps) }}
channel: '#contour-ci-notifications'
if: ${{ failure() && github.ref == 'refs/heads/main' }}

11 changes: 11 additions & 0 deletions apis/projectcontour/v1alpha1/contourconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,19 @@ type ContourConfigurationSpec struct {

// Tracing defines properties for exporting trace data to OpenTelemetry.
Tracing *TracingConfig `json:"tracing,omitempty"`

// FeatureFlags defines toggle to enable new contour features.
// Available toggles are:
// useEndpointSlices - configures contour to fetch endpoint data
// from k8s endpoint slices. defaults to false and reading endpoint
// data from the k8s endpoints.
FeatureFlags FeatureFlags `json:"featureFlags,omitempty"`
}

// FeatureFlags defines the set of feature flags
// to toggle new contour features.
type FeatureFlags []string

// XDSServerType is the type of xDS server implementation.
type XDSServerType string

Expand Down
23 changes: 23 additions & 0 deletions apis/projectcontour/v1alpha1/contourconfig_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ import (
"fmt"
"strconv"

"golang.org/x/exp/slices"
"k8s.io/apimachinery/pkg/util/sets"
)

const (
featureFlagUseEndpointSlices string = "useEndpointSlices"
)

var featureFlagsMap = map[string]bool{
featureFlagUseEndpointSlices: true,
}

// Validate configuration that is not already covered by CRD validation.
func (c *ContourConfigurationSpec) Validate() error {
// Validation of root configuration fields.
Expand Down Expand Up @@ -215,6 +224,20 @@ func (e *EnvoyTLS) SanitizedCipherSuites() []string {
return validatedCiphers
}

func (f FeatureFlags) Validate() error {
for _, featureFlag := range f {
if _, found := featureFlagsMap[featureFlag]; !found {
return fmt.Errorf("invalid contour configuration, unknown feature flag:%s", featureFlag)
}
}

return nil
}

func (f FeatureFlags) IsEndpointSliceEnabled() bool {
return slices.Contains(f, featureFlagUseEndpointSlices)
}

// Validate ensures that exactly one of ControllerName or GatewayRef are specified.
func (g *GatewayConfig) Validate() error {
if g == nil {
Expand Down
37 changes: 37 additions & 0 deletions apis/projectcontour/v1alpha1/contourconfig_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package v1alpha1_test

import (
"fmt"
"testing"

"github.com/projectcontour/contour/apis/projectcontour/v1alpha1"
Expand Down Expand Up @@ -294,3 +295,39 @@ func TestAccessLogFormatExtensions(t *testing.T) {
}
assert.Empty(t, e3.AccessLogFormatterExtensions())
}

func TestFeatureFlagsValidate(t *testing.T) {
tests := []struct {
name string
flags v1alpha1.FeatureFlags
expected error
}{
{
name: "valid flag",
flags: v1alpha1.FeatureFlags{"useEndpointSlices"},
expected: nil,
},
{
name: "invalid flag",
flags: v1alpha1.FeatureFlags{"invalidFlag"},
expected: fmt.Errorf("invalid contour configuration, unknown feature flag:invalidFlag"),
},
{
name: "mix of valid and invalid flags",
flags: v1alpha1.FeatureFlags{"useEndpointSlices", "invalidFlag"},
expected: fmt.Errorf("invalid contour configuration, unknown feature flag:invalidFlag"),
},
{
name: "empty flags",
flags: v1alpha1.FeatureFlags{},
expected: nil,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := tt.flags.Validate()
assert.Equal(t, tt.expected, err)
})
}
}
24 changes: 24 additions & 0 deletions apis/projectcontour/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions changelogs/unreleased/5745-clayton-gonsalves-minor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Add Kubernetes Endpoint Slice support

This change optionally enables Contour to consume the kubernetes endpointslice API to determine the endpoints to configure Envoy with.
Note: This change is off by default and is gated by the feature flag `useEndpointSlices`.

This feature will be enabled by default in a future version on Contour once it has had sufficient bake time in production environments.
40 changes: 30 additions & 10 deletions cmd/contour/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"github.com/projectcontour/contour/internal/xdscache"
xdscache_v3 "github.com/projectcontour/contour/internal/xdscache/v3"
"github.com/projectcontour/contour/pkg/config"
discoveryv1 "k8s.io/api/discovery/v1"
)

const (
Expand Down Expand Up @@ -190,6 +191,12 @@
handlerCacheSyncs []cache.InformerSynced
}

type EndpointsTranslator interface {
cache.ResourceEventHandler
xdscache.ResourceCache
SetObserver(observer contour.Observer)
}

// NewServer returns a Server object which contains the initial configuration
// objects required to start an instance of Contour.
func NewServer(log logrus.FieldLogger, ctx *serveContext) (*Server, error) {
Expand Down Expand Up @@ -455,9 +462,13 @@

contourMetrics := metrics.NewMetrics(s.registry)

// Endpoints updates are handled directly by the EndpointsTranslator
// due to their high update rate and their orthogonal nature.
endpointHandler := xdscache_v3.NewEndpointsTranslator(s.log.WithField("context", "endpointstranslator"))
// Endpoints updates are handled directly by the EndpointsTranslator/EndpointSliceTranslator due to the high update volume.
var endpointHandler EndpointsTranslator
if contourConfiguration.FeatureFlags.IsEndpointSliceEnabled() {
endpointHandler = xdscache_v3.NewEndpointSliceTranslator(s.log.WithField("context", "endpointslicetranslator"))
} else {
endpointHandler = xdscache_v3.NewEndpointsTranslator(s.log.WithField("context", "endpointstranslator"))
}

Check warning on line 471 in cmd/contour/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/contour/serve.go#L465-L471

Added lines #L465 - L471 were not covered by tests

resources := []xdscache.ResourceCache{
xdscache_v3.NewListenerCache(listenerConfig, *contourConfiguration.Envoy.Metrics, *contourConfiguration.Envoy.Health, *contourConfiguration.Envoy.Network.EnvoyAdminPort),
Expand All @@ -472,7 +483,7 @@
snapshotHandler := xdscache.NewSnapshotHandler(resources, s.log.WithField("context", "snapshotHandler"))

// register observer for endpoints updates.
endpointHandler.Observer = contour.ComposeObservers(snapshotHandler)
endpointHandler.SetObserver(contour.ComposeObservers(snapshotHandler))

Check warning on line 486 in cmd/contour/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/contour/serve.go#L486

Added line #L486 was not covered by tests

// Log that we're using the fallback certificate if configured.
if contourConfiguration.HTTPProxy.FallbackCertificate != nil {
Expand Down Expand Up @@ -605,12 +616,21 @@
s.log.WithError(err).WithField("resource", "secrets").Fatal("failed to create informer")
}

// Inform on endpoints.
if err := s.informOnResource(&corev1.Endpoints{}, &contour.EventRecorder{
Next: endpointHandler,
Counter: contourMetrics.EventHandlerOperations,
}); err != nil {
s.log.WithError(err).WithField("resource", "endpoints").Fatal("failed to create informer")
// Inform on endpoints/endpointSlices.

Check warning on line 619 in cmd/contour/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/contour/serve.go#L619

Added line #L619 was not covered by tests
if contourConfiguration.FeatureFlags.IsEndpointSliceEnabled() {
if err := s.informOnResource(&discoveryv1.EndpointSlice{}, &contour.EventRecorder{
Next: endpointHandler,
Counter: contourMetrics.EventHandlerOperations,
}); err != nil {
s.log.WithError(err).WithField("resource", "endpointslices").Fatal("failed to create informer")
}
} else {
if err := s.informOnResource(&corev1.Endpoints{}, &contour.EventRecorder{
Next: endpointHandler,
Counter: contourMetrics.EventHandlerOperations,
}); err != nil {
s.log.WithError(err).WithField("resource", "endpoints").Fatal("failed to create informer")
}

Check warning on line 633 in cmd/contour/serve.go

View check run for this annotation

Codecov / codecov/patch

cmd/contour/serve.go#L622-L633

Added lines #L622 - L633 were not covered by tests
}

// Register our event handler with the manager.
Expand Down
1 change: 1 addition & 0 deletions cmd/contour/servecontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@ func (ctx *serveContext) convertToContourConfigurationSpec() contour_api_v1alpha
Policy: policy,
Metrics: &contourMetrics,
Tracing: tracingConfig,
FeatureFlags: ctx.Config.FeatureFlags,
}

xdsServerType := contour_api_v1alpha1.ContourServerType
Expand Down
16 changes: 16 additions & 0 deletions examples/contour/01-crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,14 @@ spec:
type: string
type: object
type: object
featureFlags:
description: 'FeatureFlags defines toggle to enable new contour features.
Available toggles are: useEndpointSlices - configures contour to
fetch endpoint data from k8s endpoint slices. defaults to false
and reading endpoint data from the k8s endpoints.'
items:
type: string
type: array
gateway:
description: Gateway contains parameters for the gateway-api Gateway
that Contour is configured to serve traffic.
Expand Down Expand Up @@ -3898,6 +3906,14 @@ spec:
type: string
type: object
type: object
featureFlags:
description: 'FeatureFlags defines toggle to enable new contour
features. Available toggles are: useEndpointSlices - configures
contour to fetch endpoint data from k8s endpoint slices. defaults
to false and reading endpoint data from the k8s endpoints.'
items:
type: string
type: array
gateway:
description: Gateway contains parameters for the gateway-api Gateway
that Contour is configured to serve traffic.
Expand Down
8 changes: 8 additions & 0 deletions examples/contour/02-role-contour.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ rules:
- get
- list
- watch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
Expand Down
8 changes: 8 additions & 0 deletions examples/gateway-provisioner/01-roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ rules:
- create
- get
- update
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
Expand Down
24 changes: 24 additions & 0 deletions examples/render/contour-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,14 @@ spec:
type: string
type: object
type: object
featureFlags:
description: 'FeatureFlags defines toggle to enable new contour features.
Available toggles are: useEndpointSlices - configures contour to
fetch endpoint data from k8s endpoint slices. defaults to false
and reading endpoint data from the k8s endpoints.'
items:
type: string
type: array
gateway:
description: Gateway contains parameters for the gateway-api Gateway
that Contour is configured to serve traffic.
Expand Down Expand Up @@ -4117,6 +4125,14 @@ spec:
type: string
type: object
type: object
featureFlags:
description: 'FeatureFlags defines toggle to enable new contour
features. Available toggles are: useEndpointSlices - configures
contour to fetch endpoint data from k8s endpoint slices. defaults
to false and reading endpoint data from the k8s endpoints.'
items:
type: string
type: array
gateway:
description: Gateway contains parameters for the gateway-api Gateway
that Contour is configured to serve traffic.
Expand Down Expand Up @@ -8388,6 +8404,14 @@ rules:
- get
- list
- watch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- get
- list
- watch
- apiGroups:
- gateway.networking.k8s.io
resources:
Expand Down
Loading