Operator Pattern: Kubernetes/Openshift

Abhishek koserwal
May 23, 2020 · 5 min read

In this post, we will understand the Operator Pattern, Kubernetes internals, and essentials concepts for building an operator.

In the real world, we can define Operators: as a person who operates on something (machine, equipment, process). Let’s say it works on a given task “X”. Kubernetes Operator also works to follow the same principles.

We can classify any operator qualities into three categories:

  • Observe
  • Analyze
  • Act

They observe the X work, analyze the state of X, and finally act based on the current state of X to reach the desired state. Which will make the operators task completed, once we attain the desired state.

Similar work/tasks are performed by Kubernetes Operators. It helps us to extend the Kubernetes API to allow custom functionality or behavior based on the needs of the consumer.

We can categories building cloud-native applications in two categories:

  1. Containerize Application: Running an application container within the Kubernetes control plane as a Pod. Performing some kind of Request/Response.
  2. Operator Pattern: This pattern allows you to capitalize on Kubernetes infra and uses for our benefits.
Figure 1: Containerize vs Operator

In the above Figure 1, the Operator acts like having an understanding of Kubernetes internals like Events and API. It allows us to execute custom logic and query Kubernetes API for modifying the state of resources. Before going deep into Operators we can build our understanding of the Kubernetes internals:

Kubernetes Architecture

Figure 2:Kubernetes Architecture

It implements multiple controllers in a single process that runs in the control plane as a replicated set of processes. It consists of controllers like Node Controller, Route Controller, Service Controller, Authorization Controller, etc. We will see in detail how the controller works internally in the Operator pattern.

As shown in Figure 3, we can see each resource defined within the Kubernetes Control Plane is defined as an API end-point. When you are using the kubectl CLI tool. You are interacting with the Kube API like

kubectl <verb> <resource>

For extending the Schema, we can define a Custom Resource Definition type and create instances (CR) to perform the desired task using a custom controller.

Figure 3: Kubernetes API Schema

In the above figure, we are creating an instance(“example-job”) of type: Job. This is managed by Job controller runtime which handles the creation of container which executes the defined arguments. We got an understanding of the core internals. Now we can explore the pattern

Operator Pattern

Operator = Customer Resource Definition + Custom Controller

Figure 4: Observe-Analyze-Act

In the case of Kubernetes Operator, the same qualities are followed

  • Observe: Events
  • Analyze: Current Vs Desired State
  • Act: Reconciler Loop

We can understand each in-depth:

Figure 5: Operator Pattern
  • Controller: Register the Custom Resource Definition and adds it to the Kubernetes API Schema, exposes a new API end-point for the CRD, added watchers for the namespace to observe, runs a process/loop i.e control loop for acting based on the desired change.
  • Watchers: Allows to observe the events for specific resources type.
  • Reconciler: Any modification to the CR is handled by the reconciliation loop. Requeue after conflict/error with an interval defined by the re-sync period.

Classification based on deployment type

  • Namespace scoped Operator
  • Cluster scoped Operator

For understanding read: namespace vs cluster scope operator

We have a customer resource for Kind: Memcached (Custom Resource). With a specification field size (defined as 3). In the case of any modification to the customer resource. For eg: size 3 to 4.

An event will be triggered which can be watched by configuring a Watcher(Observe) for the resource object: Memcached within the Custom Controller. The reconciliation loop consists of custom logic defined by us. which can be used to compares the current (size: 3) vs desired (size: 4) & make the desired action.

Example Operator Workflow

Figure 6: example workflow
  • Defines a namespace(namespace-scoped) for our controller
  • Creates the CRD: ToDo.
  • The controller analyzes the CRD and adds it to the Kubernetes API Schema, exposes a new API end-point for the CRD, added watchers for kind CRD type.
  • Now our controller is in the running state. It watches the namespace for any changes.
  • Creating an instance of the CRD, by creating a Custome Resource object (CR) [Manual step]
  • When a CR object is created. it triggers an event that gives control to the Reconciler loop.
  • Reconcile reads that state of the cluster for a Custom object and makes changes based on the desired state.
  • In this case, it will create a Pod for the desired ToDo resource or any custom logic we intend for this operator

Example: https://github.com/operator-framework/getting-started

In conclusion, the above workflow is applicable to any operator. Except for the last point where creating a pod is a custom logic defined in the reconciler loop. Operator-Framework can be used to generate an operator and which provides high-level APIs, useful abstractions, and project scaffolding. Currently only support: Helm, Ansible & Go lang based operators. You can design operators in any preferred language using the Kubernetes client libraries with a combination of the helm charts. The following links will help to get started with operators.

Thank you for reading this article. If you like this post, please give a Cheer!!! Follow the Collection: operators for learning more…

Happy Coding ❤

Operators

Kubernetes/Openshift Operators