Home > Enterprise >  Why can't I compare resource versions with inequalities?
Why can't I compare resource versions with inequalities?

Time:11-26

The Kubernetes docs state the following about the metadata.resourceVersion of a K8s object

You must not assume resource versions are numeric or collatable. API clients may only compare two resource versions for equality (this means that you must not compare resource versions for greater-than or less-than relationships).

I'm glad I read this because I was about to do exactly the thing it says not to do (comparison with > or < to check consistency).

My question is: Why not? Why are clients not allowed to do this?

Edits: To clarify, the resource version this question refers to is the metadata.resourceVersion of K8s objects, not the apiVersion.

In my experience, the resource version is an integer, increasing monotonically in time (incremented each time the resource is modified). It seems the docs say this is not a guarantee.

CodePudding user response:

Posting this as a community wiki, feel free to edit and expand.


resourceVersion

I think most correct answer will be:

Kubernetes leverages the concept of resource versions to achieve optimistic concurrency. All Kubernetes resources have a "resourceVersion" field as part of their metadata. This resourceVersion is a string that identifies the internal version of an object that can be used by clients to determine when objects have changed. When a record is about to be updated, it's version is checked against a pre-saved value, and if it doesn't match, the update fails with a StatusConflict (HTTP status code 409).

The resourceVersion is changed by the server every time an object is modified. If resourceVersion is included with the PUT operation the system will verify that there have not been other successful mutations to the resource during a read/modify/write cycle, by verifying that the current value of resourceVersion matches the specified value.

The resourceVersion is currently backed by etcd's modifiedIndex. However, it's important to note that the application should not rely on the implementation details of the versioning system maintained by Kubernetes. We may change the implementation of resourceVersion in the future, such as to change it to a timestamp or per-object counter.

The only way for a client to know the expected value of resourceVersion is to have received it from the server in response to a prior operation, typically a GET. This value MUST be treated as opaque by clients and passed unmodified back to the server. Clients should not assume that the resource version has meaning across namespaces, different kinds of resources, or different servers. Currently, the value of resourceVersion is set to match etcd's sequencer. You could think of it as a logical clock the API server can use to order requests. However, we expect the implementation of resourceVersion to change in the future, such as in the case we shard the state by kind and/or namespace, or port to another storage system.

Since there are chances that this logic can be changed, it's better to follow what kubernetes developers offer since they know further changes better than anyone else do.

Also in API documentation it's said that it's a string type, not integer or date, see here.

Please find more details about Concurrency Control and Consistency.


apiVersion

Simple and short answer - because versions are not numeric and sometimes it can be changed very significantly.

Below is a couple of examples that I know/used which will show the difference:

  • ingress:

    used to be - extensions/v1beta1

    actual version - networking.k8s.io/v1

  • istio uses both versions at the moment:

    networking.istio.io/v1alpha3 and networking.istio.io/v1beta1

So at this point comparison with > or < won't work. And much more precise method is to check whether API version is same or not.

  • Related