Press "Enter" to skip to content

Hacking a Controller for OpenShift/Kubernetes, Pt. 3

Part 1: Introduction to the OpenShift client
Part 2: Coding for Kubernetes

In the previous post, I went more in-depth into how Kubernetes works in the command line. For this post, let’s step back to the code from Part 1 of this series and modify it to run continuously, showing the list of pods currently in the cluster and updating every time a new pod is created.

The Watch Interface

Kubernetes’ Watch interface provides the ability to listen for several different types of events in the cluster. Using the channel functionality built into Go, this is perfect for us to set up an asynchronous controller that can run continuously. First we need to update our code to take advantage of channels. Go back to the code we had in Part 1 and change the main() function in your cmd/controller/cmd.go file to look like this:

What we’ve done is created a channel that will be used to safely send “stop” signals to our Go routines when the program ends, and passed that channel to our Run() function. Now, update your pkg/controller/controller.go file to look like this:

What we’ve done here is change our Run() function to:

  • [41] Accept our stop channel as a parameter
  • [43] Spawn a Go routine that will run continuously using Kubernetes’ wait.Until() function
  • [45] Create a Watch Interface using the Kubernetes client to listen for pods in all namespaces
  • [56] Listen for events over the Watch Interface’s result channel inside a select statement.
  • [73-78] Process the event for the object type expected (in this case “pod”, but we could handle events for multiple types of objects) and print metadata about that event and the relevant resource object.

Deploy any simple app on your running and configured OpenShift cluster, then build and run your controller. You should see output similar to this:

(Your output will obviously vary based on the app you use. I just used the sample Ruby hello world app.)

These events show up because, when starting up, a Watch Interface will receive ADDED events for all currently running pods. If I leave the controller running and, in another terminal, delete my ruby-hello-world pod, I see this output added:

So you can see how different interactions on your cluster can trigger different types of events.

Note that the OpenShift 3.3 client package includes easy access to Watch Interfaces for several additional types, such as Projects.

Fun: Cumulative Runtimes

As an exercise, let’s modify our controller to keep track of the cumulative runtime of all the pods for each namespace. Update your pkg/controller/controller.go file to change your ProcessEvent() function and add a new function, TimeSince(), like so:

Now, whenever a new pod event is received (such as adding or deleting), we’ll trigger a client call to gather a list of all the running pods in the relevant namespace. From the CreationTimestamp of each pod, we use the time.Since() method to calculate how long it’s been running in minutes. From there it’s just a matter of summing up all the runtimes we’ve calculated. When you run it, the output should be similar to this:

Try scaling the pods in a project up or down, and see how it triggers a new calculation each time. This is a very simple example, but hopefully it’s enough to get you on your way writing your own controllers for OpenShift!

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *