Go operator

18. Jun 2019

use create

deploy step by step our operators.
For this SDK supported workflow, we provide:

a) a description of the generated Operator structure (there is one for each specific workflow);

b) a link to our example(s) of operator(s) based on such Operator structure (there is one for each specific workflow) and logic.

c) descriptions on how to add (e.g., 3rd party) resources, different from the Core Kubernetes resource types, to your Operator 

d) a description of the main pros and cons of using such Operator structure (there is one for each specific workflow) and logic.

a) Description of the generated Operator structure (there is one for each specific workflow)

As follows the structure of a generated GO operator:

Contains manager/main.go which is the main program of the operator. This instantiates a new manager which registers all custom resource definitions under pkg/apis/... and starts all controllers under pkg/controllers/... .
Contains the directory tree that defines the APIs of the Custom Resource Definitions (CRD). Users are expected to edit the pkg/apis/<group>/<version>/<kind>_types.go files to define the API for each resource type and import these packages in their controllers to watch for these resource types.
This pkg contains the controller implementations. Users are expected to edit the pkg/controller/<kind>/<kind>_controller.go to define the controller’s reconcile logic for handling a resource type of the specified kind.
Contains the Dockerfile and build scripts used to build the operator.
Contains various YAML manifests for registering CRDs, setting up RBAC, and deploying the operator as a Deployment.
Gopkg.toml Gopkg.lock
The Go Dep manifests that describe the external dependencies of this operator.
The golang vendor folder that contains the local copies of the external dependencies that satisfy the imports of this project. Go Dep manages the vendor directly.

Operator scope

A namespace-scoped operator (the default) watches and manages resources in a single namespace, whereas a cluster-scoped operator watches and manages resources cluster-wide. Namespace-scoped operators are preferred because of their flexibility. They enable decoupled upgrades, namespace isolation for failures and monitoring, and differing API definitions. However, there are use cases where a cluster-scoped operator may make sense. For example, the cert-manager operator is often deployed with cluster-scoped permissions and watches so that it can manage issuing certificates for an entire cluster.

b) Example of operator(s) based on such Operator structure (there is one for each specific workflow) and logic.

We will discuss two examples of GO Operator: 
1) Example 1: this operator just replicates itself under a certain project: 
2) Example 2: this operator allows to manipulate the number of pods in a project.

c) How to add 3rd Party Resources (i.e., different from the Core Kubernetes resource types) to your Operator

The operators manager supports the Core Kubernetes resource types as found in the client-go scheme (“register.go“) package and will also register the schemes of all custom resource types defined in your project under pkg/apis

import (
// Setup Scheme for all resources
if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
  log.Error(err, "")

To add a 3rd party resource to an operator, you must add it to the managers scheme. By creating an AddToSchememethod or reusing one you can easily add a resource to your scheme. An example shows that you define a function and then use the runtime package to create a SchemeBuilder.
Register with the managers scheme
Call the AddToScheme() function for your 3rd party resource and pass it the managers scheme via mgr.GetScheme().

import (
    routev1 ""
func main() {
    if err := routev1.AddToScheme(mgr.GetScheme()); err != nil {
      log.Error(err, "")

After adding new import paths to your operator project, run dep ensure in the root of your project directory to fulfill these dependencies”.

$ dep ensure

d) A description of the main pros and cons of using this Operator structure (there is one for each specific workflow) and logic;

PROS (+) AND CONS (-):

(+) it is easy to use and create a simple operator

The main program for the operator cmd/manager/main.go initializes and runs the manager. The manager will automatically register the scheme for all custom resources defined under pkg/apis/... and run all controllers under pkg/controller/....

The manager can restrict the namespace that all controllers will watch for resources:

mgr, err := manager.New(cfg, manager.Options{Namespace: namespace})

By default this will be the namespace that the operator is running in. To watch all namespaces leave the namespace option empty:

mgr, err := manager.New(cfg, manager.Options{Namespace: ""})

(+) enough clear way to add 3rd Party Resources (i.e., different from the Core Kubernetes resource types) to your Operator

(-) it is still unstable/changing the APIs and the future versions of it could be not supported (we are observing this evolution and update the blog post accordingly)

To make the operator working, we had to open some issues in Github, that was closed and classified as a bug):

(-) The workflow to create the GO operators appear a bit more complex/unclear (steps in red) that the one generated with Ansible and Helm (which require fewer steps):

  1. Create a new operator project using the SDK Command Line Interface (CLI)
  2. Define new resource APIs by adding Custom Resource Definitions (CRD)
  3. Define controllers to watch and reconcile resources
  4. Write the reconciling logic for your controller using the SDK and controller-runtime APIs
  5. Use the SDK CLI to build and generate the operator deployment manifests

Back to overview

Back to overview Section 3 – Examples of Supported Kubernetes Operator SDK workflows.


Contact us

Our team of experts is available for you. In case of emergency also 24/7.

Contact us