I’ve been learning about Kubernetes recently, a computer program used by software engineers to make large, complex, websites available to customers.

To make it easier to understand what Kubernetes does and how it works, let’s digress and talk about food for a minute.

In order for a restaurant to work well during rush hour, the employees have a set of methods and tools they use. Each table has a number assigned to it, the kitchenware is organized in a specific way, a machine keeps the plates warm, another machine makes payments with a debit card quick and easy. These methods and tools are separate from the food itself, of course, but they help deliver the food in the best possible conditions.

Drawing of a restaurant with a customer at a table, a checkout counter and the kitchen in the background

Kubernetes has a similar role for software engineering teams, it helps deliver software. When a new version of a software is ready, software engineers use Kubernetes to make it available to customers. Kubernetes brings with it a set of guidelines that make it easy to collaborate on large software projects.

Although Kubernetes may be overkill for some smaller projects, it can be very useful when a software is expected to grow in scope and complexity. In fact, you have most likely been on a website recently that uses Kubernetes behind the scenes, it’s a tool used by more and more companies.

The two main components in Kubernetes

Kubernetes is actually not a single program but the name for multiple computer programs that work together so as to provide a large number of software development tools.

From a bird’s eye view, there are two main components: the controlplane and the worker nodes.

The controlplane is kind of like a manager and the worker nodes are their team. The controlplane knows what work needs to be done and distributes it to worker nodes.

Drawing of head chef (aka controlplane) distributing work to kitchen assistants (aka worker nodes)


If we zoom in to the controlplane, we can see that it accomplishes a large number of tasks.

When a request from a software engineer comes in, a controlplane component called kube-apiserver steps in handles it. The kube-apiserver also takes appropriate action when a worker nodes no longer works.

The controlplane decides what part of a website to run on which worker node, depending on how much memory and CPU it needs, through a component called the kube-scheduler.

The controlplane also has a concept called controller. Controllers are parts of Kubernetes that guarantee specific conditions are met for what the software development team wants to make available to customers. For instance, there is a controller that makes sure a website runs on multiple worker nodes in case one fails. There is another controller that makes sure periodic tasks run at a specified time each and every day.

The controlplane is extensible, so I couldn’t list all of its use cases. A company with very specific needs could create controllers for domain specific requirements. If that’s a bit blurry, let’s talk about cheesecake.

Drawing of a cheesecake, add coulis to extend, just like you would extend Kubernetes with additional code

A cheesecake is extensible too. Yes it is. You can add a raspberry coulis to it.

And just like the raspberry coulis adds to the cheesecake, Kubernetes allows writing bits and pieces of software that change how Kubernetes works and make it adaptable to a very large number of use cases.

Worker nodes

So we’ve talked about the controlplane, but what about the worker nodes?

The worker nodes are a bit simpler: they do what the controlplane asks them to do. That could be anything from displaying the website for a local bakery to sending out emails for a marketing campaign.

Declarative vs imperative

We’ve now seen the two main parts, the controlplane and the worker nodes. Let’s see how we can ask Kubernetes to do things.

Kubernetes supports a declarative approach and an imperative approach.

Let’s go back our cheesecake to make things more digestible.

Comparison of imperative vs declarative programming based on food

If you want to ask your partner to bake a cheesecake, you can try one of two methods:

  • Tell them what you expect and trust them to do the right thing, for instance “I’d like a cheesecake”;
  • Or give them step by step instructions such as “Buy 150g digestive biscuits, buy plain flour, (…), preheat the oven to 180C, etc”.

The first way is declarative, the second is imperative.

With Kubernetes, the declarative way consists in writing a file that describes what you expect and then trust Kubernetes to do whatever needs to be done to meet your expectation. To run a website on a single server, you’d need to describe your expectation with something like this:

apiVersion: v1
kind: Pod
    name: my-website
    - name: my-website
      image: my-website:1.0
apiVersion: v1
kind: Service
  name: my-website
    app.kubernetes.io/name: my-website
    - protocol: TCP
      port: 80

The imperative way of talking to Kubernetes consists in telling it step by step what to do. To run the same website on a single server, you would use a program called kubectl in a terminal. You would need to type kubectl run my-website --image my-website:1.0 and then kubectl expose pod my-website --port=80 --name=my-website.

Most of the time, software development teams use the declarative approach with Kubernetes, because it makes collaboration easier. But the imperative method can be useful from time to time too.