Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Groups and versions and kinds, oh my!

Before getting started with the API, talk about terminology a bit.

When discussing APIs in Kubernetes, 4 terms are often used: groups, versions, kinds, and resources.

Groups and versions

An API Group in Kubernetes is simply a collection of related functionality. Each group has one or more versions, which, as the name suggests, allow you to change how an API works over time.

Kinds and resources

Each API group-version contains one or more API types, called Kinds. While a Kind may change forms between versions, each form must be able to store all the data of the other forms, somehow (you can store the data in fields, or in annotations). This means that using an older API version will not cause newer data to be lost or corrupted. See the Kubernetes API guidelines for more information.

You’ll also hear mention of resources on occasion. A resource is simply a use of a Kind in the API. Often, there is a one-to-one mapping between Kinds and resources. For instance, the pods resource corresponds to the Pod Kind. However, sometimes, the same Kind may be returned by multiple resources. For instance, the Scale Kind is returned by all scale subresources, like deployments/scale or replicasets/scale. This is what allows the Kubernetes HorizontalPodAutoscaler to interact with different resources. With CRDs, however, each Kind will correspond to a single resource.

Notice that resources are always lowercase, and by convention are the lowercase form of the Kind.

So, how does that correspond to Go?

When referring to a kind in a particular group version, it is called a GroupVersionKind, or GVK for short. Same with resources and GVR. As you’ll see shortly, each GVK corresponds to a given root Go type in a package.

Now that the terminology is clear, actually create the API!

So, how can you create an API?

In the next section, Adding a new API, check how the tool helps you create your APIs with the command kubebuilder create api.

The goal of this command is to create a Custom Resource (CR) and Custom Resource Definition (CRD) for your Kind(s). To check it further see; Extend the Kubernetes API with CustomResourceDefinitions.

But, why create APIs at all?

New APIs are how you teach Kubernetes about your custom objects. Controller-gen uses the Go structs to generate a CRD which includes the schema for your data as well as tracking data like what the new type is called. You can then create instances of your custom objects which your controllers manage.

Your APIs and resources represent your solutions on the clusters. Basically, the CRDs are a definition of your customized Objects, and the CRs are an instance of it.

Ah, do you have an example?

Think about the classic scenario where the goal is to have an application and its database running on the platform with Kubernetes. Then, one CRD could represent the App, and another one could represent the DB. By having one CRD to describe the App and another one for the DB, you avoid hurting concepts such as encapsulation, the single responsibility principle, and cohesion. Damaging these concepts could cause unexpected side effects, such as difficulty in extending, reuse, or maintenance, just to mention a few.

In this way, you can create the App CRD which has its controller and which would be responsible for things like creating Deployments that contain the App and creating Services to access it and etc. Similarly, you could create a CRD to represent the DB, and deploy a controller that would manage DB instances.

Err, but what is that Scheme thing?

The Scheme you saw before is simply a way to keep track of what Go type corresponds to a given GVK (do not be overwhelmed by its godocs).

For instance, suppose you mark the "tutorial.kubebuilder.io/api/v1".CronJob{} type as being in the batch.tutorial.kubebuilder.io/v1 API group (implicitly saying it has the Kind CronJob).

Then, you can later construct a new &CronJob{} given some JSON from the API server that says

{
    "kind": "CronJob",
    "apiVersion": "batch.tutorial.kubebuilder.io/v1",
    ...
}

or properly look up the group version when you go to submit a &CronJob{} in an update.