Skip to content

Commit

Permalink
clustermesh: enable endpointslice sync by default on headless services
Browse files Browse the repository at this point in the history
As it's highly likely that for an Headless Service the user wants to
sync EndpointSlices we should set it by default in this case and make the
behavior opt-out instead of opt-in.

It's highly unlikely that this change anything for existing setup as
before endpoint slice synchronization were a thing Headless services
were ignored. Also EndpointSlice sync is still guarded by a feature flag
set in helm/in the configmap.

Signed-off-by: Arthur Outhenin-Chalandre <arthur@cri.epita.fr>
  • Loading branch information
MrFreezeex authored and julianwiedmann committed Apr 19, 2024
1 parent 0429e0d commit 5f0fafe
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 5 deletions.
6 changes: 5 additions & 1 deletion Documentation/network/clustermesh/services.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,14 @@ Synchronizing Kubernetes EndpointSlice (Beta)

.. include:: ../../beta.rst

By default Kubernetes EndpointSlice synchronization is disabled on Global services.
By default Kubernetes EndpointSlice synchronization is disabled on non Headless Global services.
To have Cilium discover remote clusters endpoints of a Global Service
from DNS or any third party controllers, enable synchronization by adding
the annotation ``service.cilium.io/global-sync-endpoint-slices: "true"``.
This will allow Cilium to create Kubernetes EndpointSlices belonging to a
remote cluster for services that have that annotation.
Regarding Global Headless services this option is enabled by default unless
explicitly opted-out by adding the annotation ``service.cilium.io/global-sync-endpoint-slices: "false"``.

Note that this feature does not complement/is not required by any other Cilium features
and is only required if you need to discover EndpointSlice from remote cluster on
Expand Down
34 changes: 34 additions & 0 deletions pkg/clustermesh/endpointslicesync/endpointslice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,40 @@ func Test_meshEndpointSlice_Reconcile(t *testing.T) {
require.Zero(t, len(epList.Items))
})

t.Run("Create headless service and global service", func(t *testing.T) {
svcName := "local-svc-headless-global-svc"
svc1 := createService(svcName)
svc1.Spec.ClusterIP = corev1.ClusterIPNone

svcStore.CacheStore().Add(svc1)
serviceInformer.refreshAllCluster(svc1)
createGlobalService(globalService, podInformer, svcName)

queue := getControllerQueue(controller)
require.NoError(t, waitEmptyQueue(queue))

epList, err := getEndpointSlice(&fakeClient, svcName)
require.NoError(t, err)
require.Equal(t, 1, len(epList.Items))
})

t.Run("Create headless service with endpointslice opt-out and global service", func(t *testing.T) {
svcName := "local-svc-headless-opt-out-global-svc"
svc1 := createService(svcName)
svc1.Spec.ClusterIP = corev1.ClusterIPNone
svc1.ObjectMeta.Annotations[annotation.GlobalServiceSyncEndpointSlices] = "false"
svcStore.CacheStore().Add(svc1)
serviceInformer.refreshAllCluster(svc1)
createGlobalService(globalService, podInformer, svcName)

queue := getControllerQueue(controller)
require.NoError(t, waitEmptyQueue(queue))

epList, err := getEndpointSlice(&fakeClient, svcName)
require.NoError(t, err)
require.Equal(t, 0, len(epList.Items))
})

t.Run("Create service with global annotation and remove it", func(t *testing.T) {
svcName := "svc-remove-annotation"
createGlobalService(globalService, podInformer, svcName)
Expand Down
8 changes: 4 additions & 4 deletions pkg/clustermesh/endpointslicesync/service_informer.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ func doesServiceSyncEndpointSlice(svc *slim_corev1.Service) bool {
}

value, ok = annotation.Get(svc, annotation.GlobalServiceSyncEndpointSlices)
if !ok || strings.ToLower(value) != "true" {
return false
if !ok {
// If the service is headless we sync the EndpointSlice by default
return svc.Spec.ClusterIP == v1.ClusterIPNone
}

return true
return strings.ToLower(value) == "true"
}

func (i *meshServiceInformer) refreshAllCluster(svc *slim_corev1.Service) error {
Expand Down

0 comments on commit 5f0fafe

Please sign in to comment.