Documentation ¶
Overview ¶
Package dynamiccontroller provides a flexible and efficient solution for managing multiple GroupVersionResources (GVRs) in a Kubernetes environment. It implements a single controller capable of dynamically handling various resource types concurrently, adapting to runtime changes without system restarts.
Key features and design considerations:
Multi GVR management: It handles multiple resource types concurrently, creating and managing separate workflows for each.
Dynamic informer management: Creates and deletes informers on the fly for new resource types, allowing real time adaptation to changes in the cluster.
Minimal disruption: Operations on one resource type do not affect the performance or functionality of others.
Minimalism: Unlike controller-runtime, this implementation is tailored specifically for kro's needs, avoiding unnecessary dependencies and overhead.
Future Extensibility: It allows for future enhancements such as sharding and CEL cost aware leader election, which are not readily achievable with k8s.io/controller-runtime.
Why not use k8s.io/controller-runtime:
Staticc nature: controller-runtime is optimized for statically defined controllers, however kro requires runtime creation and management of controllers for various GVRs.
Overhead reduction: by not including unused features like leader election and certain metrics, this implementation remains minimalistic and efficient.
Customization: this design allows for deep customization and optimization specific to kro's unique requirements for managing multiple GVRs dynamically.
This implementation aims to provide a reusable, efficient, and flexible solution for dynamic multi-GVR controller management in Kubernetes environments.
NOTE(a-hilaly): Potentially we might open source this package for broader use cases.
Index ¶
- type Config
- type DynamicController
- func (dc *DynamicController) AllInformerHaveSynced() bool
- func (dc *DynamicController) Run(ctx context.Context) error
- func (dc *DynamicController) StartServingGVK(ctx context.Context, gvr schema.GroupVersionResource, handler Handler) error
- func (dc *DynamicController) StopServiceGVK(ctx context.Context, gvr schema.GroupVersionResource) error
- func (dc *DynamicController) WaitForInformersSync(stopCh <-chan struct{}) bool
- type Handler
- type ObjectIdentifiers
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct { // Workers specifies the number of workers processing items from the queue Workers int // ResyncPeriod defines the interval at which the controller will re list // the resources, even if there haven't been any changes. ResyncPeriod time.Duration // QueueMaxRetries is the maximum number of retries for an item in the queue // will be retried before being dropped. // // NOTE(a-hilaly): I'm not very sure how useful is this, i'm trying to avoid // situations where reconcile errors exauhst the queue. QueueMaxRetries int // ShutdownTimeout is the maximum duration to wait for the controller to // gracefully shutdown. We ideally want to avoid forceful shutdowns, giving // the controller enough time to finish processing any pending items. ShutdownTimeout time.Duration }
Config holds the configuration for DynamicController
type DynamicController ¶
type DynamicController struct {
// contains filtered or unexported fields
}
DynamicController (DC) is a single controller capable of managing multiple different kubernetes resources (GVRs) in parallel. It can safely start watching new resources and stop watching others at runtime - hence the term "dynamic". This flexibility allows us to accept and manage various resources in a Kubernetes cluster without requiring restarts or pod redeployments.
It is mainly inspired by native Kubernetes controllers but designed for more flexible and lightweight operation. DC serves as the core component of kro's dynamic resource management system. Its primary purpose is to create and manage "micro" controllers for custom resources defined by users at runtime (via the ResourceGroup CRs).
func NewDynamicController ¶
func NewDynamicController( log logr.Logger, config Config, kubeClient dynamic.Interface, ) *DynamicController
NewDynamicController creates a new DynamicController instance.
func (*DynamicController) AllInformerHaveSynced ¶
func (dc *DynamicController) AllInformerHaveSynced() bool
AllInformerHaveSynced checks if all registered informers have synced, returns true if they have.
func (*DynamicController) Run ¶
func (dc *DynamicController) Run(ctx context.Context) error
Run starts the DynamicController.
func (*DynamicController) StartServingGVK ¶
func (dc *DynamicController) StartServingGVK(ctx context.Context, gvr schema.GroupVersionResource, handler Handler) error
StartServingGVK registers a new GVK to the informers map safely.
func (*DynamicController) StopServiceGVK ¶
func (dc *DynamicController) StopServiceGVK(ctx context.Context, gvr schema.GroupVersionResource) error
UnregisterGVK safely removes a GVK from the controller and cleans up associated resources.
func (*DynamicController) WaitForInformersSync ¶
func (dc *DynamicController) WaitForInformersSync(stopCh <-chan struct{}) bool
WaitForInformerSync waits for all informers to sync or timeout
type ObjectIdentifiers ¶
type ObjectIdentifiers struct { // NamespacedKey is the namespaced key of the object. Typically in the format // `namespace/name`. NamespacedKey string GVR schema.GroupVersionResource }
ObjectIdentifiers is a struct that holds the namespaced key and the GVR of the object.
Since we are handling all the resources using the same handlerFunc, we need to know what GVR we're dealing with - so that we can use the appropriate workflow operator.