API Versions
In the Kubernetes API, there is the concept of API versioning; that is, the Kubernetes API supports multiple versions of a type of resource. These different versions may act differently. Each one has a different API path, such as /api/v1 or /apis/extensions/v1beta1.
The different API versions differ in terms of stability and support:
- Alpha: This version is indicated by alpha in the apiVersion field—for example, /apis/batch/v1alpha1. The alpha version of resources is disabled by default as it is not intended for production clusters but can be used by early adopters and developers who are willing to provide feedback and suggestions and report bugs. Also, support for alpha resources may be dropped without notice by the time the final stable version of Kubernetes is finalized.
- Beta: This version is indicated by beta in the apiVersion field—for example, /apis/certificates.k8s.io/v1beta1. The beta version of resources is enabled by default, and the code behind it is well tested. However, using it is recommended for scenarios that are not business-critical because it is possible that changes in subsequent releases may reduce incompatibilities; that is, some features may not be supported for a long time.
- Stable: For these versions, the apiVersion field just contains the version number without any mention of alpha or beta—for example, /apis/networking.k8s.io/v1. The Stable version of resources is supported for many subsequent versions releases of Kubernetes. So, this version of API resources is recommended for any critical use cases.
You can get a complete list of the API versions enabled in your cluster by using the following command:
kubectl api-versions
You should see a response similar to this:
An interesting thing that you may observe in this screenshot is that some API resources, such as autoscaling, have multiple versions; for example, for autoscaling, there is v1beta1, v1beta2, and v1. So, what is the difference between them and which one should you use?
Let's again consider the example of autoscaling. This feature allows you to scale the number of pods in a replication controller, such as Deployments, ReplicaSets, or StatefulSets, based on specific metrics. For example, you can autoscale the number of pods from 3 to 10 if the average CPU load exceeds 50%.
In this case, the difference in the versions is that of feature support. The Stable release for autoscaling is autoscaling/v1, which only supports scaling the number of pods based on the average CPU metric. The beta release for autoscaling, which is autoscaling/v2beta1, supports scaling based on CPU and memory utilization. The newer version in the beta release, which is autoscaling/v2beta2, supports scaling the number of pods based on custom metrics in addition to CPU and memory. However, since the beta release is still not meant to be used for business-critical scenarios when you create an autoscaling resource, it will use the autoscaling/v1 version. However, you can still use other versions to use additional features by specifying the beta version in the YAML file until the required features are added to the stable release.
All of this information can seem overwhelming. However, Kubernetes provides ways to access all the information you need to navigate your way around the API resources. You can use kubectl to access the Kubernetes docs and get the necessary information about the various API resources. Let's see how that works in the following exercise.
Exercise 4.02: Getting Information about API Resources
Let's say that we want to create an ingress object. For the purposes of this exercise, you don't need to know much about ingress; we will learn about it in the upcoming chapters.
We will use kubectl to get more information about the Ingress API resource, determine which API versions are available, and find out which groups it belongs to. If you recall from previous sections, we need this information for the apiVersion field of our YAML manifest. Then, we also get the information required for the other fields of our manifest file:
- Let's first ask our cluster for all the available API resources that match the ingresses keyword:
kubectl api-resources | grep ingresses
This command will filter the list of all the API resources by the ingresses keyword. You should get the following output:
ingresses ing extensions true Ingress
ingresses ing networking.k8s.io true Ingress
We can see that we have ingress resources on two different API groups—extensions and networking.k8s.io.
- We have also seen how we can get API resources belonging to specific groups. Let's check the API groups that we saw in the previous step:
kubectl api-resources --api-group="extensions"
You should get the following output:
NAME SHORTNAMES APIGROUP NAMESPACED KIND
ingresses ing extensions true Ingress
Now, let's check the other group:
kubectl api-resources --api-group="networking.k8s.io"
You should see the following output:
However, if we were to use an ingress resource, we still don't know whether we should use the one from the extensions group or the networking.k8s.io group. In the next step, we will get some more information that will help us decide that.
- Use the following command to get more information:
kubectl explain ingress
You should get this response:
As you can see, the kubectl explain command describes the API resource, as well as the details about the fields associated with it. We can also see that ingress uses the extensions/v1beta1 API version, but if we read the DESCRIPTION, it mentions that this group version of ingress is deprecated by networking.k8s.io/v1beta1. Deprecated means that the standard is in the process of being phased out, and even though it is currently supported, it is not recommended for use.
Note
If you compare this to the different versions of autoscaling that we saw just before this exercise, you may think that the logical upgrade path from v1beta would be v2beta, and that would totally make sense. However, the ingress resource was moved from the extensions group to the networking.k8s.io group, and so this bucks the naming trend.
- It is not a good idea to use a deprecated version, so let's say that you want to use the networking.k8s.io/v1beta1 version instead. However, we need to get more information about it first. We can add a flag to the kubectl explain command to get information about a specific version of an API resource, as follows:
kubectl explain ingress --api-version=networking.k8s.io/v1beta1
You should see this response:
- We can also filter the output of the kubectl explain command by using the JSONPath identifier. This allows us to get information about the various fields that we need to specify while defining the YAML manifest. So, for example, if we would like to see the spec fields for Ingress, the command will be as follows:
kubectl explain ingress.spec --api-version=networking.k8s.io/v1beta1
This should give a response as follows:
- We can pe deeper to get more details about the nested fields. For example, if you wanted to get more details about the backend field of ingress, we can specify ingress.spec.backend to get the required information:
kubectl explain ingress.spec.backend --api-version=networking.k8s.io/v1beta1
This will give the following output:
Similarly, we can repeat this for any field that you need information about, which is handy for building or modifying a YAML manifest. So, we have seen that the kubectl explain command is very useful when you are looking for more details and documentation about an API resource. It is also very useful when creating or modifying objects using YAML manifest files.
How to Enable/Disable API Resources, Groups, or Versions
In a typical cluster, not all API groups are enabled by default. It depends on the cluster use case as determined by the administrators. For example, some Kubernetes cloud providers disable resources that use the alpha level for stability and security reasons. However, those can still be enabled on the API server by using the --runtime-config flag, which accepts comma-separated lists.
To be able to create any resource, the group and version should be enabled in the cluster. For example, when you try to create a CronJob that uses apiVersion: batch/v2alpha1 in its manifest file, if the group/version is not enabled, you will get an error similar to the following:
No matches for kind "CronJob" in version "batch/v2alpha1".
To enable batch/v2alpha1, you will need to set --runtime-config=batch/v2alpha1 on the API server. This can be done either during the creation of the cluster or by updating the /etc/kubernetes/manifests/kube-apiserver.yaml manifest file. The flag also supports disabling an API group or version by setting a false value to the specific version—for example, --runtime-config=batch/v1=false.
--runtime-config also supports the api/all special key, which is used to control all API versions. For example, to turn off all API versions except v1, you can pass the --runtime-config=api/all=false,api/v1=true flag. Let's try our own hands-on example of creating and disabling API groups and versions in the following exercise.
Exercise 4.03: Enabling and Disabling API Groups and Versions on a Minikube Cluster
In this exercise, we will create specific API versions while starting up Minikube, disable certain API versions in our running cluster, and then enable/disable resources in an entire API group:
- Start Minikube with the flag shown in the following command:
minikube start --extra-config=apiserver.runtime-config=batch/v2alpha1
You should see the following response:
Note
You can refer to the minikube start documentation for further details about the --extra-config flag, at https://minikube.sigs.k8s.io/docs/handbook/config/.
- You can confirm it is enabled by checking the details about the kube-apiserver-minikube pod. Use the describe pod command and filter the results by the runtime keyword:
kubectl describe pod kube-apiserver-minikube -n kube-system | grep runtime
You should see the following response:
--runtime-config=batch/v2alpha1
- Another way to confirm this is by looking at the enabled API versions by using the following command:
kubectl api-versions | grep batch/v2alpha1
You should see the following response:
batch/v2alpha1
- Now, let's create a resource called a CronJob, which uses batch/v2alpha1 to confirm that our API server accepts the API. Create a file named sample-cronjob.yaml with the following contents:
apiVersion: batch/v2alpha1
kind: CronJob
metadata:
name: hello
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: hello
image: busybox
args:
- /bin/sh
- -c
- date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure
- Now, create a CronJob by using this YAML file:
kubectl create -f sample-cronjob.yaml
You should see the following output:
cronjob.batch/hello created
As you can see, the API server accepted our YAML file and the CronJob is created successfully.
- Now, let's disable batch/v2alpha1 on our cluster. To do that, we need to access the Minikube virtual machine (VM) using SSH, as demonstrated in previous chapters:
minikube ssh
You should see this response:
- Open the API server manifest file. This is the template Kubernetes uses for the API server pods. We will use vi to modify this file, although you can use any text editor of your preference:
sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml
You should see a response like the following:
Look for the line that contains --runtime-config=batch/v2alpha1 and change it to --runtime-config=batch/v2alpha1=false. Then, save the modified file.
- End the SSH session by using the following command:
exit
- For the changes in the API server manifest to take effect, we need to restart the API server and the controller manager. Since these are deployed as stateless pods, we can simply delete them and they will automatically get deployed again. First, let's delete the API server by running this command:
kubectl delete pods -n kube-system -l component=kube-apiserver
You should see this output:
pod "kube-apiserver-minikube" deleted
Now, let's delete the controller manager:
kubectl delete pods -n kube-system -l component=kube-controller-manager
You should see this output:
pod "kube-controller-manager-minikube" deleted
Note that for both of these commands, we did not delete the pods by their names. The -l flag looks for labels. These commands deleted all the pods in the kube-system namespace that had labels that match the ones specified after the -l flag.
- We can confirm that batch/v2alpha1 is no longer shown in API versions by using the following command:
kubectl api-versions | grep batch/v2alpha1
This command will not give you any response, indicating that we have disabled batch/v2alpha1.
So, we have seen how we can enable or disable a specific group or version of API resources. But this is still a broad approach. What if you wanted to disable a specific API resource?
For our example, let's say that you want to disable ingress. We saw in the previous exercise that we have ingresses in the extensions as well as networking.k8s.io API groups. If you are targeting a specific API resource, you need to specify its group and version. Let's say that you want to disable ingress from the extensions group because it is deprecated. In this group, we have just one version of ingresses, which is v1beta, as you can observe from Figure 4.33.
To achieve this, all we have to do is modify the --runtime-config flag to specify the resource that we want. So, if we wanted to disable ingress from the extensions group, the flag would be as follows:
--runtime-config=extensions/v1beta1/ingresses=false
To disable the resource, we can use this flag when starting up Minikube, as shown in step 1 of this exercise, or we can add this line to the API server's manifest file, as shown in step 7 of this exercise. Recall from this exercise that if we instead want to enable the resource, we just need to remove the =false part from the end of this flag.