API Deprecation Checker
Find deprecated apiVersions in pasted manifests and get the exact replacement — entirely on this device.
Multi-document YAML is fine — separate manifests with ---. Everything is checked in your browser; nothing you paste leaves this page.
Paste manifests and pick a target version to see which apiVersions are deprecated or removed there, and what to migrate each one to.
The tables below are the guide's removal history, one wave per release. Every row links its own section of the official guide.
Removed in v1.16
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| extensions/v1beta1 | NetworkPolicy | networking.k8s.io/v1 | v1.9 | v1.16 | Migrate to networking.k8s.io/v1, served since v1.8. | Guide |
| extensions/v1beta1 | DaemonSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta2 | DaemonSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| extensions/v1beta1 | Deployment | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta1 | Deployment | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta2 | Deployment | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta1 | StatefulSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta2 | StatefulSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| extensions/v1beta1 | ReplicaSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta1 | ReplicaSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| apps/v1beta2 | ReplicaSet | apps/v1 | v1.9 | v1.16 | Migrate to apps/v1, served since v1.9. | Guide |
| extensions/v1beta1 | PodSecurityPolicy | no direct replacement | v1.11 | v1.16 | PodSecurityPolicy has no direct replacement API — migrate to Pod Security Admission (the built-in PodSecurity admission controller) or a third-party policy agent. The guide's own v1.16 target, policy/v1beta1, was itself removed in v1.25. | Guide |
Removed in v1.22
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| admissionregistration.k8s.io/v1beta1 | MutatingWebhookConfiguration | admissionregistration.k8s.io/v1 | v1.16 | v1.22 | Migrate to admissionregistration.k8s.io/v1, served since v1.16. | Guide |
| admissionregistration.k8s.io/v1beta1 | ValidatingWebhookConfiguration | admissionregistration.k8s.io/v1 | v1.16 | v1.22 | Migrate to admissionregistration.k8s.io/v1, served since v1.16. | Guide |
| apiextensions.k8s.io/v1beta1 | CustomResourceDefinition | apiextensions.k8s.io/v1 | v1.16 | v1.22 | Migrate to apiextensions.k8s.io/v1, served since v1.16 — a structural schema is required. | Guide |
| apiregistration.k8s.io/v1beta1 | APIService | apiregistration.k8s.io/v1 | v1.19 | v1.22 | Migrate to apiregistration.k8s.io/v1, served since v1.10. | Guide |
| authentication.k8s.io/v1beta1 | TokenReview | authentication.k8s.io/v1 | v1.19 | v1.22 | Migrate to authentication.k8s.io/v1, served since v1.6. | Guide |
| authorization.k8s.io/v1beta1 | SubjectAccessReview | authorization.k8s.io/v1 | v1.19 | v1.22 | Migrate to authorization.k8s.io/v1, served since v1.6. | Guide |
| authorization.k8s.io/v1beta1 | LocalSubjectAccessReview | authorization.k8s.io/v1 | v1.19 | v1.22 | Migrate to authorization.k8s.io/v1, served since v1.6. | Guide |
| authorization.k8s.io/v1beta1 | SelfSubjectAccessReview | authorization.k8s.io/v1 | v1.19 | v1.22 | Migrate to authorization.k8s.io/v1, served since v1.6. | Guide |
| authorization.k8s.io/v1beta1 | SelfSubjectRulesReview | authorization.k8s.io/v1 | v1.19 | v1.22 | Migrate to authorization.k8s.io/v1, served since v1.6. | Guide |
| certificates.k8s.io/v1beta1 | CertificateSigningRequest | certificates.k8s.io/v1 | v1.19 | v1.22 | Migrate to certificates.k8s.io/v1, served since v1.19 — spec.signerName is required. | Guide |
| coordination.k8s.io/v1beta1 | Lease | coordination.k8s.io/v1 | v1.19 | v1.22 | Migrate to coordination.k8s.io/v1, served since v1.14. | Guide |
| extensions/v1beta1 | Ingress | networking.k8s.io/v1 | v1.14 | v1.22 | Migrate to networking.k8s.io/v1, served since v1.19 — spec.backend becomes spec.defaultBackend, backend serviceName/servicePort become service.name and service.port.name or service.port.number, and each path needs a pathType. | Guide |
| networking.k8s.io/v1beta1 | Ingress | networking.k8s.io/v1 | v1.19 | v1.22 | Migrate to networking.k8s.io/v1, served since v1.19 — spec.backend becomes spec.defaultBackend, backend serviceName/servicePort become service.name and service.port.name or service.port.number, and each path needs a pathType. | Guide |
| networking.k8s.io/v1beta1 | IngressClass | networking.k8s.io/v1 | v1.19 | v1.22 | Migrate to networking.k8s.io/v1, served since v1.19. | Guide |
| rbac.authorization.k8s.io/v1beta1 | ClusterRole | rbac.authorization.k8s.io/v1 | v1.17 | v1.22 | Migrate to rbac.authorization.k8s.io/v1, served since v1.8. | Guide |
| rbac.authorization.k8s.io/v1beta1 | ClusterRoleBinding | rbac.authorization.k8s.io/v1 | v1.17 | v1.22 | Migrate to rbac.authorization.k8s.io/v1, served since v1.8. | Guide |
| rbac.authorization.k8s.io/v1beta1 | Role | rbac.authorization.k8s.io/v1 | v1.17 | v1.22 | Migrate to rbac.authorization.k8s.io/v1, served since v1.8. | Guide |
| rbac.authorization.k8s.io/v1beta1 | RoleBinding | rbac.authorization.k8s.io/v1 | v1.17 | v1.22 | Migrate to rbac.authorization.k8s.io/v1, served since v1.8. | Guide |
| scheduling.k8s.io/v1beta1 | PriorityClass | scheduling.k8s.io/v1 | v1.14 | v1.22 | Migrate to scheduling.k8s.io/v1, served since v1.14. | Guide |
| storage.k8s.io/v1beta1 | CSIDriver | storage.k8s.io/v1 | v1.19 | v1.22 | Migrate to storage.k8s.io/v1 — CSIDriver is served there since v1.19. | Guide |
| storage.k8s.io/v1beta1 | CSINode | storage.k8s.io/v1 | v1.17 | v1.22 | Migrate to storage.k8s.io/v1 — CSINode is served there since v1.17. | Guide |
| storage.k8s.io/v1beta1 | StorageClass | storage.k8s.io/v1 | v1.19 | v1.22 | Migrate to storage.k8s.io/v1 — StorageClass is served there since v1.6. | Guide |
| storage.k8s.io/v1beta1 | VolumeAttachment | storage.k8s.io/v1 | v1.19 | v1.22 | Migrate to storage.k8s.io/v1 — VolumeAttachment is served there since v1.13. | Guide |
Removed in v1.25
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| batch/v1beta1 | CronJob | batch/v1 | v1.21 | v1.25 | Migrate to batch/v1, served since v1.21. | Guide |
| discovery.k8s.io/v1beta1 | EndpointSlice | discovery.k8s.io/v1 | v1.21 | v1.25 | Migrate to discovery.k8s.io/v1, served since v1.21 — per-endpoint topology moves to nodeName/zone. | Guide |
| events.k8s.io/v1beta1 | Event | events.k8s.io/v1 | v1.19 | v1.25 | Migrate to events.k8s.io/v1, served since v1.19. | Guide |
| autoscaling/v2beta1 | HorizontalPodAutoscaler | autoscaling/v2 | v1.22 | v1.25 | Migrate to autoscaling/v2, served since v1.23. | Guide |
| policy/v1beta1 | PodDisruptionBudget | policy/v1 | v1.21 | v1.25 | Migrate to policy/v1, served since v1.21 — an empty spec.selector now selects every pod in the namespace. | Guide |
| policy/v1beta1 | PodSecurityPolicy | no direct replacement | v1.21 | v1.25 | PodSecurityPolicy has no direct replacement API — migrate to Pod Security Admission (the built-in PodSecurity admission controller) or a third-party policy agent. | Guide |
| node.k8s.io/v1beta1 | RuntimeClass | node.k8s.io/v1 | v1.20 | v1.25 | Migrate to node.k8s.io/v1, served since v1.20. | Guide |
Removed in v1.26
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| flowcontrol.apiserver.k8s.io/v1beta1 | FlowSchema | flowcontrol.apiserver.k8s.io/v1 | v1.23 | v1.26 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29 — the guide's contemporaneous beta targets were themselves removed later. | Guide |
| flowcontrol.apiserver.k8s.io/v1beta1 | PriorityLevelConfiguration | flowcontrol.apiserver.k8s.io/v1 | v1.23 | v1.26 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29 — the guide's contemporaneous beta targets were themselves removed later. For PriorityLevelConfiguration, spec.limited.assuredConcurrencyShares is renamed to spec.limited.nominalConcurrencyShares in v1. | Guide |
| autoscaling/v2beta2 | HorizontalPodAutoscaler | autoscaling/v2 | v1.23 | v1.26 | Migrate to autoscaling/v2, served since v1.23. | Guide |
Removed in v1.27
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| storage.k8s.io/v1beta1 | CSIStorageCapacity | storage.k8s.io/v1 | v1.24 | v1.27 | Migrate to storage.k8s.io/v1 — CSIStorageCapacity is served there since v1.24. | Guide |
Removed in v1.29
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| flowcontrol.apiserver.k8s.io/v1beta2 | FlowSchema | flowcontrol.apiserver.k8s.io/v1 | v1.26 | v1.29 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29 — the guide's contemporaneous beta targets were themselves removed later. | Guide |
| flowcontrol.apiserver.k8s.io/v1beta2 | PriorityLevelConfiguration | flowcontrol.apiserver.k8s.io/v1 | v1.26 | v1.29 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29 — the guide's contemporaneous beta targets were themselves removed later. For PriorityLevelConfiguration, spec.limited.assuredConcurrencyShares is renamed to spec.limited.nominalConcurrencyShares in v1. | Guide |
Removed in v1.32
| API version | Kind | Replacement | Deprecated in | Removed in | How to migrate | Source |
|---|---|---|---|---|---|---|
| flowcontrol.apiserver.k8s.io/v1beta3 | FlowSchema | flowcontrol.apiserver.k8s.io/v1 | v1.29 | v1.32 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29. | Guide |
| flowcontrol.apiserver.k8s.io/v1beta3 | PriorityLevelConfiguration | flowcontrol.apiserver.k8s.io/v1 | v1.29 | v1.32 | Migrate to flowcontrol.apiserver.k8s.io/v1, served since v1.29. For PriorityLevelConfiguration, spec.limited.assuredConcurrencyShares is renamed to spec.limited.nominalConcurrencyShares in v1. | Guide |
Do it offline:$
How to use it
- Paste one or more manifests into the field. Multi-document YAML works as-is — keep the --- separators and the checker reads each document on its own. Press / to focus the field.
- Pick the target version: the release your cluster runs today, or the one you are upgrading to. The verdict is computed against that exact version, so 1.24 and 1.25 can answer differently.
- Read the findings. Removed means the target's API server no longer serves that apiVersion; Deprecated means it still works there but has a named removal release; each row shows the replacement to copy and the field changes to expect.
- Fix the manifests and paste again, or jump to the per-version tables below — every removal wave since v1.16 has its own anchored table with per-row links into the official guide.
An upgrade note says your cluster's next version stops serving old APIs, and your manifests are where the old apiVersions hide. Paste them here, pick the Kubernetes version you run or plan to reach, and every deprecated or removed apiVersion is flagged with its exact replacement and migration note — checked against the official deprecation guide's full removal history, entirely in your browser. The tables below hold every wave, v1.16 to v1.32.
Examples
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web
extensions/v1beta1 Ingress is no longer served at v1.22 — removed in v1.22. Migrate to networking.k8s.io/v1, served since v1.19 — spec.backend becomes spec.defaultBackend, backend serviceName/servicePort become service.name and service.port.name or service.port.number, and each path needs a pathType.The classic v1.22 break: this Ingress version is gone, and the replacement is not a search-and-replace — the finding names the fields that moved.
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: nightly
batch/v1beta1 CronJob is no longer served at v1.25 — removed in v1.25. Migrate to batch/v1, served since v1.21.A one-line fix: batch/v1 CronJob has the same shape, so changing the apiVersion string is usually the whole migration.
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: api
autoscaling/v2beta1 HorizontalPodAutoscaler is deprecated since v1.22 but still served at v1.24; it stops being served in v1.25. Migrate to autoscaling/v2, served since v1.23.The warning state: at a 1.24 target this manifest still applies, and the finding names the release where it stops.
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
apps/v1 Deployment matches no removal row — apps/v1 is a migration target the guide names as served.The clean state says what it can verify: no removal row matched, and apps/v1 is a replacement the guide itself names.
Every example on this page is executed against the same engine that powers the tool, on every build.
Gotchas worth knowing
PodSecurityPolicy has no replacement apiVersion
Every other row here migrates to a newer version of the same kind. PSP does not: it was removed in v1.25 with no direct replacement API. The successor is Pod Security Admission — the built-in PodSecurity admission controller configured per namespace — or a third-party policy agent, and this checker says so instead of inventing a target apiVersion.
Removed means no longer served, not deleted
Objects are stored version-independently. When a release stops serving batch/v1beta1, your existing CronJobs survive — the API server simply refuses requests that name the old version, which is why kubectl apply of an old manifest fails after the upgrade while the workload keeps running.
The deprecation window is the upgrade window
A Deprecated finding means the target release still serves that apiVersion. That window is the safe time to migrate: rewrite the manifest, apply it, and the upgrade to the removal release stops being an emergency.
The pack ends at the guide's published history
These rows cover the guide's removal waves through v1.32, and each carries its own citation. Later clusters inherit every earlier removal, so checking against v1.32 is the strictest answer this page can honestly give; new waves are appended when the guide publishes them, never predicted.
Common errors
extensions/v1beta1 Ingress is no longer served at v1.22 — removed in v1.22. Migrate to networking.k8s.io/v1, served since v1.19 — spec.backend becomes spec.defaultBackend, backend serviceName/servicePort become service.name and service.port.name or service.port.number, and each path needs a pathType.- KD_REMOVED, the error state: the target version's API server refuses this apiVersion, and the sentence carries the replacement plus the field moves.
autoscaling/v2beta1 HorizontalPodAutoscaler is deprecated since v1.22 but still served at v1.24; it stops being served in v1.25. Migrate to autoscaling/v2, served since v1.23.- KD_DEPRECATED, the warning state: still served at your target, with the removal release named so the migration can be scheduled.
example.com/v1 Widget is not in the curated pack — this pack covers the 24 deprecated or removed API versions on the official guide's removal history (v1.16–v1.32); CRDs and other groups are outside its scope.- KD_UNKNOWN_API, the honest boundary: CRDs and groups outside the guide's history get a named out-of-scope answer, never a false clean.
Nothing to check — paste at least one Kubernetes manifest.- KD_NO_DOCUMENTS: an empty or comment-only paste has nothing to classify, so the checker asks for a manifest instead of showing an empty pass.
Document 1 has no apiVersion field — nothing to check against the pack.- KD_MISSING_APIVERSION: deprecation is a property of the apiVersion string, so a document without one is reported as not checkable rather than silently skipped.
FAQ
What is the difference between a deprecated and a removed Kubernetes API?
Both describe an API version, not the resource itself. Deprecated means the version still works but a newer one is the supported path and a removal release has been announced; removed means the API server in that release no longer serves the version at all, so requests using it fail. Stored objects survive a removal — what breaks is every manifest and client still naming the old version.
Why does moving an Ingress to networking.k8s.io/v1 break my fields?
Because v1 renamed the backend shape rather than just the version string: spec.backend became spec.defaultBackend, serviceName and servicePort became service.name with service.port.name or service.port.number, and every path now needs an explicit pathType. An old Ingress manifest therefore fails validation after the apiVersion swap until those fields are rewritten.
How is this different from scanning my cluster with pluto or kubent?
This page reads only what you paste — it never connects to a cluster, which is also why nothing you paste leaves the browser. pluto and kubent talk to a live cluster or Helm releases and can find API versions recorded in release history that your local YAML no longer shows. Use this checker on manifests and charts before they ship; use a cluster scanner to audit what is already deployed.
Keyboard shortcuts
- /
- Focus the manifest field