Event-Driven Design: The Core Principle Behind Kubernetes Architecture

Note: This is a handwritten blog. In this blog, we should explore the event where the architecture of Kubernetes is discussed. It will be very short.

As you know, Kubernetes follows an event-driven architecture. The Kubernetes control plane heavily consumes events. But most distributed systems follow RPCs to trigger behavior, but Kubernetes does not.

Reason behind why Kubernetes is not built using RPCs:

  1. Tight coupling: RPCs create strong dependencies between components. In Kubernetes, control plane components must remain loosely coupled to evolve and scale independently.
  2. Poor failure handling: RPCs expect the caller and callee to be alive at the same time. In a distributed system like Kubernetes, transient failures are common and break this assumption.
  3. Scalability limits: Synchronous RPC calls don’t scale well when thousands of objects and controllers are involved. They can easily become bottlenecks.

Let’s understand this scenario with one simple example. When you create a Deployment, the following happens:

  1. The Deployment controller notices the Deployment object through the Deployment informer. It creates the ReplicaSet.
  2. The ReplicaSet controller notices the ReplicaSet object via the ReplicaSet informer, and then it creates the Pod.
  3. The Scheduler, which is also another controller, notices that Pod (with the spec.nodName field empty) via the Pod informer. The Pod goes into the scheduling queue. At the same time, the kubelet, which is also another controller, notices the same Pod through the Pod informer and, since spec.nodName is empty, it ignores it and goes back to sleep (until the next event).
  4. Now, the Scheduler takes that Pod from the work queue and schedules it to the best-fit node by updating spec.nodName and writing it back to the API server.
  5. The kubelet wakes up again since there is an event on that Pod (an update to the spec). It notices the spec.nodName, and now kubelet’s node matches, it starts the container on that node. All the information is then written back to the API server.
  6. The same kind of process happens when you delete that Deployment, where each component looks for the event and performs some action.
  7. And so on…

As we notice, all the components communicate with each other based on certain trigger events, and controllers are responsible for maintaining the desired state all the time.

This example clearly shows why Kubernetes relies on an event-driven architecture instead of direct RPC calls. Each component reacts to state changes rather than issuing commands to one another. This design enables loose coupling, better fault tolerance, and continuous reconciliation of the desired state, which makes Kubernetes highly scalable and resilient in dynamic environments.