github.com/cilium/cilium@v1.16.2/pkg/clustermesh/endpointslicesync/endpointslice_meta_controller.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package endpointslicesync 5 6 import ( 7 "context" 8 "time" 9 10 "github.com/cilium/endpointslice-controller/endpointslice" 11 "github.com/sirupsen/logrus" 12 discovery "k8s.io/api/discovery/v1" 13 "k8s.io/apimachinery/pkg/api/errors" 14 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 15 "k8s.io/apimachinery/pkg/labels" 16 "k8s.io/client-go/informers" 17 discoveryv1 "k8s.io/client-go/kubernetes/typed/discovery/v1" 18 discoverylisters "k8s.io/client-go/listers/discovery/v1" 19 20 "github.com/cilium/cilium/pkg/clustermesh/common" 21 k8sClient "github.com/cilium/cilium/pkg/k8s/client" 22 "github.com/cilium/cilium/pkg/k8s/resource" 23 slim_corev1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1" 24 "github.com/cilium/cilium/pkg/k8s/utils" 25 ) 26 27 // endpointSliceCleanupFactory returns a function used as a hook when no service are found in 28 // EndpointSlice controller. Usually EndpointSlice get cleaned up via OwnerReference whenever 29 // the service is deleted, but for the clustermesh case the Service could still 30 // exist but should no longer sync the remote cluster EndpintSlice, so we need to make 31 // sure the existing EndpointSlice from remote clusters are properly deleted. 32 func endpointSliceCleanupFactory(ctx context.Context, discoveryClient discoveryv1.DiscoveryV1Interface, endpointSliceLister discoverylisters.EndpointSliceLister) func(namespace, name string) error { 33 return func(namespace, name string) error { 34 labelSelector := labels.Set(map[string]string{ 35 discovery.LabelServiceName: name, 36 discovery.LabelManagedBy: utils.EndpointSliceMeshControllerName, 37 }).AsSelectorPreValidated() 38 endpointSlices, err := endpointSliceLister.EndpointSlices(namespace).List(labelSelector) 39 if err != nil { 40 return err 41 } 42 for _, endpointSlice := range endpointSlices { 43 deleteOpt := metav1.DeleteOptions{Preconditions: &metav1.Preconditions{ 44 UID: &endpointSlice.UID, 45 }} 46 if err = discoveryClient.EndpointSlices(endpointSlice.Namespace). 47 Delete(ctx, endpointSlice.Name, deleteOpt); err != nil && !errors.IsNotFound(err) { 48 return err 49 } 50 } 51 52 return nil 53 } 54 } 55 56 func newEndpointSliceMeshController( 57 ctx context.Context, logger logrus.FieldLogger, cfg EndpointSliceSyncConfig, 58 meshPodInformer *meshPodInformer, meshNodeInformer *meshNodeInformer, 59 clientset k8sClient.Clientset, services resource.Resource[*slim_corev1.Service], 60 globalServices *common.GlobalServiceCache, 61 ) (*endpointslice.Controller, *meshServiceInformer, informers.SharedInformerFactory) { 62 meshClient := meshClient{clientset} 63 64 factory := informers.NewSharedInformerFactory(meshClient, 12*time.Hour) 65 endpointSliceInformer := factory.Discovery().V1().EndpointSlices() 66 67 meshServiceInformer := newMeshServiceInformer( 68 logger, globalServices, services, meshNodeInformer, 69 ) 70 71 controller := endpointslice.NewControllerWithName( 72 ctx, meshPodInformer, meshServiceInformer, 73 meshNodeInformer, endpointSliceInformer, 74 int32(cfg.ClusterMeshMaxEndpointsPerSlice), 75 meshClient, cfg.ClusterMeshEndpointUpdatesBatchPeriod, 76 utils.EndpointSliceMeshControllerName, nil, 77 endpointSliceCleanupFactory(ctx, clientset.DiscoveryV1(), endpointSliceInformer.Lister()), 78 ) 79 80 return controller, meshServiceInformer, factory 81 }