The desired state

Posted on May 15, 2023

When talking about Kubernetes, a key concept is the one about desired state vs actual state and the functionality of reconciling the actual state to match the desired state. While that is easy to understand, the idea of the desired state needs to be discussed a bit further. What is the desired state from a user’s point of view?

A growing system

In the early days of Kubernetes, there were only a few resources: ReplicationControllers, Services, ConfigMaps and a few other things. As the system matured, more and more resources were introduced and with Third Party Resources first which became Custom Resource Definitions, there was an explosion of new resources. At the same time, more controllers/operators were created which also started to manage resources themselves. The webhook system of Kubernetes was extended to support mutating webhooks which injected things in some of the resources and more components were created to deal with user submitted resources, for example like the Horizontal Pod Autoscaler or the Vertical Pod Autoscaler.

Due to all of those new controllers and resources, n the modern Kubernetes world, when the user applies a resource, there is so much going on that it is likely that the resources will be modified. The classics are:

  • Replica count being changed
  • Memory/CPU requests and limits being adjusted
  • Sidecars being injected

And more depending on the use case.

Your desired state is not the actual state… ever.

The reason for the existence of all the aforementioned modifications of user provided resources is that Kubernetes is a really complex system and that we want to “simplify” things for the users and create automation, to avoid having the users in the loop for every little thing.

For that reason, the system does a lot of things behind the scenes… which makes the resources that the user interacts with different in the live system if compared to the applied resources.

It’s all about abstractions

To better understand what is explained above, I would like to make an example. Let’s say we are dealing with a Deployment and a Vertical Pod Autoscaler resource. The Vertical Pod Autoscaler doesn’t have any value per se, but it exists to tell Kubernetes that it can adjust limits and requests for the pods associated with the Deployment. This is a simple, modular approach, but what we are really dealing with is a single resource: a Deployment that has automatic limits and request adjustment. We could call this a AutomaticallyLimitRequestAdjustedDeployment. But not even Kubernetes is not enough Java to do that :-) And obviously that wouldn’t work either for reasons of modularity.

Conclusion

You don’t always get your state exactly as you specify it to Kubernetes. That is not bad as this is mostly done to simplify the developers’ lives. It’s important for platform teams that are managing Kubernetes in the context of a company to clearly define to the users the concepts behind the abstractions, to make it easier to work with Kubernetes and limit possible surprises that arise from the obvious difference between the live resources and the desired state in Git.