I have always wanted to create a Kubernetes operator with the operator framework and tried to give that a go on my Windows 10 system. Note that the emphasis is on creating an operator, not necessarily writing a useful one 😁. All I am doing is using the boilerplate that is generated by the framework. If you have never even seen how this is done, then this post if for you. 👍
An operator is an application-specific controller. A controller is a piece of software that implements a control loop, watching the state of the Kubernetes cluster via the API. It makes changes to the state to drive it towards the desired state.
An operator uses Kubernetes to create and manage complex applications. Many operators can be found here: https://operatorhub.io/. The Cassandra operator for instance, has domain-specific knowledge embedded in it, that knows how to deploy and configure this database. That’s great because that means some of the burden is shifted from you to the operator.
Installation
I installed the Operator SDK CLI from the GitHub releases in WSL, Windows Subsystem for Linux. I am using WSL 1, not WSL 2 as I am not running a Windows Insiders release. The commands to run:
RELEASE_VERSION=v0.13.0 curl -LO https://github.com/operator-framework/operator-sdk/releases/download/${RELEASE_VERSION}/operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu chmod +x operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu && sudo mkdir -p /usr/local/bin/ && sudo cp operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu /usr/local/bin/operator-sdk && rm operator-sdk-${RELEASE_VERSION}-x86_64-linux-gnu
You should now be able to run operator-sdk in WSL 1.
Creating an operator
In WSL, you should have installed Go. I am using version 1.13.5. Although not required, I used my Go path on Windows to generate the operator and not the %GOPATH set in WSL. My working directory was:
/mnt/c/Users/geert/go/src/github.com/baeke.info
To create the operator, I ran the following commands (one line):
export GO111MODULE=on operator-sdk new fun-operator --repo github.com/baeke.info/fun-operator
This creates a folder, fun-operator, under baeke.info and sets up the project:

Before continuing, cd into fun-operator and run go mod tidy. Now we can run the following command:
operator-sdk add api --api-version=fun.baeke.info/v1alpha1 --kind FunOp
This creates a new CRD (Custom Resource Definition) API called FunOp. The API version is fun.baeke.info/v1alpha1 which you choose yourself. With the above you can create CRDs like below that the operator acts upon:
apiVersion: fun.baeke.info/v1alpha1 kind: FunOp metadata: name: example-funop
Now we can add a controller that watches for the above CRD resource:
operator-sdk add controller --api-version=fun.baeke.info/v1alpha1 --kind=FunOp
The above will generate a file, funop_controller.go, that contains some boilerplate code that creates a busybox pod. The Reconcile function is responsible for doing this work:

As stated above, I will just use the boilerplate code and build the project:
operator-sdk build gbaeke/fun-operator
In WSL 1, you cannot run Docker so the above command will build the operator from the Go code but fail while building the container image. Can’t wait for WSL 2! The build creates the following artifact:

The supplied Dockerfile can be used to build the container images in Windows. In Windows, copy the Dockerfile from the build folder to the root of the operator project (in my case C:\Users\geert\go\src\github.com\baeke.info\fun-operator) and run docker build and push:
docker build -t gbaeke/fun-operator . docker push gbaeke/fun-operator
Deploying the operator
The project folder structure contains a bunch of yaml in the deploy folder:

The service account, role and role binding make sure your code can create (or delete/update) resources in the cluster. The operator.yaml actually deploys the operator on your cluster. You just need to update the container spec with the name of your image (here gbaeke/fun-operator).
Before you deploy the operator, make sure you deploy the CRD manifest (here fun.baeke.info_funops_crd.yaml).
As always, just use kubectl apply -f with the above YAML files.
Testing the operator
With the operator deployed, create a resource based on the CRD. For instance:
apiVersion: fun.baeke.info/v1alpha1 kind: FunOp metadata: name: example-funop
From the moment you create this resource with kubectl apply, a pod will be created by the operator.

When you delete example-funop, the pod will be removed by the operator.
That’s it! We created a Kubernetes operator with the boilerplate code supplied by the operator-sdk cli. Another time, maybe we’ll create an operator that actually does something useful! 😉