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  }