k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/proxy/config/config.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package config 18 19 import ( 20 "context" 21 "fmt" 22 "sync" 23 "time" 24 25 v1 "k8s.io/api/core/v1" 26 discoveryv1 "k8s.io/api/discovery/v1" 27 networkingv1alpha1 "k8s.io/api/networking/v1alpha1" 28 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 "k8s.io/apimachinery/pkg/util/sets" 30 v1informers "k8s.io/client-go/informers/core/v1" 31 discoveryv1informers "k8s.io/client-go/informers/discovery/v1" 32 networkingv1alpha1informers "k8s.io/client-go/informers/networking/v1alpha1" 33 "k8s.io/client-go/tools/cache" 34 "k8s.io/klog/v2" 35 ) 36 37 // ServiceHandler is an abstract interface of objects which receive 38 // notifications about service object changes. 39 type ServiceHandler interface { 40 // OnServiceAdd is called whenever creation of new service object 41 // is observed. 42 OnServiceAdd(service *v1.Service) 43 // OnServiceUpdate is called whenever modification of an existing 44 // service object is observed. 45 OnServiceUpdate(oldService, service *v1.Service) 46 // OnServiceDelete is called whenever deletion of an existing service 47 // object is observed. 48 OnServiceDelete(service *v1.Service) 49 // OnServiceSynced is called once all the initial event handlers were 50 // called and the state is fully propagated to local cache. 51 OnServiceSynced() 52 } 53 54 // EndpointSliceHandler is an abstract interface of objects which receive 55 // notifications about endpoint slice object changes. 56 type EndpointSliceHandler interface { 57 // OnEndpointSliceAdd is called whenever creation of new endpoint slice 58 // object is observed. 59 OnEndpointSliceAdd(endpointSlice *discoveryv1.EndpointSlice) 60 // OnEndpointSliceUpdate is called whenever modification of an existing 61 // endpoint slice object is observed. 62 OnEndpointSliceUpdate(oldEndpointSlice, newEndpointSlice *discoveryv1.EndpointSlice) 63 // OnEndpointSliceDelete is called whenever deletion of an existing 64 // endpoint slice object is observed. 65 OnEndpointSliceDelete(endpointSlice *discoveryv1.EndpointSlice) 66 // OnEndpointSlicesSynced is called once all the initial event handlers were 67 // called and the state is fully propagated to local cache. 68 OnEndpointSlicesSynced() 69 } 70 71 // EndpointSliceConfig tracks a set of endpoints configurations. 72 type EndpointSliceConfig struct { 73 listerSynced cache.InformerSynced 74 eventHandlers []EndpointSliceHandler 75 logger klog.Logger 76 } 77 78 // NewEndpointSliceConfig creates a new EndpointSliceConfig. 79 func NewEndpointSliceConfig(ctx context.Context, endpointSliceInformer discoveryv1informers.EndpointSliceInformer, resyncPeriod time.Duration) *EndpointSliceConfig { 80 result := &EndpointSliceConfig{ 81 listerSynced: endpointSliceInformer.Informer().HasSynced, 82 logger: klog.FromContext(ctx), 83 } 84 85 _, _ = endpointSliceInformer.Informer().AddEventHandlerWithResyncPeriod( 86 cache.ResourceEventHandlerFuncs{ 87 AddFunc: result.handleAddEndpointSlice, 88 UpdateFunc: result.handleUpdateEndpointSlice, 89 DeleteFunc: result.handleDeleteEndpointSlice, 90 }, 91 resyncPeriod, 92 ) 93 94 return result 95 } 96 97 // RegisterEventHandler registers a handler which is called on every endpoint slice change. 98 func (c *EndpointSliceConfig) RegisterEventHandler(handler EndpointSliceHandler) { 99 c.eventHandlers = append(c.eventHandlers, handler) 100 } 101 102 // Run waits for cache synced and invokes handlers after syncing. 103 func (c *EndpointSliceConfig) Run(stopCh <-chan struct{}) { 104 c.logger.Info("Starting endpoint slice config controller") 105 106 if !cache.WaitForNamedCacheSync("endpoint slice config", stopCh, c.listerSynced) { 107 return 108 } 109 110 for _, h := range c.eventHandlers { 111 c.logger.V(3).Info("Calling handler.OnEndpointSlicesSynced()") 112 h.OnEndpointSlicesSynced() 113 } 114 } 115 116 func (c *EndpointSliceConfig) handleAddEndpointSlice(obj interface{}) { 117 endpointSlice, ok := obj.(*discoveryv1.EndpointSlice) 118 if !ok { 119 utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj)) 120 return 121 } 122 for _, h := range c.eventHandlers { 123 c.logger.V(4).Info("Calling handler.OnEndpointSliceAdd", "endpoints", klog.KObj(endpointSlice)) 124 h.OnEndpointSliceAdd(endpointSlice) 125 } 126 } 127 128 func (c *EndpointSliceConfig) handleUpdateEndpointSlice(oldObj, newObj interface{}) { 129 oldEndpointSlice, ok := oldObj.(*discoveryv1.EndpointSlice) 130 if !ok { 131 utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", newObj)) 132 return 133 } 134 newEndpointSlice, ok := newObj.(*discoveryv1.EndpointSlice) 135 if !ok { 136 utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", newObj)) 137 return 138 } 139 for _, h := range c.eventHandlers { 140 c.logger.V(4).Info("Calling handler.OnEndpointSliceUpdate") 141 h.OnEndpointSliceUpdate(oldEndpointSlice, newEndpointSlice) 142 } 143 } 144 145 func (c *EndpointSliceConfig) handleDeleteEndpointSlice(obj interface{}) { 146 endpointSlice, ok := obj.(*discoveryv1.EndpointSlice) 147 if !ok { 148 tombstone, ok := obj.(cache.DeletedFinalStateUnknown) 149 if !ok { 150 utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj)) 151 return 152 } 153 if endpointSlice, ok = tombstone.Obj.(*discoveryv1.EndpointSlice); !ok { 154 utilruntime.HandleError(fmt.Errorf("unexpected object type: %T", obj)) 155 return 156 } 157 } 158 for _, h := range c.eventHandlers { 159 c.logger.V(4).Info("Calling handler.OnEndpointsDelete") 160 h.OnEndpointSliceDelete(endpointSlice) 161 } 162 } 163 164 // ServiceConfig tracks a set of service configurations. 165 type ServiceConfig struct { 166 listerSynced cache.InformerSynced 167 eventHandlers []ServiceHandler 168 logger klog.Logger 169 } 170 171 // NewServiceConfig creates a new ServiceConfig. 172 func NewServiceConfig(ctx context.Context, serviceInformer v1informers.ServiceInformer, resyncPeriod time.Duration) *ServiceConfig { 173 result := &ServiceConfig{ 174 listerSynced: serviceInformer.Informer().HasSynced, 175 logger: klog.FromContext(ctx), 176 } 177 178 _, _ = serviceInformer.Informer().AddEventHandlerWithResyncPeriod( 179 cache.ResourceEventHandlerFuncs{ 180 AddFunc: result.handleAddService, 181 UpdateFunc: result.handleUpdateService, 182 DeleteFunc: result.handleDeleteService, 183 }, 184 resyncPeriod, 185 ) 186 187 return result 188 } 189 190 // RegisterEventHandler registers a handler which is called on every service change. 191 func (c *ServiceConfig) RegisterEventHandler(handler ServiceHandler) { 192 c.eventHandlers = append(c.eventHandlers, handler) 193 } 194 195 // Run waits for cache synced and invokes handlers after syncing. 196 func (c *ServiceConfig) Run(stopCh <-chan struct{}) { 197 c.logger.Info("Starting service config controller") 198 199 if !cache.WaitForNamedCacheSync("service config", stopCh, c.listerSynced) { 200 return 201 } 202 203 for i := range c.eventHandlers { 204 c.logger.V(3).Info("Calling handler.OnServiceSynced()") 205 c.eventHandlers[i].OnServiceSynced() 206 } 207 } 208 209 func (c *ServiceConfig) handleAddService(obj interface{}) { 210 service, ok := obj.(*v1.Service) 211 if !ok { 212 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 213 return 214 } 215 for i := range c.eventHandlers { 216 c.logger.V(4).Info("Calling handler.OnServiceAdd") 217 c.eventHandlers[i].OnServiceAdd(service) 218 } 219 } 220 221 func (c *ServiceConfig) handleUpdateService(oldObj, newObj interface{}) { 222 oldService, ok := oldObj.(*v1.Service) 223 if !ok { 224 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", oldObj)) 225 return 226 } 227 service, ok := newObj.(*v1.Service) 228 if !ok { 229 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj)) 230 return 231 } 232 for i := range c.eventHandlers { 233 c.logger.V(4).Info("Calling handler.OnServiceUpdate") 234 c.eventHandlers[i].OnServiceUpdate(oldService, service) 235 } 236 } 237 238 func (c *ServiceConfig) handleDeleteService(obj interface{}) { 239 service, ok := obj.(*v1.Service) 240 if !ok { 241 tombstone, ok := obj.(cache.DeletedFinalStateUnknown) 242 if !ok { 243 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 244 return 245 } 246 if service, ok = tombstone.Obj.(*v1.Service); !ok { 247 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 248 return 249 } 250 } 251 for i := range c.eventHandlers { 252 c.logger.V(4).Info("Calling handler.OnServiceDelete") 253 c.eventHandlers[i].OnServiceDelete(service) 254 } 255 } 256 257 // NodeHandler is an abstract interface of objects which receive 258 // notifications about node object changes. 259 type NodeHandler interface { 260 // OnNodeAdd is called whenever creation of new node object 261 // is observed. 262 OnNodeAdd(node *v1.Node) 263 // OnNodeUpdate is called whenever modification of an existing 264 // node object is observed. 265 OnNodeUpdate(oldNode, node *v1.Node) 266 // OnNodeDelete is called whenever deletion of an existing node 267 // object is observed. 268 OnNodeDelete(node *v1.Node) 269 // OnNodeSynced is called once all the initial event handlers were 270 // called and the state is fully propagated to local cache. 271 OnNodeSynced() 272 } 273 274 // NoopNodeHandler is a noop handler for proxiers that have not yet 275 // implemented a full NodeHandler. 276 type NoopNodeHandler struct{} 277 278 // OnNodeAdd is a noop handler for Node creates. 279 func (*NoopNodeHandler) OnNodeAdd(node *v1.Node) {} 280 281 // OnNodeUpdate is a noop handler for Node updates. 282 func (*NoopNodeHandler) OnNodeUpdate(oldNode, node *v1.Node) {} 283 284 // OnNodeDelete is a noop handler for Node deletes. 285 func (*NoopNodeHandler) OnNodeDelete(node *v1.Node) {} 286 287 // OnNodeSynced is a noop handler for Node syncs. 288 func (*NoopNodeHandler) OnNodeSynced() {} 289 290 var _ NodeHandler = &NoopNodeHandler{} 291 292 // NodeConfig tracks a set of node configurations. 293 // It accepts "set", "add" and "remove" operations of node via channels, and invokes registered handlers on change. 294 type NodeConfig struct { 295 listerSynced cache.InformerSynced 296 eventHandlers []NodeHandler 297 logger klog.Logger 298 } 299 300 // NewNodeConfig creates a new NodeConfig. 301 func NewNodeConfig(ctx context.Context, nodeInformer v1informers.NodeInformer, resyncPeriod time.Duration) *NodeConfig { 302 result := &NodeConfig{ 303 listerSynced: nodeInformer.Informer().HasSynced, 304 logger: klog.FromContext(ctx), 305 } 306 307 _, _ = nodeInformer.Informer().AddEventHandlerWithResyncPeriod( 308 cache.ResourceEventHandlerFuncs{ 309 AddFunc: result.handleAddNode, 310 UpdateFunc: result.handleUpdateNode, 311 DeleteFunc: result.handleDeleteNode, 312 }, 313 resyncPeriod, 314 ) 315 316 return result 317 } 318 319 // RegisterEventHandler registers a handler which is called on every node change. 320 func (c *NodeConfig) RegisterEventHandler(handler NodeHandler) { 321 c.eventHandlers = append(c.eventHandlers, handler) 322 } 323 324 // Run starts the goroutine responsible for calling registered handlers. 325 func (c *NodeConfig) Run(stopCh <-chan struct{}) { 326 c.logger.Info("Starting node config controller") 327 328 if !cache.WaitForNamedCacheSync("node config", stopCh, c.listerSynced) { 329 return 330 } 331 332 for i := range c.eventHandlers { 333 c.logger.V(3).Info("Calling handler.OnNodeSynced()") 334 c.eventHandlers[i].OnNodeSynced() 335 } 336 } 337 338 func (c *NodeConfig) handleAddNode(obj interface{}) { 339 node, ok := obj.(*v1.Node) 340 if !ok { 341 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 342 return 343 } 344 for i := range c.eventHandlers { 345 c.logger.V(4).Info("Calling handler.OnNodeAdd") 346 c.eventHandlers[i].OnNodeAdd(node) 347 } 348 } 349 350 func (c *NodeConfig) handleUpdateNode(oldObj, newObj interface{}) { 351 oldNode, ok := oldObj.(*v1.Node) 352 if !ok { 353 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", oldObj)) 354 return 355 } 356 node, ok := newObj.(*v1.Node) 357 if !ok { 358 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj)) 359 return 360 } 361 for i := range c.eventHandlers { 362 c.logger.V(5).Info("Calling handler.OnNodeUpdate") 363 c.eventHandlers[i].OnNodeUpdate(oldNode, node) 364 } 365 } 366 367 func (c *NodeConfig) handleDeleteNode(obj interface{}) { 368 node, ok := obj.(*v1.Node) 369 if !ok { 370 tombstone, ok := obj.(cache.DeletedFinalStateUnknown) 371 if !ok { 372 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 373 return 374 } 375 if node, ok = tombstone.Obj.(*v1.Node); !ok { 376 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", obj)) 377 return 378 } 379 } 380 for i := range c.eventHandlers { 381 c.logger.V(4).Info("Calling handler.OnNodeDelete") 382 c.eventHandlers[i].OnNodeDelete(node) 383 } 384 } 385 386 // ServiceCIDRHandler is an abstract interface of objects which receive 387 // notifications about ServiceCIDR object changes. 388 type ServiceCIDRHandler interface { 389 // OnServiceCIDRsChanged is called whenever a change is observed 390 // in any of the ServiceCIDRs, and provides complete list of service cidrs. 391 OnServiceCIDRsChanged(cidrs []string) 392 } 393 394 // ServiceCIDRConfig tracks a set of service configurations. 395 type ServiceCIDRConfig struct { 396 listerSynced cache.InformerSynced 397 eventHandlers []ServiceCIDRHandler 398 mu sync.Mutex 399 cidrs sets.Set[string] 400 logger klog.Logger 401 } 402 403 // NewServiceCIDRConfig creates a new ServiceCIDRConfig. 404 func NewServiceCIDRConfig(ctx context.Context, serviceCIDRInformer networkingv1alpha1informers.ServiceCIDRInformer, resyncPeriod time.Duration) *ServiceCIDRConfig { 405 result := &ServiceCIDRConfig{ 406 listerSynced: serviceCIDRInformer.Informer().HasSynced, 407 cidrs: sets.New[string](), 408 logger: klog.FromContext(ctx), 409 } 410 411 _, _ = serviceCIDRInformer.Informer().AddEventHandlerWithResyncPeriod( 412 cache.ResourceEventHandlerFuncs{ 413 AddFunc: func(obj interface{}) { 414 result.handleServiceCIDREvent(nil, obj) 415 }, 416 UpdateFunc: func(oldObj, newObj interface{}) { 417 result.handleServiceCIDREvent(oldObj, newObj) 418 }, 419 DeleteFunc: func(obj interface{}) { 420 result.handleServiceCIDREvent(obj, nil) 421 }, 422 }, 423 resyncPeriod, 424 ) 425 return result 426 } 427 428 // RegisterEventHandler registers a handler which is called on every ServiceCIDR change. 429 func (c *ServiceCIDRConfig) RegisterEventHandler(handler ServiceCIDRHandler) { 430 c.eventHandlers = append(c.eventHandlers, handler) 431 } 432 433 // Run waits for cache synced and invokes handlers after syncing. 434 func (c *ServiceCIDRConfig) Run(stopCh <-chan struct{}) { 435 c.logger.Info("Starting serviceCIDR config controller") 436 437 if !cache.WaitForNamedCacheSync("serviceCIDR config", stopCh, c.listerSynced) { 438 return 439 } 440 c.handleServiceCIDREvent(nil, nil) 441 } 442 443 // handleServiceCIDREvent is a helper function to handle Add, Update and Delete 444 // events on ServiceCIDR objects and call downstream event handlers. 445 func (c *ServiceCIDRConfig) handleServiceCIDREvent(oldObj, newObj interface{}) { 446 var oldServiceCIDR, newServiceCIDR *networkingv1alpha1.ServiceCIDR 447 var ok bool 448 449 if oldObj != nil { 450 oldServiceCIDR, ok = oldObj.(*networkingv1alpha1.ServiceCIDR) 451 if !ok { 452 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", oldObj)) 453 return 454 } 455 } 456 457 if newObj != nil { 458 newServiceCIDR, ok = newObj.(*networkingv1alpha1.ServiceCIDR) 459 if !ok { 460 utilruntime.HandleError(fmt.Errorf("unexpected object type: %v", newObj)) 461 return 462 } 463 } 464 465 c.mu.Lock() 466 defer c.mu.Unlock() 467 468 if oldServiceCIDR != nil { 469 c.cidrs.Delete(oldServiceCIDR.Spec.CIDRs...) 470 } 471 472 if newServiceCIDR != nil { 473 c.cidrs.Insert(newServiceCIDR.Spec.CIDRs...) 474 } 475 476 for i := range c.eventHandlers { 477 c.logger.V(4).Info("Calling handler.OnServiceCIDRsChanged") 478 c.eventHandlers[i].OnServiceCIDRsChanged(c.cidrs.UnsortedList()) 479 } 480 }