Further in the documentation, Controller and Operator definitions are used as synonymous.
Let's take an example of some controller like Kerberos principal list, which needs to be propagated to KDC database.
Using Custom Resource option, our target Custom Resource will look like this:
Freya does not require to write YAML files for your custom resources definitions, nor for customer resource instances and ConfigMaps at all. CRD in K8s will be created automatically based on case classes you define.
For the sake of example, we are not going to create any container with Kerberos server running in it, but just showing how Freya can help to watch our custom resources or ConfigMaps. Particular controller actions to be implemented by controller author using fabric8 kubernetes-client. Freya is only a facilitator between K8s api-server and your custom controller actions.
There are 3 steps to implement a CRD Operator:
Above Kerberos spec can be designed as two case classes
According to Kubernetes API, every custom resource may have optional property
status. In order to model
status, we will define one more case class. Name and properties of this class can be anything. Basically,
it can define its own hierarchy of case classes.
freya.Controller abstract class:
type NewStatus[U] = Option[U]
All methods have default implementation as
F.unit, so override only necessary methods for your custom controller.
onInit - is called before controller is started. In terms fabric8 client, onInit is called before watcher
is started to watch for custom resources or ConfigMap resources.
onModify - are called whenever corresponding event is triggered by Kubernetes api-server.
onModify - allows to set new custom resource status by returning a value of
F[Option[U]] in these methods.
U is a type of status case class.
run method returns an
IO[ExitCode], which is running a web-socket connection to Kubernetes api-server.
IO value is a long-running and server-like task, which terminates only if K8s api-server closes client
connection. Running Operator is watching for events:
- for customer resources with
Kerbkind and apiGroup
io.myorg.kerboperator/v1, in case of CRD Operator
- for ConfigMap kind with label
io.myorg.kerboperator/kind=Kerb, in case of ConfigMap Operator
Freya dispatches api-server events concurrently accross different namespaces, but in original order within the same namespace. Supplied controller will be called concurrently, thus any state variables of the controller needs to be thread-safe or atomic. In order to use single-threaded dispatch, one can set
Concurrent dispatching is maintaining in-memory queues per namespace to buffer received events for a short time. These events are dispatched one by one to the controller.
Freya can automatically restart your operator in case of any failure during the CRs/ConfigMaps event listening. In terms Cats-Effect IO, once IO task is completed, which means Freya Operator has exited from its normal listening process, it will be restarted with the same parameters. There are few options to control restart behaviour.
Infinite type will restart operator infinitely making random delay between retries within
[minDelay, maxDelay) time range.
Above configuration will lead to the following delay in seconds: 2, 4 and 8.
multiplier is used to
calculate next delay by
previous delay * multiplier.
In order to disable automatic deployment of Custom Resource Definition as well as OpenAPi schema, one can
set false in
freya.Configuration.CrdConfig.deployCrd = false. Operator will expect to find a CRD in K8s during the startup, it
won't try to deploy new CRD, even if CRD is not found. However, what may happen in case CRD is not found and
false, then operator will fail and return failed
IO value immediately. Freya Operator can't work without CRD being
retrieved from K8s api-server.
Manual deployment of CRD is usually done with YAML files using tools like
Both types of controllers can be constructed using helper as input parameter. Helper has several useful properties and method to retrieve current resources for CRD or ConfigMap kinds. Although, the same functionality can be written within Operator code manually.
CrdHelper provides several properties such as:
freya.Configuration.CrdConfig- configuration which is passed on operator construction
io.fabric8.kubernetes.client.KubernetesClient- K8s client
Option[Boolean]- isOpenShift property
io.fabric8.kubernetes.api.model.apiextensions.CustomResourceDefinition- custom resource definition object
freya.resource.CrdParser- CR parser to parse