<p>Kuberentes has a mechanism for supporting versioning of CRDs. See <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definition-versioning/" rel="noreferrer">https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definition-versioning/</a>. What is not clear to me is how you actually support an evolution of CRD v1 to CRD v2 when you cannot always convert from v1 &lt;-> v2. Suppose we introduce a new field in v2 that can not be populated by a web hook conversion, then perhaps all we can do is leave the field null? Furthermore when you request api version N you always get back an object as version N even if it was not written as version N so how can you controller know how to treat the object?</p>

<p>As you can read in <a href="https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#writing-reading-and-updating-versioned-customresourcedefinition-objects" rel="nofollow noreferrer">Writing, reading, and updating versioned CustomResourceDefinition objects</a></p>
<blockquote>
<p>If you update an existing object, it is rewritten at the version that is currently the storage version. This is the only way that objects can change from one version to another.</p>
</blockquote>
<p>Kubernetes returns the object to you at the version you requested, but the persisted object is neither changed on disk, nor converted in any way (other than changing the apiVersion string) while serving the request.</p>
<p>If you update an existing object, it is rewritten at the version that is currently the storage version. This is the only way that objects can change from one version to another.</p>
<p>You read your object at version <code>v1beta1</code>, then you read the object again at version <code>v1</code>. Both returned objects are identical except for the <code>apiVersion</code> field, <a href="https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definition-versioning/#upgrade-existing-objects-to-a-new-stored-version" rel="nofollow noreferrer">Upgrade existing objects to a new stored version</a></p>
<p>The API server also supports webhook conversions that call an external service in case a conversion is required.
The webhook handles the ConversionReview requests sent by the API servers, and sends back conversion results wrapped in ConversionResponse. You can read about Webbooks <a href="https://book.kubebuilder.io/beyond_basics/what_is_a_webhook.html" rel="nofollow noreferrer">here</a>.</p>
<p>Webhook conversion was introduced in <code>Kubernetes v1.13</code> as an alpha feature.
When the webhook server is deployed into the Kubernetes cluster as a service, it has to be exposed via a service on port 443.
When deprecating versions and dropping support, devise a storage upgrade procedure.</p>
