VOOZH about

URL: https://thenewstack.io/living-with-kubernetes-api-lifecycles-and-you/

⇱ Living with Kubernetes: API Lifecycles and You - The New Stack


TNS
SUBSCRIBE
Join our community of software engineering leaders and aspirational developers. Always stay in-the-know by getting the most important news and exclusive content delivered fresh to your inbox to learn more about at-scale software development.
REQUIRED
It seems that you've previously unsubscribed from our newsletter in the past. Click the button below to open the re-subscribe form in a new tab. When you're done, simply close that tab and continue with this form to complete your subscription.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.
Welcome and thank you for joining The New Stack community!
Please answer a few simple questions to help us deliver the news and resources you are interested in.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Great to meet you!
Tell us a bit about your job so we can cover the topics you find most relevant.
REQUIRED
REQUIRED
REQUIRED
REQUIRED
REQUIRED
Welcome!

We’re so glad you’re here. You can expect all the best TNS content to arrive Monday through Friday to keep you on top of the news and at the top of your game.

What’s next?

Check your inbox for a confirmation email where you can adjust your preferences and even join additional groups.

Follow TNS on your favorite social media networks.

Become a TNS follower on LinkedIn.

Check out the latest featured and trending stories while you wait for your first TNS newsletter.

PREV
1 of 2
NEXT
VOXPOP
As a JavaScript developer, what non-React tools do you use most often?
Angular
0%
Astro
0%
Svelte
0%
Vue.js
0%
Other
0%
I only use React
0%
I don't use JavaScript
0%
Thanks for your opinion! Subscribe below to get the final results, published exclusively in our TNS Update newsletter:
NEW! Try Stackie AI
From clobbered drafts to real-time sync
Apr 14th 2026 10:00am, by David Moore
TypeScript 6.0 RC arrives as a bridge to a faster future
Mar 14th 2026 9:00am, by Darryl K. Taft
Mastra empowers web devs to build AI agents in TypeScript
Jan 28th 2026 11:00am, by Loraine Lawson
2021-02-09 08:25:45
Living with Kubernetes: API Lifecycles and You
contributed,sponsor-amazon-web-services-aws,sponsored,sponsored-post-contributed,
API Management / Cloud Native Ecosystem / Kubernetes

Living with Kubernetes: API Lifecycles and You

In this series, we’ll talk about what it takes to use Kubernetes — beyond creating a cluster and deploying applications.
Feb 9th, 2021 8:25am by Justin Garrison
👁 Featued image for: Living with Kubernetes: API Lifecycles and You
Feature image via Pixabay.
AWS sponsored this post.
This is part 1 of a series entitled Living with Kubernetes:
2. Cluster Upgrades
3. Multicluster Management
4. Debug Clusters in 8 Commands
5. 12 Commands to Debug Your Workloads
Justin Garrison
Justin is a Senior Developer Advocate at Amazon Web Services (AWS).
Welcome to Living with Kubernetes. In this series, we’ll talk about what it takes to use Kubernetes — beyond creating a cluster and deploying applications. We’ll look at what it takes to safely upgrade your clusters, explore tools that can help you manage multiple clusters, and discuss other considerations for using Kubernetes long term. This article is all about the Kubernetes API: what makes it great, how it can be extended with Custom Resources (CR), and what it means when parts of it are deprecated. 👁 Image
The Kubernetes API is the most powerful part of Kubernetes. It provides a predictable, extensible API for your infrastructure and applications. The predictability comes from well-designed usage patterns and strong contracts for stability. With those things in place, the API was always intended to be easily extensible and to change often. The end result is something you can rely on to drive complex control loops with minimal, declarative data. These control loops are the key to everything, from the Kubernetes scheduler to GitOps. They’re at the heart and soul of having reliable and scalable applications with Kubernetes. This pattern is so reliable that the industry has been adopting it for more uses than were originally imagined. It doesn’t matter if you’re using Kubernetes to deploy via the Cluster-API, running databases at scale via Vitess, or ordering a pizza with cruster-api. You can use the same Kubernetes primitives to solve business needs — or hunger needs. What makes the Kubernetes API so powerful, and what’s the best way to be a consumer as the API changes? Let’s look at how the API is changing and how that affects you as Kubernetes becomes a critical part of your infrastructure.

API Groups and Extensions

The Kubernetes API is made up of different groups. These groups allow for
  • Predictable API patterns
  • Progressive adoption of features by users
  • Independently defining resource scope and maturity
  • Unique API paths for specific use cases (e.g. pod/logs)
👁 Image
Originally, the Kubernetes API didn’t have groups. This functionality was later named the core group (sometimes called “legacy”). Resources in the core group proved to be hard to mature, because of the tight coupling between resources and version number. With all resources behind a single /apis/$VERSION/ path, it was difficult for users to use resources from different versions and maintain compatibility between controllers. Developing the API required more versions to mature resources, and extending the API was not possible until the addition of Third-Party Resources (TPR). As customers and vendors started adopting TPRs, various shortcomings were addressed, and TPRs were replaced with CustomResourceDefinitions (CRD).
Since its inception, Amazon Web Services (AWS) has been the best place for customers to build and run open source software in the cloud. AWS is proud to support open source projects, foundations, and partners.
Learn More
The latest from AWS
Hear more from our sponsor
CRDs are so successful that resources in the core group are slowly being moved into more specific API groups. Some API groups include apps, extensions and scheduling.k8s.io. You’ll see these groups in your spec files as part of the apiVersion field.
# batch is the group and v1 is the versionapiVersion: batch/v1
Other Kubernetes resources can be separated into namespaces. This shows up in the API as namespaces/$NAMESPACE in the following example:
/apis/$GROUP/$VERSION/namespaces/$NAMESPACE/$RESOURCES/$RESOURCE
This approach means we can perform predictable actions on a resource, such as reading all deployments in the “todo-list” namespace with the GET HTTP verb:
GET /apis/apps/v1/namespaces/todo-list/deployments
Or, we can read a specific deployment named “frontend” in the todo-list namespace with:
GET /apis/apps/v1/namespaces/todo-list/deployments/frontend
This pattern makes it incredibly easy to extend the API with new resource types and groups. You can use the apiextensions.k8s.io group to create your own Custom Resources (CRs), which will create brand new groups to use. Here’s a minimal example to create a group mine.k8s.io with a version v1alpha1 and a resource type sock.
apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: name: socks.mine.k8s.iospec: group: mine.k8s.io versions: v1alpha1 names: kind: Sock plural: socks scope: Namespaced
By submitting that small amount of data to the Kubernetes API, you will get the following API:
/apis/mine.k8s.io/v1alpha1/namespaces/$NAMESPACE/socks/$SOCK
We can immediately check which sock resources we have with kubectl get socks --all-namespaces. These constructs keep the API flexible enough to grow for unknown use cases and simple enough to understand and be approachable.

CRD vs. Aggregation

One thing to point out is that Custom Resources allow the Kubernetes API to recognize custom resources, and the API path is part of the main kubernetes-api process. You can also extend the Kubernetes API with an aggregation API server to claim a specific path (e.g., /apis/socks.mine.co/v1). The main difference is that an aggregated API will proxy requests to a Kubernetes service endpoint. This means you will need to run a service inside your cluster that is responsible for state storage and version lifecycles. We won’t specifically talk about aggregated APIs, but it is important to know the difference when extending the API. 👁 Image
It’s important to become familiar with these concepts. In this article, we’re focusing not on how to use these things, but how to live with them. How Kubernetes adopts and grows the API is through strict contracts about how groups are versioned.

Versions and Lifecycles

Versions follow the group name as part of the URL path — or follow /apis/ in the case of the core group — and have defined guidelines about how things change from one version to another. These versions will show up in your yaml files after the group name in apiVersion. 👁 Image
Kubernetes follows a maturity progression of alpha → beta → stable with some additional versioning, so that a resource can iterate without needing to progress to the next level of maturity. An alpha resource can start at v1alpha1 and iterate with v1alpha2 or, if there are breaking changes, maybe v2alpha1. A beta API may be the same spec as an alpha API, but the maturity and contract with the user will be different.
  • Alpha APIs are experimental. They can have bugs and backward-incompatible changes. They are not enabled by default, and you should use them sparingly.
  • Beta APIs are well tested and enabled by default. They can be relied upon for future functionality, but their implementation may change based on user feedback or constraints such as scalability.
  • Stable APIs don’t have “beta” or “alpha” names. They are represented with a version (e.g., v1) and their implementation should not have breaking changes without changing the version number.
When a Kubernetes API is deprecated, it usually means that one of its versions is no longer available. The vast majority of deprecations have happened because:
  • Resource scheme changes (e.g., v1beta1 → v1beta2).
  • APIs have become more stable (e.g., v1alpha2 → v1beta1).
  • Group names have changed (e.g., ingress moved from extensions/v1beta1 to networking.k8s.io/v1beta1).
A deprecation means a version of the API has been removed, and you need to verify in your manifests and resources that you’re using the correct version of the API. In some cases, you may need to change your resource fields to update the new scheme for the resource. If an API is available in multiple versions at the same time, the Kubernetes API can silently upgrade some of them for you. However, you should still make sure you have the correct resource scheme — especially since as alpha APIs mature, the scheme may change between versions. These versions matter, because when you want to upgrade your Kubernetes API server, you need to make sure your resources — stored in etcd and in static manifests — match what is available in the server. This process gets very tricky when you have version skew in multiple clusters or environments. This step is also critical for your custom resources. Even if you don’t update your Kubernetes version, you can still have breaking changes between controllers and group versions if you don’t make sure to match or migrate them together.

Upgrading Kubernetes and Validating Manifests

You can get a list of API groups and versions from a running cluster with the command kubectl api-versions. The best part about doing this against a running cluster is that you can also see the custom resources and aggregated API groups you have. If you don’t have a running cluster, you can see the default groups and versions available in the API reference documentation. Change the API version to your target version in the URL. If you want to verify your static manifest files against a specific Kubernetes API version, check out pluto. You can back up static manifests from a running cluster with a tool like velero, or you can run pluto wherever you store your deployment manifests. Pluto can read a directory of files and let you know if there are deprecations against a specific Kubernetes version.
pluto detect-files -d ./ --target-versions k8s=v1.20.0NAME KIND VERSION REPLACEMENT REMOVED DEPRECATED targetgroupbindings.elbv2.k8s.aws CustomResourceDefinition apiextensions.k8s.io/v1beta1 apiextensions.k8s.io/v1 true true echo Ingress extensions/v1beta1 networking.k8s.io/v1beta1 false true echo Ingress extensions/v1beta1 networking.k8s.io/v1beta1 false true
Pluto can also help with default resource types but not custom API groups from CRDs or aggregated APIs. Running Pluto is a good smoke test to validate configs before updating your API server, or before deploying existing manifests to a new cluster. Pluto can help with default groups and versions, but how do you upgrade your custom resources? If you’re using or creating CRDs via helm, you can check out its documentation on how to best use them. If you’re using CRDs from third-party vendors, you should check their documentation on how to handle upgrades. If you want to compare CRDs in an open source project from one release to another, check out docs.crds.dev. It will help you quickly see which CRDs are included in the project — including what API group and version. If you need to validate more than just API version differences, you should also look at kubeval and conftest. These tools can help validate manifest files based on scheme documents or open policy agent.

Custom Resources

For Custom Resources that you create, here’s how you can handle upgrades and deprecations. Testing your CR upgrades is important, in order to make sure your controllers are able to function properly with the custom resource and the Kubernetes API groups and versions. CR definitions may or may not need to be updated when you update your controllers for scheme and API version changes. CustomResourceDefinitions can have multiple versions defined inside their specification. This approach allows the Kubernetes API to serve multiple versions at the same time. Using our socks example from earlier with version v1alpha1, if we wanted to also serve a v1beta1 version of the API, we can define that with:
apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata: name: socks.mine.k8s.iospec: group: mine.k8s.io versions: - v1alpha1 served: true storage: false schema: ... - v1beta1 served: true storage: true schema: ... names: kind: Sock plural: socks scope: Namespaced
This specification means both /apsi/mine.k8s.io/v1alpha1/ and /apis/mine.k8s.io/v1beta1/ will be served from the API. When a new “sock” object is created, it will be stored in etcd as v1beta1 because of the storage: true under the v1beta1 version. Only one version can be stored in etcd. If your versions have scheme changes, you’ll need to modify the resources when they’re submitted to the API. This step is handled via a conversion webhook. The webhook is responsible for reading the resource and converting the scheme to a different version and sending it back to the API server. You can add the conversion webhook spec to your CR like this:
conversion: strategy: Webhook webhook: clientConfig: url: "https://socks.converter.example/convert-me"
Any time a sock resource is created in the Kubernetes API server, its specification will be sent to the URL specified for conversion. The conversion webhook should do whatever is necessary to the resource and send it back to the API server as a ConversionReview object. Using webhooks for conversion allows a lot of flexibility to manage CR lifecycles and lets you slowly migrate from one version to another as needed. 👁 Image
A CR with a conversion webhook requires the same amount of components as an aggregation API, but with CRs you can take advantage of etcd to store your objects. Plus the default API patterns can simplify how much you need to maintain. Once all of your resources have been updated, you can deprecate an old version by using deprecated: true in the CR definition version. Deprecated versions will still be served by the API, but they will print a warning when resources are submitted to the API server using the deprecated version.

Conclusion

Kubernetes API was designed to change. One of its core strengths is to be flexible in any environment. Being aware of which groups and versions your resources are using is a responsibility users have in order to make sure their resources are compatible with the current Kubernetes API. In many cases, resources can be transparently modified and stored as newer resources without any user action. This capability allows users to be more confident in API upgrades and allows for gradual scheme changes. No matter whether you verify your resources statically with a tool like pluto or automatically convert your resources with a conversion webhook, it’s important to make sure you are able to safely migrate your resources from one version to another. Adding these tests early will help give you confidence as you use Kubernetes long term.
Since its inception, Amazon Web Services (AWS) has been the best place for customers to build and run open source software in the cloud. AWS is proud to support open source projects, foundations, and partners.
Learn More
The latest from AWS
Hear more from our sponsor
TRENDING STORIES
Justin serves as Head of Product at Sidero Labs and hosts the Ship It! podcast, where he helps demystify infrastructure and make it more accessible. His career includes contributions to Oscar-winning films, the Disney+ streaming platform, and Amazon EKS. In...
Read more from Justin Garrison
AWS sponsored this post.
SHARE THIS STORY
TRENDING STORIES
TNS owner Insight Partners is an investor in: Pragma.
SHARE THIS STORY
TRENDING STORIES
TNS DAILY NEWSLETTER Receive a free roundup of the most recent TNS articles in your inbox each day.
The New Stack does not sell your information or share it with unaffiliated third parties. By continuing, you agree to our Terms of Use and Privacy Policy.