Skip to content

Commit 5dc87d2

Browse files
authored
Merge pull request kubernetes#83965 from robscott/endpointslice-managed-by
Adding new label to indicate what is managing an EndpointSlice
2 parents 48ddf3b + 6b8b2ff commit 5dc87d2

File tree

5 files changed

+304
-34
lines changed

5 files changed

+304
-34
lines changed

pkg/controller/endpointslice/endpointslice_controller.go

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,20 @@ const (
5454
// 5ms, 10ms, 20ms, 40ms, 80ms, 160ms, 320ms, 640ms, 1.3s, 2.6s, 5.1s,
5555
// 10.2s, 20.4s, 41s, 82s
5656
maxRetries = 15
57+
// controllerName is a unique value used with LabelManagedBy to indicated
58+
// the component managing an EndpointSlice.
59+
controllerName = "endpointslice-controller.k8s.io"
60+
// managedBySetupAnnotation is set on a Service to indicate that
61+
// EndpointSlices for the Service have already been configured with
62+
// LabelManagedBy. If this annotation is not set, all related EndpointSlices
63+
// will have LabelManagedBy set to reference this controller if the label
64+
// is not already set. Once all EndpointSlices are labeled, the Controller
65+
// will set this annotation on the Service.
66+
managedBySetupAnnotation = "endpointslice.kubernetes.io/managed-by-setup"
67+
// managedBySetupCompleteValue represents the value of the
68+
// managedBySetupAnnotation that indicates that the setup process has been
69+
// completed for a Service.
70+
managedBySetupCompleteValue = "true"
5771
)
5872

5973
// NewController creates and initializes a new Controller
@@ -286,7 +300,28 @@ func (c *Controller) syncService(key string) error {
286300
return err
287301
}
288302

289-
esLabelSelector := labels.Set(map[string]string{discovery.LabelServiceName: service.Name}).AsSelectorPreValidated()
303+
// With the goal of different controllers being able to manage different
304+
// subsets of EndpointSlices, LabelManagedBy has been added to indicate
305+
// which controller or entity manages an EndpointSlice. As part of this
306+
// v1.16->v1.17 change, EndpointSlices will initially be assumed to be
307+
// managed by this controller unless a label is set to indicate otherwise.
308+
// To ensure a seamless upgrade process, the managedBySetupAnnotation is
309+
// used to indicate that LabelManagedBy has been set initially for related
310+
// EndpointSlices. If it hasn't been set to the expected value here, we call
311+
// ensureSetupManagedByAnnotation() to set up LabelManagedBy on each
312+
// EndpointSlice.
313+
// TODO(robscott): Remove this before v1.18.
314+
err = c.ensureSetupManagedByAnnotation(service)
315+
if err != nil {
316+
c.eventRecorder.Eventf(service, v1.EventTypeWarning, "FailedToSetEndpointSliceManagedByLabel",
317+
"Error adding managed-by Label to Endpoint Slices for Service %s/%s: %v", service.Namespace, service.Name, err)
318+
return err
319+
}
320+
321+
esLabelSelector := labels.Set(map[string]string{
322+
discovery.LabelServiceName: service.Name,
323+
discovery.LabelManagedBy: controllerName,
324+
}).AsSelectorPreValidated()
290325
endpointSlices, err := c.endpointSliceLister.EndpointSlices(service.Namespace).List(esLabelSelector)
291326

292327
if err != nil {
@@ -337,6 +372,49 @@ func (c *Controller) onServiceDelete(obj interface{}) {
337372
c.queue.Add(key)
338373
}
339374

375+
// ensureSetupManagedByAnnotation selects all EndpointSlices for a Service and
376+
// ensures they have LabelManagedBy set appropriately. This ensures that only
377+
// one controller or entity is trying to manage a given EndpointSlice. This
378+
// function provides backwards compatibility with the initial alpha release of
379+
// EndpointSlices that did not include these labels.
380+
// TODO(robscott): Remove this in time for v1.18.
381+
func (c *Controller) ensureSetupManagedByAnnotation(service *v1.Service) error {
382+
if managedBySetup, ok := service.Annotations[managedBySetupAnnotation]; ok && managedBySetup == managedBySetupCompleteValue {
383+
return nil
384+
}
385+
386+
esLabelSelector := labels.Set(map[string]string{discovery.LabelServiceName: service.Name}).AsSelectorPreValidated()
387+
endpointSlices, err := c.endpointSliceLister.EndpointSlices(service.Namespace).List(esLabelSelector)
388+
389+
if err != nil {
390+
c.eventRecorder.Eventf(service, v1.EventTypeWarning, "FailedToListEndpointSlices",
391+
"Error listing Endpoint Slices for Service %s/%s: %v", service.Namespace, service.Name, err)
392+
return err
393+
}
394+
395+
for _, endpointSlice := range endpointSlices {
396+
if _, ok := endpointSlice.Labels[discovery.LabelManagedBy]; !ok {
397+
if endpointSlice.Labels == nil {
398+
endpointSlice.Labels = make(map[string]string)
399+
}
400+
401+
endpointSlice.Labels[discovery.LabelManagedBy] = controllerName
402+
_, err = c.client.DiscoveryV1alpha1().EndpointSlices(endpointSlice.Namespace).Update(endpointSlice)
403+
if err != nil {
404+
return err
405+
}
406+
}
407+
}
408+
409+
if service.Annotations == nil {
410+
service.Annotations = make(map[string]string)
411+
}
412+
413+
service.Annotations[managedBySetupAnnotation] = managedBySetupCompleteValue
414+
_, err = c.client.CoreV1().Services(service.Namespace).Update(service)
415+
return err
416+
}
417+
340418
func (c *Controller) addPod(obj interface{}) {
341419
pod := obj.(*v1.Pod)
342420
services, err := c.serviceSelectorCache.GetPodServiceMemberships(c.serviceLister, pod)

0 commit comments

Comments
 (0)