Skip to content

Commit

Permalink
*: Add support for EndpointSlices in EDS
Browse files Browse the repository at this point in the history
Introduces initial support for the EndpointSlice API in
the core gloo translator logic.

Signed-off-by: timflannagan <timflannagan@gmail.com>
  • Loading branch information
timflannagan committed Oct 3, 2024
1 parent 0f6fd42 commit 4edd4e4
Show file tree
Hide file tree
Showing 18 changed files with 936 additions and 191 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,7 @@ $(TEST_ASSET_DIR)/conformance/conformance_test.go:

CONFORMANCE_SUPPORTED_FEATURES ?= -supported-features=Gateway,ReferenceGrant,HTTPRoute,HTTPRouteQueryParamMatching,HTTPRouteMethodMatching,HTTPRouteResponseHeaderModification,HTTPRoutePortRedirect,HTTPRouteHostRewrite,HTTPRouteSchemeRedirect,HTTPRoutePathRedirect,HTTPRouteHostRewrite,HTTPRoutePathRewrite,HTTPRouteRequestMirror
CONFORMANCE_SUPPORTED_PROFILES ?= -conformance-profiles=GATEWAY-HTTP
CONFORMANCE_SKIP_TESTS ?= -skip-tests=HTTPRouteServiceTypes
CONFORMANCE_SKIP_TESTS ?= -skip-tests=
CONFORMANCE_REPORT_ARGS ?= -report-output=$(TEST_ASSET_DIR)/conformance/$(VERSION)-report.yaml -organization=solo.io -project=gloo-gateway -version=$(VERSION) -url=github.com/solo-io/gloo -contact=github.com/solo-io/gloo/issues/new/choose
CONFORMANCE_ARGS := -gateway-class=gloo-gateway $(CONFORMANCE_SKIP_TESTS) $(CONFORMANCE_SUPPORTED_FEATURES) $(CONFORMANCE_SUPPORTED_PROFILES) $(CONFORMANCE_REPORT_ARGS)

Expand Down
8 changes: 8 additions & 0 deletions changelog/v1.18.0-beta24/support-endpointslices.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
changelog:
- type: NEW_FEATURE
issueLink: https://github.com/solo-io/solo-projects/issues/6910
resolvesIssue: false
description: >-
Add support for EndpointSlices in the Gloo Gateway proxy. This feature
allows Gloo to use EndpointSlices to discover endpoints for services
instead of the legacy Endpoints API.
16 changes: 10 additions & 6 deletions pkg/schemes/scheme.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
package schemes

import (
sologatewayv1 "github.com/solo-io/gloo/projects/gateway/pkg/api/v1/kube/apis/gateway.solo.io/v1"
sologatewayv1alpha1 "github.com/solo-io/gloo/projects/gateway2/api/v1alpha1"
extauthkubev1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/extauth/v1/kube/apis/enterprise.gloo.solo.io/v1"
graphqlv1beta1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/graphql/v1beta1/kube/apis/graphql.gloo.solo.io/v1beta1"
gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/kube/apis/gloo.solo.io/v1"
ratelimitv1alpha1 "github.com/solo-io/solo-apis/pkg/api/ratelimit.solo.io/v1alpha1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
"k8s.io/apimachinery/pkg/runtime"
apiv1 "sigs.k8s.io/gateway-api/apis/v1"
apiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

ratelimitv1alpha1 "github.com/solo-io/solo-apis/pkg/api/ratelimit.solo.io/v1alpha1"

sologatewayv1 "github.com/solo-io/gloo/projects/gateway/pkg/api/v1/kube/apis/gateway.solo.io/v1"
sologatewayv1alpha1 "github.com/solo-io/gloo/projects/gateway2/api/v1alpha1"
extauthkubev1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/extauth/v1/kube/apis/enterprise.gloo.solo.io/v1"
graphqlv1beta1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/enterprise/options/graphql/v1beta1/kube/apis/graphql.gloo.solo.io/v1beta1"
gloov1 "github.com/solo-io/gloo/projects/gloo/pkg/api/v1/kube/apis/gloo.solo.io/v1"
)

// SchemeBuilder contains all the Schemes for registering the CRDs with which Gloo Gateway interacts.
Expand All @@ -24,6 +27,7 @@ var SchemeBuilder = runtime.SchemeBuilder{
// Kubernetes Core resources
corev1.AddToScheme,
appsv1.AddToScheme,
discoveryv1.AddToScheme,

// Solo Kubernetes Gateway API resources
sologatewayv1alpha1.AddToScheme,
Expand Down
2 changes: 1 addition & 1 deletion projects/gateway2/controller/gw_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (r *gatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
return ctrl.Result{}, nil
}

log.Info("reconciling gateway", "Gateway", gw.GetObjectMeta())
log.Info("reconciling gateway", "Gateway", gw.GetName())
objs, err := r.deployer.GetObjsToDeploy(ctx, &gw)
if err != nil {
return ctrl.Result{}, err
Expand Down
2 changes: 1 addition & 1 deletion projects/gateway2/translator/gateway_translator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type translatorTestCase struct {

var _ = DescribeTable("Basic GatewayTranslator Tests",
func(in translatorTestCase) {
ctx := context.TODO()
ctx := context.Background()
dir := util.MustGetThisDir()

results, err := TestCase{
Expand Down
36 changes: 23 additions & 13 deletions projects/gloo/pkg/plugins/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (

"github.com/solo-io/solo-kit/pkg/api/v1/clients/kube/controller"
kubeinformers "k8s.io/client-go/informers"
kubelisters "k8s.io/client-go/listers/core/v1"
corev1listers "k8s.io/client-go/listers/core/v1"
discoveryv1listers "k8s.io/client-go/listers/discovery/v1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
Expand All @@ -19,15 +20,17 @@ import (
//go:generate mockgen -destination ./mocks/kubesharedfactory_mock.go github.com/solo-io/gloo/projects/gloo/pkg/plugins/kubernetes KubePluginSharedFactory

type KubePluginSharedFactory interface {
EndpointsLister(ns string) kubelisters.EndpointsLister
EndpointsLister(ns string) corev1listers.EndpointsLister
EndpointSlicesLister(ns string) discoveryv1listers.EndpointSliceLister
Subscribe() <-chan struct{}
Unsubscribe(<-chan struct{})
}

type KubePluginListers struct {
initError error

endpointsLister map[string]kubelisters.EndpointsLister
endpointsLister map[string]corev1listers.EndpointsLister
endpointSlicesLister map[string]discoveryv1listers.EndpointSliceLister

cacheUpdatedWatchers []chan struct{}
cacheUpdatedWatchersMutex sync.Mutex
Expand All @@ -48,31 +51,35 @@ func getInformerFactory(ctx context.Context, client kubernetes.Interface, watchN
}

func startInformerFactory(ctx context.Context, client kubernetes.Interface, watchNamespaces []string) *KubePluginListers {
resyncDuration := 12 * time.Hour
const resyncDuration = 12 * time.Hour

var informers []cache.SharedIndexInformer
k := &KubePluginListers{
endpointsLister: map[string]kubelisters.EndpointsLister{},
endpointsLister: map[string]corev1listers.EndpointsLister{},
endpointSlicesLister: map[string]discoveryv1listers.EndpointSliceLister{},
}
for _, nsToWatch := range watchNamespaces {
kubeInformerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(client, resyncDuration, kubeinformers.WithNamespace(nsToWatch))
endpointInformer := kubeInformerFactory.Core().V1().Endpoints()
informers = append(informers, endpointInformer.Informer())
endpointSliceInformer := kubeInformerFactory.Discovery().V1().EndpointSlices()
k.endpointsLister[nsToWatch] = endpointInformer.Lister()
k.endpointSlicesLister[nsToWatch] = endpointSliceInformer.Lister()
informers = append(informers, endpointInformer.Informer(), endpointSliceInformer.Informer())
}

kubeController := controller.NewController("kube-plugin-controller",
kubeController := controller.NewController(
"kube-plugin-controller",
controller.NewLockingSyncHandler(k.updatedOccurred),
informers...)
informers...,
)

stop := ctx.Done()
err := kubeController.Run(2, stop)
if err != nil && ctx.Err() == nil {
if err := kubeController.Run(2, stop); err != nil && ctx.Err() == nil {
k.initError = errors.Wrapf(err, "could not start shared informer factory")
return k
}

var syncFuncs []cache.InformerSynced
syncFuncs := make([]cache.InformerSynced, 0, len(informers))
for _, informer := range informers {
syncFuncs = append(syncFuncs, informer.HasSynced)
}
Expand All @@ -86,10 +93,14 @@ func startInformerFactory(ctx context.Context, client kubernetes.Interface, watc
return k
}

func (k *KubePluginListers) EndpointsLister(ns string) kubelisters.EndpointsLister {
func (k *KubePluginListers) EndpointsLister(ns string) corev1listers.EndpointsLister {
return k.endpointsLister[ns]
}

func (k *KubePluginListers) EndpointSlicesLister(ns string) discoveryv1listers.EndpointSliceLister {
return k.endpointSlicesLister[ns]
}

func (k *KubePluginListers) Subscribe() <-chan struct{} {
k.cacheUpdatedWatchersMutex.Lock()
defer k.cacheUpdatedWatchersMutex.Unlock()
Expand All @@ -99,7 +110,6 @@ func (k *KubePluginListers) Subscribe() <-chan struct{} {
}

func (k *KubePluginListers) Unsubscribe(c <-chan struct{}) {

k.cacheUpdatedWatchersMutex.Lock()
defer k.cacheUpdatedWatchersMutex.Unlock()
for i, cacheUpdated := range k.cacheUpdatedWatchers {
Expand Down
Loading

0 comments on commit 4edd4e4

Please sign in to comment.