From 8afdee87d92bbfe0fc500b67b882b1903b9b1ab9 Mon Sep 17 00:00:00 2001 From: Aaron U'Ren Date: Tue, 26 Dec 2023 15:51:57 -0600 Subject: [PATCH] fact(NSC): differentiate headless services Differentiate headless services from ClusterIP being none, in preparation for handling the service.kubernetes.io/headless label. One might thing that handling these is similar, which it sort of is and sort of isn't. ClusterIP is an immutable field, whereas labels are mutable. This changes our handling of ClusterIP none-ness from the presence of the headless label. When we consider what to do with ClusterIP being none, that is fundamentally different, because once it is None, the k8s API guarantees that the service won't ever change. Whereas the label can be added and removed. --- pkg/controllers/proxy/network_services_controller.go | 4 ++-- pkg/controllers/routing/ecmp_vip.go | 4 ++-- pkg/utils/service.go | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/controllers/proxy/network_services_controller.go b/pkg/controllers/proxy/network_services_controller.go index ea8437d46d..9d7c3c8426 100644 --- a/pkg/controllers/proxy/network_services_controller.go +++ b/pkg/controllers/proxy/network_services_controller.go @@ -800,7 +800,7 @@ func (nsc *NetworkServicesController) OnEndpointsUpdate(es *discovery.EndpointSl klog.Warningf("failed to lookup any service as an owner for %s/%s", es.Namespace, es.Name) return } - if utils.ServiceIsHeadless(svc) { + if utils.ServiceHasNoClusterIP(svc) { klog.V(1).Infof("The service associated with endpoint: %s/%s is headless, skipping...", es.Namespace, es.Name) return @@ -839,7 +839,7 @@ func (nsc *NetworkServicesController) OnServiceUpdate(svc *v1.Service) { // skip processing as we only work with VIPs in the next section. Since the ClusterIP field is immutable we don't // need to consider previous versions of the service here as we are guaranteed if is a ClusterIP now, it was a // ClusterIP before. - if utils.ServiceIsHeadless(svc) { + if utils.ServiceHasNoClusterIP(svc) { klog.V(1).Infof("%s/%s is headless, skipping...", svc.Namespace, svc.Name) return } diff --git a/pkg/controllers/routing/ecmp_vip.go b/pkg/controllers/routing/ecmp_vip.go index b5f7bf4355..e782670800 100644 --- a/pkg/controllers/routing/ecmp_vip.go +++ b/pkg/controllers/routing/ecmp_vip.go @@ -204,7 +204,7 @@ func (nrc *NetworkRoutingController) tryHandleServiceUpdate(objOld, objNew inter // skip processing as we only work with VIPs in the next section. Since the ClusterIP field is immutable we // don't need to consider previous versions of the service here as we are guaranteed if is a ClusterIP now, // it was a ClusterIP before. - if utils.ServiceIsHeadless(objNew) { + if utils.ServiceHasNoClusterIP(objNew) { klog.V(1).Infof("%s/%s is headless, skipping...", svcNew.Namespace, svcNew.Name) return } @@ -228,7 +228,7 @@ func (nrc *NetworkRoutingController) tryHandleServiceDelete(oldObj interface{}, klog.V(1).Infof(logMsgFormat, oldSvc.Namespace, oldSvc.Name) // If the service is headless skip processing as we only work with VIPs in the next section. - if utils.ServiceIsHeadless(oldObj) { + if utils.ServiceHasNoClusterIP(oldObj) { klog.V(1).Infof("%s/%s is headless, skipping...", oldSvc.Namespace, oldSvc.Name) return } diff --git a/pkg/utils/service.go b/pkg/utils/service.go index 0059cde0f6..a266093c3e 100644 --- a/pkg/utils/service.go +++ b/pkg/utils/service.go @@ -115,11 +115,11 @@ func ServiceForEndpointSlice(ci *cache.Indexer, es *discovery.EndpointSlice) (in return item, true, nil } -// ServiceIsHeadless decides whether or not the this service is a headless service which is often useful to kube-router -// as there is no need to execute logic on most headless changes. Function takes a generic interface as its input -// parameter so that it can be used more easily in early processing if needed. If a non-service object is given, +// ServiceHasNoClusterIP decides whether or not the this service is a headless service which is often useful to +// kube-router as there is no need to execute logic on most headless changes. Function takes a generic interface as its +// input parameter so that it can be used more easily in early processing if needed. If a non-service object is given, // function will return false. -func ServiceIsHeadless(obj interface{}) bool { +func ServiceHasNoClusterIP(obj interface{}) bool { if svc, _ := obj.(*v1core.Service); svc != nil { if svc.Spec.Type == v1core.ServiceTypeClusterIP { if ClusterIPIsNone(svc.Spec.ClusterIP) && containsOnlyNone(svc.Spec.ClusterIPs) {