In a Kubernetes CRD, what does setting deprecated: true on a version entry do for clients, and how is it different from served: false?
answer
- advisory versus removal
- a response header kubectl prints
- custom text needs the flag
- 404 but data still readable
basics
~20 sSetting deprecated: true keeps the CRD version fully working but adds a warning to every response at that version, optionally replaced by deprecationWarning. Setting served: false removes the version's endpoints, so requests get 404 while stored objects stay readable.
solid answer
~40 s`deprecated: true` on a `spec.versions` entry is advisory: requests at that version still succeed, but the API server adds a `Warning` header that `kubectl` prints, by default naming the newest served replacement, for example `autocomplete.example.com/v1alpha1 SuggestIndex is deprecated; use autocomplete.example.com/v1 SuggestIndex`. `deprecationWarning` overrides that text and is allowed only when `deprecated` is true. `served: false` goes further: the version's URLs return 404 and discovery stops listing it. Neither flag touches stored data, and objects stored in an unserved version stay readable through other versions because conversion from any listed version still works. The usual order is deprecate, stop serving, migrate storage, then remove the entry.
go deeper
Know that deprecated only warns, served: false hides the version with 404s, and neither changes stored data.
Explain where the warning comes from, what the default text contains, and why unserved versions can still be converted from.
Use the two flags as stages of a retirement plan and watch client warnings before cutting a version off.
Set a platform-wide deprecation policy for custom APIs, with fixed windows between deprecating, unserving and removing versions.
## Two flags, two different promises Each entry in a CustomResourceDefinition's `spec.versions` has flags that act on clients rather than on data: - **`deprecated`** (default `false`) — the version still works exactly as before, but the API server attaches a **warning** to every response for a request made at that version. - **`deprecationWarning`** — replaces the default warning text. It may be set only when `deprecated` is `true`. - **`served`** — whether the version's REST paths exist at all. Neither flag changes how objects are stored. The storage version and the objects in etcd are untouched either way. ## What `deprecated: true` looks like to a client The warning travels in an HTTP `Warning` response header. `kubectl` prints it, and client libraries can log or surface it. The default text names the deprecated version and, when one exists, the newest served non-deprecated version of the same kind: ```bash kubectl get suggestindexes.v1alpha1.autocomplete.example.com -n search ``` For the search-autocomplete team's `SuggestIndex`, that command still lists the objects, and `kubectl` first prints `Warning: autocomplete.example.com/v1alpha1 SuggestIndex is deprecated; use autocomplete.example.com/v1 SuggestIndex`. A custom `deprecationWarning` is useful when the default text is not enough — for example to link a migration guide or name the release in which the version stops being served. Deprecation is **advisory**: nothing breaks, so it is the right first step when the search-autocomplete team wants to retire `v1alpha1`. ## What `served: false` does Setting `served: false` removes the version from the API surface: 1. Requests to `/apis/autocomplete.example.com/v1alpha1/...` get **404 Not Found**, as if the version never existed. 2. Discovery stops advertising it, so tools that enumerate versions no longer see it. 3. Objects **stored** in `v1alpha1` are still readable through `v1`, because the API server can convert from any version still listed in `spec.versions`, served or not. That third point is the difference between "stop serving" and "delete": data survives `served: false`, but it would not survive removing the entry while objects are still stored in it. ## Side by side | | `deprecated: true` | `served: false` | |---|---|---| | Requests at that version | Succeed, with a warning | Fail with 404 | | Visible in discovery | Yes | No | | Stored objects | Unchanged, readable | Unchanged, readable through other versions | | Typical use | Announce retirement | Flush out remaining clients | | Reversible instantly | Yes | Yes | ## The usual retirement order 1. Add the new version and make it the storage version. 2. Set `deprecated: true` on the old one and tell users. 3. After a release or two, set `served: false`. 4. Migrate stored objects and remove the old entry once nothing is stored in it. ## Common confusions - Deprecation does **not** reject requests, and it does not convert stored data. - `served: false` is **not** removal: the entry, its schema and conversion from it are still in use. - A version can be stored without being served; the storage flag and the served flag are independent.
- Can a Kubernetes CRD version be the storage version while served: false?Yes. `storage` and `served` are independent: the API server can encode objects in a version that no client can request directly and convert them to the served versions on every request. It is unusual, but it lets you hide an internal representation. At least one version must still be served for clients to use the resource at all.
saying these in an interview costs you the question
- deprecated: true makes the API server reject requests at that version.
- Setting served: false deletes the objects stored in that version.
- deprecationWarning can be set on a version that is not deprecated.
- A deprecated CRD version is automatically removed after a set number of releases.