# Versions in CustomResourceDefinitions

LLMS index: [llms.txt](/llms.txt)

---

<!-- overview -->
This page explains how to add versioning information to
[CustomResourceDefinitions](/docs/reference/kubernetes-api/extend-resources/custom-resource-definition-v1/), to indicate the stability
level of your CustomResourceDefinitions or advance your API to a new version with conversion between API representations. It also describes how to upgrade an object from one version to another.

## Before you begin

<p>You need to have a Kubernetes cluster, and the kubectl command-line tool must
be configured to communicate with your cluster. It is recommended to run this tutorial on a cluster with at least two nodes that are not acting as control plane hosts. If you do not already have a
cluster, you can create one by using
<a href="https://minikube.sigs.k8s.io/docs/tutorials/multi_node/">minikube</a>
or you can use one of these Kubernetes playgrounds:</p>
<ul>
<li><a href="https://labs.iximiuz.com/playgrounds?category=kubernetes&filter=all">iximiuz Labs</a></li>
<li><a href="https://killercoda.com/playgrounds/scenario/kubernetes">Killercoda</a></li>
<li><a href="https://kodekloud.com/public-playgrounds">KodeKloud</a></li>
</ul>


You should have an initial understanding of [custom resources](/docs/concepts/extend-kubernetes/api-extension/custom-resources/).



Your Kubernetes server must be at or later than version v1.16.
 <p>To check the version, enter  <code>kubectl version</code>.</p>


<!-- steps -->

## Overview

The CustomResourceDefinition API provides a workflow for introducing and upgrading
to new versions of a CustomResourceDefinition.

When a CustomResourceDefinition is created, the first version is set in the
CustomResourceDefinition `spec.versions` list to an appropriate stability level
and a version number. For example `v1beta1` would indicate that the first
version is not yet stable. All custom resource objects will initially be stored
at this version.

Once the CustomResourceDefinition is created, clients may begin using the
`v1beta1` API.

Later it might be necessary to add new version such as `v1`.

Adding a new version:

1. Pick a conversion strategy. Since custom resource objects need the ability to
   be served at both versions, that means they will sometimes be served in a
   different version than the one stored. To make this possible, the custom resource objects must sometimes be converted between the
   version they are stored at and the version they are served at. If the
   conversion involves schema changes and requires custom logic, a conversion
   webhook should be used. If there are no schema changes, the default `None`
   conversion strategy may be used and only the `apiVersion` field will be
   modified when serving different versions.
1. If using conversion webhooks, create and deploy the conversion webhook. See
   the [Webhook conversion](#webhook-conversion) for more details.
1. Update the CustomResourceDefinition to include the new version in the
   `spec.versions` list with `served:true`.  Also, set `spec.conversion` field
   to the selected conversion strategy. If using a conversion webhook, configure
   `spec.conversion.webhookClientConfig` field to call the webhook.

Once the new version is added, clients may incrementally migrate to the new
version. It is perfectly safe for some clients to use the old version while
others use the new version.

Migrate stored objects to the new version:

1. See the [upgrade existing objects to a new stored version](#upgrade-existing-objects-to-a-new-stored-version) section.

It is safe for clients to use both the old and new version before, during and
after upgrading the objects to a new stored version.

Removing an old version:

1. Ensure all clients are fully migrated to the new version. The kube-apiserver
   logs can be reviewed to help identify any clients that are still accessing via
   the old version.
1. Set `served` to `false` for the old version in the `spec.versions` list. If
   any clients are still unexpectedly using the old version they may begin reporting
   errors attempting to access the custom resource objects at the old version.
   If this occurs, switch back to using `served:true` on the old version, migrate the 
   remaining clients to the new version and repeat this step.
1. Ensure the [upgrade of existing objects to the new stored version](#upgrade-existing-objects-to-a-new-stored-version) step has been completed.
   1. Verify that the `storage` is set to `true` for the new version in the `spec.versions` list in the CustomResourceDefinition.
   1. Verify that the old version is no longer listed in the CustomResourceDefinition `status.storedVersions`.
1. Remove the old version from the CustomResourceDefinition `spec.versions` list.
1. Drop conversion support for the old version in conversion webhooks.

## Specify multiple versions

The CustomResourceDefinition API `versions` field can be used to support multiple versions of custom resources that you
have developed. Versions can have different schemas, and conversion webhooks can convert custom resources between versions.
Webhook conversions should follow the [Kubernetes API conventions](https://github.com/kubernetes/community/blob/main/contributors/devel/sig-architecture/api-conventions.md) wherever applicable.
Specifically, See the [API change documentation](https://github.com/kubernetes/community/blob/main/contributors/devel/sig-architecture/api_changes.md) for a set of useful gotchas and suggestions.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>In <code>apiextensions.k8s.io/v1beta1</code>, there was a <code>version</code> field instead of <code>versions</code>. The
<code>version</code> field is deprecated and optional, but if it is not empty, it must
match the first item in the <code>versions</code> field.</div>


This example shows a CustomResourceDefinition with two versions. For the first
example, the assumption is all versions share the same schema with no conversion
between them. The comments in the YAML provide more context.

<ul class="nav nav-tabs" id="tabs-customresourcedefinition-versioning-example-1" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-customresourcedefinition-versioning-example-1-0" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-1-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-customresourcedefinition-versioning-example-1-1" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-1-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-customresourcedefinition-versioning-example-1-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-customresourcedefinition-versioning-example-1-0" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-1-0-tab" tabindex="customresourcedefinition-versioning-example-1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># name must match the spec fields below, and be in the form: &lt;plural&gt;.&lt;group&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># group name to use for REST API: /apis/&lt;group&gt;/&lt;version&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># list of versions supported by this CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can be enabled/disabled by Served flag.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># One and only one version must be marked as the storage version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># A schema is required</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># The conversion section is introduced in Kubernetes 1.13+ with a default value of</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># None conversion (strategy sub-field set to None).</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># None conversion assumes the same schema for all versions and only sets the apiVersion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># field of custom resources to the proper value</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">None</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># either Namespaced or Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># plural name to be used in the URL: /apis/&lt;group&gt;/&lt;version&gt;/&lt;plural&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># singular name to be used as an alias on the CLI and for display</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind is normally the CamelCased singular type. Your resource manifests use this.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># shortNames allow shorter string to match your resource on the CLI</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">shortNames</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ct</span><span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-customresourcedefinition-versioning-example-1-1" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-1-1-tab" tabindex="customresourcedefinition-versioning-example-1"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># name must match the spec fields below, and be in the form: &lt;plural&gt;.&lt;group&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># group name to use for REST API: /apis/&lt;group&gt;/&lt;version&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># list of versions supported by this CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can be enabled/disabled by Served flag.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># One and only one version must be marked as the storage version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">validation</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">host</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">port</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># The conversion section is introduced in Kubernetes 1.13+ with a default value of</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># None conversion (strategy sub-field set to None).</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># None conversion assumes the same schema for all versions and only sets the apiVersion</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># field of custom resources to the proper value</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">None</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># either Namespaced or Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># plural name to be used in the URL: /apis/&lt;group&gt;/&lt;version&gt;/&lt;plural&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># singular name to be used as an alias on the CLI and for display</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind is normally the PascalCased singular type. Your resource manifests use this.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># shortNames allow shorter string to match your resource on the CLI</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">shortNames</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ct</span><span class="w">
</span></span></span></code></pre></div></div></div>


You can save the CustomResourceDefinition in a YAML file, then use
`kubectl apply` to create it.

```shell
kubectl apply -f my-versioned-crontab.yaml
```

After creation, the API server starts to serve each enabled version at an HTTP
REST endpoint. In the above example, the API versions are available at
`/apis/example.com/v1beta1` and `/apis/example.com/v1`.

### Version priority

Regardless of the order in which versions are defined in a
CustomResourceDefinition, the version with the highest priority is used by
kubectl as the default version to access objects. The priority is determined
by parsing the _name_ field to determine the version number, the stability
(GA, Beta, or Alpha), and the sequence within that stability level.

The algorithm used for sorting the versions is designed to sort versions in the
same way that the Kubernetes project sorts Kubernetes versions. Versions start with a
`v` followed by a number, an optional `beta` or `alpha` designation, and
optional additional numeric versioning information. Broadly, a version string might look
like `v2` or `v2beta1`. Versions are sorted using the following algorithm:

- Entries that follow Kubernetes version patterns are sorted before those that
  do not.
- For entries that follow Kubernetes version patterns, the numeric portions of
  the version string is sorted largest to smallest.
- If the strings `beta` or `alpha` follow the first numeric portion, they sorted
  in that order, after the equivalent string without the `beta` or `alpha`
  suffix (which is presumed to be the GA version).
- If another number follows the `beta`, or `alpha`, those numbers are also
  sorted from largest to smallest.
- Strings that don't fit the above format are sorted alphabetically and the
  numeric portions are not treated specially. Notice that in the example below,
  `foo1` is sorted above `foo10`. This is different from the sorting of the
  numeric portion of entries that do follow the Kubernetes version patterns.

This might make sense if you look at the following sorted version list:

```none
- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10
```

For the example in [Specify multiple versions](#specify-multiple-versions), the
version sort order is `v1`, followed by `v1beta1`. This causes the kubectl
command to use `v1` as the default version unless the provided object specifies
the version.

### Version deprecation








  <div class="feature-state-notice feature-stable">
      <span class="feature-state-name">FEATURE STATE:</span>
      <code>Kubernetes v1.19 [stable]</code>
    </div>
  



Starting in v1.19, a CustomResourceDefinition can indicate a particular version of the resource it defines is deprecated.
When API requests to a deprecated version of that resource are made, a warning message is returned in the API response as a header.
The warning message for each deprecated version of the resource can be customized if desired.

A customized warning message should indicate the deprecated API group, version, and kind,
and should indicate what API group, version, and kind should be used instead, if applicable.

<ul class="nav nav-tabs" id="tabs-customresourcedefinition-versioning-deprecated" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-customresourcedefinition-versioning-deprecated-0" role="tab" aria-controls="tabs-customresourcedefinition-versioning-deprecated-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-customresourcedefinition-versioning-deprecated-1" role="tab" aria-controls="tabs-customresourcedefinition-versioning-deprecated-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-customresourcedefinition-versioning-deprecated-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-customresourcedefinition-versioning-deprecated-0" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-deprecated-0-tab" tabindex="customresourcedefinition-versioning-deprecated"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This indicates the v1alpha1 version of the custom resource is deprecated.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># API requests to this version receive a warning header in the server response.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecated</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This overrides the default warning returned to API clients making v1alpha1 API requests.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecationWarning</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w"> </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This indicates the v1beta1 version of the custom resource is deprecated.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># API requests to this version receive a warning header in the server response.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># A default warning message is returned for this version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecated</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w"> </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w"> </span><span class="l">...</span><span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-customresourcedefinition-versioning-deprecated-1" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-deprecated-1-tab" tabindex="customresourcedefinition-versioning-deprecated"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">validation</span><span class="p">:</span><span class="w"> </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1alpha1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This indicates the v1alpha1 version of the custom resource is deprecated.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># API requests to this version receive a warning header in the server response.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecated</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This overrides the default warning returned to API clients making v1alpha1 API requests.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecationWarning</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># This indicates the v1beta1 version of the custom resource is deprecated.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># API requests to this version receive a warning header in the server response.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># A default warning message is returned for this version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">deprecated</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></div></div></div>



### Version removal

An older API version cannot be dropped from a CustomResourceDefinition manifest until existing stored data has been migrated to the newer API version for all clusters that served the older version of the custom resource, and the old version is removed from the `status.storedVersions` of the CustomResourceDefinition.

```yaml
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: crontabs.example.com
spec:
  group: example.com
  names:
    plural: crontabs
    singular: crontab
    kind: CronTab
  scope: Namespaced
  versions:
  - name: v1beta1
    # This indicates the v1beta1 version of the custom resource is no longer served.
    # API requests to this version receive a not found error in the server response.
    served: false
    schema: ...
  - name: v1
    served: true
    # The new served version should be set as the storage version
    storage: true
    schema: ...
```

## Webhook conversion








  <div class="feature-state-notice feature-stable">
      <span class="feature-state-name">FEATURE STATE:</span>
      <code>Kubernetes v1.16 [stable]</code>
    </div>
  




<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>Webhook conversion is available as beta since 1.15, and as alpha since Kubernetes 1.13. The
<code>CustomResourceWebhookConversion</code> feature must be enabled, which is the case automatically for many clusters for beta features. Please refer to the <a href="/docs/reference/command-line-tools-reference/feature-gates/">feature gate</a> documentation for more information.</div>


The above example has a None conversion between versions which only sets the `apiVersion` field
on conversion and does not change the rest of the object. The API server also supports webhook
conversions that call an external service in case a conversion is required. For example when:

* custom resource is requested in a different version than stored version.
* Watch is created in one version but the changed object is stored in another version.
* custom resource PUT request is in a different version than storage version.

To cover all of these cases and to optimize conversion by the API server, 
the conversion requests may contain multiple objects in order to minimize the external calls.
The webhook should perform these conversions independently.

### Write a conversion webhook server

Please refer to the implementation of the [custom resource conversion webhook
server](https://github.com/kubernetes/kubernetes/tree/v1.25.3/test/images/agnhost/crd-conversion-webhook/main.go)
that is validated in a Kubernetes e2e test. The webhook handles the
`ConversionReview` requests sent by the API servers, and sends back conversion
results wrapped in `ConversionResponse`. Note that the request
contains a list of custom resources that need to be converted independently without
changing the order of objects.
The example server is organized in a way to be reused for other conversions.
Most of the common code are located in the
[framework file](https://github.com/kubernetes/kubernetes/tree/v1.25.3/test/images/agnhost/crd-conversion-webhook/converter/framework.go)
that leaves only
[one function](https://github.com/kubernetes/kubernetes/tree/v1.25.3/test/images/agnhost/crd-conversion-webhook/converter/example_converter.go#L29-L80)
to be implemented for different conversions.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>The example conversion webhook server leaves the <code>ClientAuth</code> field
<a href="https://github.com/kubernetes/kubernetes/tree/v1.25.3/test/images/agnhost/crd-conversion-webhook/config.go#L47-L48">empty</a>,
which defaults to <code>NoClientCert</code>. This means that the webhook server does not
authenticate the identity of the clients, supposedly API servers. If you need
mutual TLS or other ways to authenticate the clients, see
how to <a href="/docs/reference/access-authn-authz/extensible-admission-controllers/#authenticate-apiservers">authenticate API servers</a>.</div>


#### Permissible mutations

A conversion webhook must not mutate anything inside of `metadata` of the converted object
other than `labels` and `annotations`.
Attempted changes to `name`, `UID` and `namespace` are rejected and fail the request
which caused the conversion. All other changes are ignored.  

### Deploy the conversion webhook service

Documentation for deploying the conversion webhook is the same as for the
[admission webhook example service](/docs/reference/access-authn-authz/extensible-admission-controllers/#deploy-the-admission-webhook-service).
The assumption for next sections is that the conversion webhook server is deployed to a service
named `example-conversion-webhook-server` in `default` namespace and serving traffic on path `/crdconvert`.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4>When the webhook server is deployed into the Kubernetes cluster as a
service, it has to be exposed via a service on port 443 (The server
itself can have an arbitrary port but the service object should map it to port 443).
The communication between the API server and the webhook service may fail
if a different port is used for the service.</div>


### Configure CustomResourceDefinition to use conversion webhooks

The `None` conversion example can be extended to use the conversion webhook by modifying `conversion`
section of the `spec`:

<ul class="nav nav-tabs" id="tabs-customresourcedefinition-versioning-example-2" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-customresourcedefinition-versioning-example-2-0" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-2-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-customresourcedefinition-versioning-example-2-1" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-2-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-customresourcedefinition-versioning-example-2-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-customresourcedefinition-versioning-example-2-0" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-2-0-tab" tabindex="customresourcedefinition-versioning-example-2"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># name must match the spec fields below, and be in the form: &lt;plural&gt;.&lt;group&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># group name to use for REST API: /apis/&lt;group&gt;/&lt;version&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># list of versions supported by this CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can be enabled/disabled by Served flag.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># One and only one version must be marked as the storage version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can define its own schema when there is no top-level</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># schema is defined.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">hostPort</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># the Webhook strategy instructs the API server to call an external webhook for any conversion between custom resources.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># webhook is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhook</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># conversionReviewVersions indicates what ConversionReview versions are understood/preferred by the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># The first version in the list understood by the API server is sent to the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="c"># The webhook must respond with a ConversionReview object in the same version it received.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">conversionReviewVersions</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;v1&#34;</span><span class="p">,</span><span class="s2">&#34;v1beta1&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">clientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">example-conversion-webhook-server</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">/crdconvert</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">caBundle</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Ci0tLS0tQk...&lt;base64-encoded PEM bundle&gt;...tLS0K&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># either Namespaced or Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># plural name to be used in the URL: /apis/&lt;group&gt;/&lt;version&gt;/&lt;plural&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># singular name to be used as an alias on the CLI and for display</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind is normally the CamelCased singular type. Your resource manifests use this.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># shortNames allow shorter string to match your resource on the CLI</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">shortNames</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ct</span><span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-customresourcedefinition-versioning-example-2-1" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-2-1-tab" tabindex="customresourcedefinition-versioning-example-2"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">metadata</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># name must match the spec fields below, and be in the form: &lt;plural&gt;.&lt;group&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs.example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># group name to use for REST API: /apis/&lt;group&gt;/&lt;version&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">group</span><span class="p">:</span><span class="w"> </span><span class="l">example.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># prunes object fields that are not specified in OpenAPI schemas below.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">preserveUnknownFields</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># list of versions supported by this CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">versions</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can be enabled/disabled by Served flag.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># One and only one version must be marked as the storage version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Each version can define its own schema when there is no top-level</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># schema is defined.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">hostPort</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">served</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">storage</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">openAPIV3Schema</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">object</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">properties</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">host</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">string</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># the Webhook strategy instructs the API server to call an external webhook for any conversion between custom resources.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># webhookClientConfig is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhookClientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">service</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">default</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">example-conversion-webhook-server</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">/crdconvert</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">caBundle</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Ci0tLS0tQk...&lt;base64-encoded PEM bundle&gt;...tLS0K&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># either Namespaced or Cluster</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">scope</span><span class="p">:</span><span class="w"> </span><span class="l">Namespaced</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">names</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># plural name to be used in the URL: /apis/&lt;group&gt;/&lt;version&gt;/&lt;plural&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">plural</span><span class="p">:</span><span class="w"> </span><span class="l">crontabs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># singular name to be used as an alias on the CLI and for display</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">singular</span><span class="p">:</span><span class="w"> </span><span class="l">crontab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind is normally the CamelCased singular type. Your resource manifests use this.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CronTab</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># shortNames allow shorter string to match your resource on the CLI</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">shortNames</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ct</span><span class="w">
</span></span></span></code></pre></div></div></div>


You can save the CustomResourceDefinition in a YAML file, then use
`kubectl apply` to apply it.

```shell
kubectl apply -f my-versioned-crontab-with-conversion.yaml
```

Make sure the conversion service is up and running before applying new changes.

### Contacting the webhook

Once the API server has determined a request should be sent to a conversion webhook,
it needs to know how to contact the webhook. This is specified in the `webhookClientConfig`
stanza of the webhook configuration.

Conversion webhooks can either be called via a URL or a service reference,
and can optionally include a custom CA bundle to use to verify the TLS connection.

### URL

`url` gives the location of the webhook, in standard URL form
(`scheme://host:port/path`).

The `host` should not refer to a service running in the cluster; use
a service reference by specifying the `service` field instead.
The host might be resolved via external DNS in some apiservers
(i.e., `kube-apiserver` cannot resolve in-cluster DNS as that would
be a layering violation). `host` may also be an IP address.

Please note that using `localhost` or `127.0.0.1` as a `host` is
risky unless you take great care to run this webhook on all hosts
which run an apiserver which might need to make calls to this
webhook. Such installations are likely to be non-portable or not readily run in a new cluster.

The scheme must be "https"; the URL must begin with "https://".

Attempting to use a user or basic auth (for example "user:password@") is not allowed.
Fragments ("#...") and query parameters ("?...") are also not allowed.

Here is an example of a conversion webhook configured to call a URL
(and expects the TLS certificate to be verified using system trust roots, so does not specify a caBundle):

<ul class="nav nav-tabs" id="tabs-customresourcedefinition-versioning-example-3" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-customresourcedefinition-versioning-example-3-0" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-3-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-customresourcedefinition-versioning-example-3-1" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-3-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-customresourcedefinition-versioning-example-3-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-customresourcedefinition-versioning-example-3-0" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-3-0-tab" tabindex="customresourcedefinition-versioning-example-3"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhook</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">clientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://my-webhook.example.com:9443/my-webhook-path&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-customresourcedefinition-versioning-example-3-1" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-3-1-tab" tabindex="customresourcedefinition-versioning-example-3"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhookClientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">url</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;https://my-webhook.example.com:9443/my-webhook-path&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span></code></pre></div></div></div>


### Service Reference

The `service` stanza inside `webhookClientConfig` is a reference to the service for a conversion webhook.
If the webhook is running within the cluster, then you should use `service` instead of `url`.
The service namespace and name are required. The port is optional and defaults to 443.
The path is optional and defaults to "/".

Here is an example of a webhook that is configured to call a service on port "1234"
at the subpath "/my-path", and to verify the TLS connection against the ServerName
`my-service-name.my-service-namespace.svc` using a custom CA bundle.

<ul class="nav nav-tabs" id="tabs-customresourcedefinition-versioning-example-4" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-customresourcedefinition-versioning-example-4-0" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-4-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-customresourcedefinition-versioning-example-4-1" role="tab" aria-controls="tabs-customresourcedefinition-versioning-example-4-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-customresourcedefinition-versioning-example-4-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-customresourcedefinition-versioning-example-4-0" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-4-0-tab" tabindex="customresourcedefinition-versioning-example-4"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhook</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">clientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">service</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">my-service-namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">my-service-name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">/my-path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">1234</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">caBundle</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Ci0tLS0tQk...&lt;base64-encoded PEM bundle&gt;...tLS0K&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-customresourcedefinition-versioning-example-4-1" role="tabpanel" aria-labelledby="tabs-customresourcedefinition-versioning-example-4-1-tab" tabindex="customresourcedefinition-versioning-example-4"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhookClientConfig</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">service</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">namespace</span><span class="p">:</span><span class="w"> </span><span class="l">my-service-namespace</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">my-service-name</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">/my-path</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="m">1234</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">caBundle</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;Ci0tLS0tQk...&lt;base64-encoded PEM bundle&gt;...tLS0K&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span></code></pre></div></div></div>


## Webhook request and response

### Request

Webhooks are sent a POST request, with `Content-Type: application/json`,
with a `ConversionReview` API object in the `apiextensions.k8s.io` API group
serialized to JSON as the body.

Webhooks can specify what versions of `ConversionReview` objects they accept
with the `conversionReviewVersions` field in their CustomResourceDefinition:

<ul class="nav nav-tabs" id="tabs-conversionreviewversions" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-conversionreviewversions-0" role="tab" aria-controls="tabs-conversionreviewversions-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-conversionreviewversions-1" role="tab" aria-controls="tabs-conversionreviewversions-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-conversionreviewversions-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-conversionreviewversions-0" role="tabpanel" aria-labelledby="tabs-conversionreviewversions-0-tab" tabindex="conversionreviewversions"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">webhook</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">conversionReviewVersions</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;v1&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;v1beta1&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="l">...</span><span class="w">
</span></span></span></code></pre></div><p><code>conversionReviewVersions</code> is a required field when creating
<code>apiextensions.k8s.io/v1</code> custom resource definitions.
Webhooks are required to support at least one <code>ConversionReview</code>
version understood by the current and previous API server.</p>
</div><div class="tab-body tab-pane fade"
        id="tabs-conversionreviewversions-1" role="tabpanel" aria-labelledby="tabs-conversionreviewversions-1-tab" tabindex="conversionreviewversions"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">apiVersion</span><span class="p">:</span><span class="w"> </span><span class="l">apiextensions.k8s.io/v1beta1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">kind</span><span class="p">:</span><span class="w"> </span><span class="l">CustomResourceDefinition</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nn">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">spec</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="l">...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">conversion</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w"> </span><span class="l">Webhook</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">conversionReviewVersions</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&#34;v1&#34;</span><span class="p">,</span><span class="w"> </span><span class="s2">&#34;v1beta1&#34;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="l">...</span><span class="w">
</span></span></span></code></pre></div><p>If no <code>conversionReviewVersions</code> are specified, the default when creating
<code>apiextensions.k8s.io/v1beta1</code> custom resource definitions is <code>v1beta1</code>.</p>
</div></div>


API servers send the first `ConversionReview` version in the `conversionReviewVersions` list they support.
If none of the versions in the list are supported by the API server, the custom resource definition will not be allowed to be created.
If an API server encounters a conversion webhook configuration that was previously created and does not support any of the `ConversionReview`
versions the API server knows how to send, attempts to call to the webhook will fail.

This example shows the data contained in an `ConversionReview` object
for a request to convert `CronTab` objects to `example.com/v1`:


<ul class="nav nav-tabs" id="tabs-conversionreview-request" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-conversionreview-request-0" role="tab" aria-controls="tabs-conversionreview-request-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-conversionreview-request-1" role="tab" aria-controls="tabs-conversionreview-request-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-conversionreview-request-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-conversionreview-request-0" role="tabpanel" aria-labelledby="tabs-conversionreview-request-0-tab" tabindex="conversionreview-request"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;request&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Random uid uniquely identifying this conversion call</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;705ab4f5-6393-11e8-b7cc-42010a800002&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># The API group and version the objects should be converted to</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;desiredAPIVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># The list of objects to convert.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># May contain one or more objects, in one or more versions.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;objects&#34;: </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-04T14:03:02Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;local-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;namespace&#34;: </span><span class="s2">&#34;default&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;143&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;3415a7fc-162b-4300-b5da-fd6083580d66&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;hostPort&#34;: </span><span class="s2">&#34;localhost:1234&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-03T13:02:01Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;remote-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;12893&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;359a83ec-b575-460d-b553-d859cedde8a0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;hostPort&#34;: </span><span class="s2">&#34;example.com:2345&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-conversionreview-request-1" role="tabpanel" aria-labelledby="tabs-conversionreview-request-1-tab" tabindex="conversionreview-request"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;request&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Random uid uniquely identifying this conversion call</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;705ab4f5-6393-11e8-b7cc-42010a800002&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># The API group and version the objects should be converted to</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;desiredAPIVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># The list of objects to convert.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># May contain one or more objects, in one or more versions.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;objects&#34;: </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-04T14:03:02Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;local-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;namespace&#34;: </span><span class="s2">&#34;default&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;143&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;3415a7fc-162b-4300-b5da-fd6083580d66&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;hostPort&#34;: </span><span class="s2">&#34;localhost:1234&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-03T13:02:01Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;remote-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;12893&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;359a83ec-b575-460d-b553-d859cedde8a0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;hostPort&#34;: </span><span class="s2">&#34;example.com:2345&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div></div>


### Response

Webhooks respond with a 200 HTTP status code, `Content-Type: application/json`,
and a body containing a `ConversionReview` object (in the same version they were sent),
with the `response` stanza populated, serialized to JSON.

If conversion succeeds, a webhook should return a `response` stanza containing the following fields:
* `uid`, copied from the `request.uid` sent to the webhook
* `result`, set to `{"status":"Success"}`
* `convertedObjects`, containing all of the objects from `request.objects`, converted to `request.desiredAPIVersion`

Example of a minimal successful response from a webhook:

<ul class="nav nav-tabs" id="tabs-conversionreview-response-success" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-conversionreview-response-success-0" role="tab" aria-controls="tabs-conversionreview-response-success-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-conversionreview-response-success-1" role="tab" aria-controls="tabs-conversionreview-response-success-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-conversionreview-response-success-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-conversionreview-response-success-0" role="tabpanel" aria-labelledby="tabs-conversionreview-response-success-0-tab" tabindex="conversionreview-response-success"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;response&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># must match &lt;request.uid&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;705ab4f5-6393-11e8-b7cc-42010a800002&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;result&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;status&#34;: </span><span class="s2">&#34;Success&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Objects must match the order of request.objects, and have apiVersion set to &lt;request.desiredAPIVersion&gt;.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># metadata.labels and metadata.annotations fields may be changed by the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># All other changes to metadata fields by the webhook are ignored.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;convertedObjects&#34;: </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-04T14:03:02Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;local-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;namespace&#34;: </span><span class="s2">&#34;default&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;143&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;3415a7fc-162b-4300-b5da-fd6083580d66&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;host&#34;: </span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;port&#34;: </span><span class="s2">&#34;1234&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-03T13:02:01Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;remote-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;12893&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;359a83ec-b575-460d-b553-d859cedde8a0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;host&#34;: </span><span class="s2">&#34;example.com&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;port&#34;: </span><span class="s2">&#34;2345&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-conversionreview-response-success-1" role="tabpanel" aria-labelledby="tabs-conversionreview-response-success-1-tab" tabindex="conversionreview-response-success"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;response&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># must match &lt;request.uid&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;705ab4f5-6393-11e8-b7cc-42010a800002&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;result&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;status&#34;: </span><span class="s2">&#34;Failed&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># Objects must match the order of request.objects, and have apiVersion set to &lt;request.desiredAPIVersion&gt;.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># metadata.labels and metadata.annotations fields may be changed by the webhook.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># All other changes to metadata fields by the webhook are ignored.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;convertedObjects&#34;: </span><span class="p">[</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-04T14:03:02Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;local-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;namespace&#34;: </span><span class="s2">&#34;default&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;143&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;3415a7fc-162b-4300-b5da-fd6083580d66&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;host&#34;: </span><span class="s2">&#34;localhost&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;port&#34;: </span><span class="s2">&#34;1234&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;CronTab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;example.com/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;metadata&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;creationTimestamp&#34;: </span><span class="s2">&#34;2019-09-03T13:02:01Z&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;name&#34;: </span><span class="s2">&#34;remote-crontab&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;resourceVersion&#34;: </span><span class="s2">&#34;12893&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">          </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;359a83ec-b575-460d-b553-d859cedde8a0&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span>}<span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;host&#34;: </span><span class="s2">&#34;example.com&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="nt">&#34;port&#34;: </span><span class="s2">&#34;2345&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div></div>


If conversion fails, a webhook should return a `response` stanza containing the following fields:
* `uid`, copied from the `request.uid` sent to the webhook
* `result`, set to `{"status":"Failed"}`

<div class="alert alert-danger" role="note"><h4 class="alert-heading">Warning:</h4>Failing conversion can disrupt read and write access to the custom resources,
including the ability to update or delete the resources. Conversion failures
should be avoided whenever possible, and should not be used to enforce validation
constraints (use validation schemas or webhook admission instead).</div>


Example of a response from a webhook indicating a conversion request failed, with an optional message:
<ul class="nav nav-tabs" id="tabs-conversionreview-response-failure" role="tablist"><li class="nav-item"><a data-bs-toggle="tab" class="nav-link active" href="#tabs-conversionreview-response-failure-0" role="tab" aria-controls="tabs-conversionreview-response-failure-0" aria-selected="true">apiextensions.k8s.io/v1</a></li>
	  
		<li class="nav-item"><a data-bs-toggle="tab" class="nav-link" href="#tabs-conversionreview-response-failure-1" role="tab" aria-controls="tabs-conversionreview-response-failure-1">apiextensions.k8s.io/v1beta1</a></li></ul>

<div class="tab-content" id="tabs-conversionreview-response-failure-content"><div class="tab-body tab-pane fadeshow active"
        id="tabs-conversionreview-response-failure-0" role="tabpanel" aria-labelledby="tabs-conversionreview-response-failure-0-tab" tabindex="conversionreview-response-failure"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;response&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;&lt;value from request.uid&gt;&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;result&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;status&#34;: </span><span class="s2">&#34;Failed&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;message&#34;: </span><span class="s2">&#34;hostPort could not be parsed into a separate host and port&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div><div class="tab-body tab-pane fade"
        id="tabs-conversionreview-response-failure-1" role="tabpanel" aria-labelledby="tabs-conversionreview-response-failure-1-tab" tabindex="conversionreview-response-failure"><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="c"># Deprecated in v1.16 in favor of apiextensions.k8s.io/v1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;apiVersion&#34;: </span><span class="s2">&#34;apiextensions.k8s.io/v1beta1&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;kind&#34;: </span><span class="s2">&#34;ConversionReview&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">&#34;response&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;uid&#34;: </span><span class="s2">&#34;&lt;value from request.uid&gt;&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#34;result&#34;: </span>{<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;status&#34;: </span><span class="s2">&#34;Failed&#34;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">&#34;message&#34;: </span><span class="s2">&#34;hostPort could not be parsed into a separate host and port&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>}<span class="w">
</span></span></span><span class="line"><span class="cl">}<span class="w">
</span></span></span></code></pre></div></div></div>


## Writing, reading, and updating versioned CustomResourceDefinition objects

When an object is written, it is stored at the version designated as the
storage version at the time of the write. If the storage version changes,
existing objects are never converted automatically. However, newly-created
or updated objects are written at the new storage version. It is possible for an
object to have been written at a version that is no longer served.

When you read an object, you specify the version as part of the path.
You can request an object at any version that is currently served.
If you specify a version that is different from the object's stored version,
Kubernetes returns the object to you at the version you requested, but the
stored object is not changed on disk.

What happens to the object that is being returned while serving the read
request depends on what is specified in the CRD's `spec.conversion`:
- if the default `strategy` value `None` is specified, the only modifications
  to the object are changing the `apiVersion` string and perhaps [pruning
  unknown fields](/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#field-pruning)
  (depending on the configuration). Note that this is unlikely to lead to good
  results if the schemas differ between the storage and requested version.
  In particular, you should not use this strategy if the same data is
  represented in different fields between versions.
- if [webhook conversion](#webhook-conversion) is specified, then this
  mechanism controls the conversion.

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.

To illustrate this, consider the following hypothetical series of events:

1. The storage version is `v1beta1`. You create an object. It is stored at version `v1beta1`
2. You add version `v1` to your CustomResourceDefinition and designate it as
   the storage version. Here the schemas for `v1` and `v1beta1` are identical,
   which is typically the case when promoting an API to stable in the
   Kubernetes ecosystem.
3. You read your object at version `v1beta1`, then you read the object again at
   version `v1`. Both returned objects are identical except for the apiVersion
   field.
4. You create a new object. It is stored at version `v1`. You now
   have two objects, one of which is at `v1beta1`, and the other of which is at
   `v1`.
5. You update the first object. It is now stored at version `v1` since that
   is the current storage version.

### Previous storage versions

The API server records each version which has ever been marked as the storage
version in the status field `storedVersions`. Objects may have been stored
at any version that has ever been designated as a storage version. No objects
can exist in storage at a version that has never been a storage version.

## Upgrade existing objects to a new stored version

When deprecating versions and dropping support, select a storage upgrade
procedure. 

*Option 1:* Use the Storage Version Migrator

1. Run the [storage Version migrator](https://github.com/kubernetes-sigs/kube-storage-version-migrator)
2. Remove the old version from the CustomResourceDefinition `status.storedVersions` field.

*Option 2:* Manually upgrade the existing objects to a new stored version

The following is an example procedure to upgrade from `v1beta1` to `v1`.

1. Set `v1` as the storage in the CustomResourceDefinition file and apply it
   using kubectl. The `storedVersions` is now `v1beta1, v1`.
2. Write an upgrade procedure to list all existing objects and write them with
   the same content. This forces the backend to write objects in the current
   storage version, which is `v1`.
3. Remove `v1beta1` from the CustomResourceDefinition `status.storedVersions` field.


<div class="alert alert-info" role="note"><h4 class="alert-heading">Note:</h4><p>Here is an example of how to patch the <code>status</code> subresource for a CRD object using <code>kubectl</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">kubectl patch customresourcedefinitions &lt;CRD_Name&gt; --subresource<span class="o">=</span><span class="s1">&#39;status&#39;</span> --type<span class="o">=</span><span class="s1">&#39;merge&#39;</span> -p <span class="s1">&#39;{&#34;status&#34;:{&#34;storedVersions&#34;:[&#34;v1&#34;]}}&#39;</span>
</span></span></code></pre></div></div>
