The controller-framework is a versatile Golang module designed to facilitate the creation of robust and feature-rich Kubernetes controllers. This framework offers a straightforward approach to building controllers with essential functionalities, including graceful shutdown handling, informer synchronization, and work queue management. Contrasted with the controller-runtime library, the controller-framework prioritizes simplicity and flexibility, making it an ideal choice for crafting controllers that closely resemble the traditional ones used within the Kubernetes project.
Graceful Shutdown: The Controller Framework ensures a smooth and graceful shutdown of your controllers. It allows ongoing workers to finalize and resources to be managed appropriately before the controller terminates.
Informer Synchronization: Easily synchronize informers with the controller-framework, enabling seamless tracking and reaction to changes in Kubernetes resources. The module abstracts the complexity of informer cache synchronization.
Workqueue Management: The framework streamlines work queue management, allowing tasks to be efficiently queued and processed. It handles retries and back-off strategies for any failed tasks, promoting reliability.
Simplicity and Flexibility: Prioritizing simplicity, the controller-framework minimizes boilerplate code, empowering developers to focus on implementing the core logic of their controllers.
Familiar Kubernetes Controller Paradigm: Controllers created using this framework mirror the established structure and design principles of traditional Kubernetes controllers. Developers familiar with Kubernetes controller development will find it intuitive to work with this framework.
The original location for this framework is OpenShift library-go repository and this framework is used as controller framework for all OpenShift control plane operators. It has been proven stable, reliable and with minimum issues for multiple OpenShift releases.
Start to integrate the controller framework into your Golang project by using factory Go modules:
import "github.com/mfojtik/controller-framework/pkg/factory"The factory provide a builder that produce all Kubernetes controller boilerplate. To learn how flexible it is, read the documentation
funcNew() framework.controller {
returnfactory.New().ToController("new-controller", eventRecorder) }You can access the workqueue inside the sync() function via the controller context.
func (c*controller) sync(ctx context.Context, syncCtx framework.Context) error {
syncCtx.Recorder().Eventf(...)
syncCtx.Queue().Add("key")
}And finally, for Kubernetes Event management, you can use included Event Recorder which offers various backends for storing events (filesystem, Kubernetes Events, in-memory events, etc.)
...recorder:=events.NewRecorder(client.CoreV1().Events("test-namespace"), "test-operator", controllerRef)
...Utilizing the controller framework is straightforward. Here's a simple example showcasing how to create a controller:
// simple_controller.go:package simple
import (
"context""errors""os""time""github.com/mfojtik/controller-framework/pkg/events""github.com/mfojtik/controller-framework/pkg/factory""github.com/mfojtik/controller-framework/pkg/framework"
)
typecontrollerstruct {}
funcNew(recorder events.Recorder) framework.Controller {
c:=&controller{}
returnfactory.New().
WithSync(c.sync). // reconcile function// WithInformers(secretInformer) // react to secretInformer changesResyncEvery(10*time.Second). // queue sync() every 10s regardless of informersToController("simple", recorder)
}
func (c*controller) sync(ctx context.Context, controllerContext framework.Context) error {
// do stuff_, err:=os.ReadFile("/etc/cert.pem")
iferrors.Is(err, os.ErrNotExist) {
// controller will requeue and retryreturnerrors.New("file not found")
}
returnnil
}
// main.go:funcmain() {
// the controllerRef is an Kubernetes ownerReference to an object the events will tied to (a pod, namespace, etc)recorder:=events.NewRecorder(client.CoreV1().Events("test-namespace"), "test-operator", controllerRef)
controller:=simple.New(recorder)
// when this context is done, the controllers will gracefully shutddownctx:=context.Background()
// start the controller with one workergocontroller.Run(ctx, 1)
...
}Check the Examples for more controller examples.
Contributions to the controller-framework are welcomed! Feel free to submit issues and pull requests via the GitHub repository.
The Controller Framework is distributed under the Apache v2 License. Refer to the LICENSE file for more details.