The Lesser Known Side of Kubernetes API

17 January 2022
REST
API
kubernetes

To learn what Kubernetes APIs are and to do RESTful Operations

The Kubernetes API server is one of the core components of the control plane which helps in exposing the Kubernetes API.

This API server serves different HTTP(REST) API endpoints which allows end-users to do different RESTful operations, to interact with different components of the cluster.

At the bottom level, everything in the Kubernetes cluster is treated as an API object and the Kubernetes API endpoints allows us to perform CRUD operations on these API objects.

Kubernetes API server provides different endpoints to which we can connect through different standard HTTP verbs such as POST, PUT, DELETE, GET, PATCH and kubectl CLI is one of the most common tools which users can use to communicate with the Kubernetes API.

The below command will give you the list of API endpoints to which you can connect to :

kubectl api-versions
Kubernetes API Model
Figure 1:Kubernetes API Model

API groups:

API groups in Kubernetes are a logical collection of related functionality. Kubernetes divides the endpoints into 2 subgroups: core API group and other API group.

  • The core (also called legacy) group is found at the REST path /api/v1
  • The named groups are found at the REST path /apis/$GROUP_NAME/$VERSION 

You can find the full list of supported API groups in Kubernetes API reference.

API request verbs:

As all object resource types support the standard HTTP verbs - GET, POST, PUT, PATCH, and DELETE and so Kubernetes also uses its own verbs, which are used in lowercase to differentiate them from HTTP verbs like get, list, create, update, patch, watch and delete.

Request URIs Format:

As resource types can be used and scoped either by a cluster (/apis/GROUP/VERSION/*) or by a namespace (/apis/GROUP/VERSION/namespaces/NAMESPACE/*). 

The resource is an identifier that receives and returns its corresponding kind. Resources also expose CRUD actions for that kind.

Cluster-scoped resources

  • GET /apis/GROUP/VERSION/RESOURCETYPE - return the collection of resources of the resource type
  • GET /apis/GROUP/VERSION/RESOURCETYPE/NAME - return the resource NAME under the resource type

Namespace-scoped resources

  • GET /apis/GROUP/VERSION/RESOURCETYPE - return the collection of all instances of the resource type across all namespaces
  • GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE - return a collection of all resource type instances in NAMESPACE
  • GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME - return the resource type instance with NAME in NAMESPACE

As Kubernetes API resources are divided into different API groups along with different scopes and sometimes it becomes difficult to remember all and to see which ones is supported in your Kubernetes cluster and in which scope.

And to help with these, one can run the following command to check:

kubectl api-resources -o wide

The above command helps in enumerating the resource types available in the cluster along with their respective scope and different HTTP verbs. 

A group is simply a collection of kinds. You can have kinds such as ReplicaSets, StatefulSets, and Deployments which are all part of the apps group.

Versions allow Kubernetes to release groups as tagged versions. Here are the versions that Kubernetes has available.

  • Alpha: This is usually disabled by default since it should only be used for testing. You may see labeled as v1alpha1
  • Beta: Enabled by default. You man see labeled as v1beta1 
  • Stable: These have reached maturity and will be around for further releases. You may see labeled as v1

One can also list down the API resources for a particular API group

kubectl api-resources --api-group apps -o wide
kubectl api-resources --api-group batch -o wide

Use Cases of using API endpoints:

1. Extract information out of K8s as JSON reply

2. Navigate through the JSON reply and extract information such as pod names, IPs, and many more.

3. Display information on the front end of a web app.

Lab with Kubernetes API

To start using Kubernetes APIs you need to turn on Kubernetes reverse proxy and run it in the background by specifying & with the following command.

kubectl proxy --port 8040 &

kubectl proxy is a server that handles certificates for us so that we don’t need to worry about auth tokens with curl.

The following list contains a few Kubernetes API endpoints to use after turning on the reverse proxy and the response value would be in JSON format.

  1. localhost:8040/api  to get the API version.
  2. localhost:8040/api/v1/namespaces to get all the namespaces in the k8s cluster
  3. localhost:8040/api/v1/pods to get all the pods in the k8s cluster (pods' IPs, names, where does it exist, etc...)
  4. localhost:8040/api/v1/namespaces/<namespace_name>/pods to get the pods exists in a given namespace 
  5. localhost:8040/api/services to get all the services exposed by k8s 
  6. localhost:8040/apis/app/namespaces/<name>/deployments to get the pods exists in a given namespace

As everything in Kubernetes is an object to which you can connect and perform CRUD operations .

Let’s start by creating a test namespace and a few pods inside that namespace.

kubectl create ns test
kubectl run nginx --image nginx -n test
kubectl run redis --image redis -n test

Performing GET and LIST operations

In Kubernetes terminology, the response you get from a LIST is a collection of resources and GET helps in retrieving a single resource.

When you query the API for a particular type, all items returned by that query are of that type. For example, when you list Pods, the collection response has a kind set to PodList; each item in that collection represents a single Pod. For example:

  • List all of the pods on a cluster
curl localhost:8040/api/v1/pods
Copy Code
Loading...
  • List all of the pods on a cluster on a specific namespace
curl localhost:8040/api/v1/namespaces/test/pods
Copy Code
Loading...

As we have to deal with a lot of data, we can use jq (jq is a Linux command-line utility that is easily used to extract data from JSON documents) to further improve readability.

sudo apt install jq -y
curl localhost:8040/api/v1/namespaces/test/pods/ | jq '.items[].metadata.name'

The /pods endpoint lists all the pods and if you want to query for a particular pod you can query with  /pods/<pod_name> endpoint .

curl localhost:8040/api/v1/namespaces/test/pods/nginx

Performing POST operation

In the case of post operations, you can send the payload as a JSON object.

A payload in API is the actual data pack that is sent with the methods in HTTP. It is the crucial information that you submit to the server when you are making an API request.

The payload can be sent or received in various formats, including JSON. Usually, the payload is denoted using the “{}” in a query string.

  • Create a specific namespace, let's say demo namespace

 You can send the below payload to  /api/v1/namespaces endpoint with a header of Content-Type = application/json

curl -v -XPOST  -H "User-Agent: kubectl/v1.22.2 (linux/amd64) kubernetes/8b5a191" -H "Accept: application/json, */*" -H "Content-Type: application/json" -d '{"kind": "Namespace", "apiVersion": "v1", "metadata": {"name": "demo"}}'  'http://localhost:8040/api/v1/namespaces?fieldManager=kubectl-create'

Similarly, we can create a deployment also inside a specific namespace. Here we are creating a redis deployment inside demo namespace

curl -v -XPOST  -H "Accept: application/json, */*" -H "Content-Type: application/json" -H "User-Agent: kubectl/v1.22.2 (linux/amd64) kubernetes/8b5a191" 'http://localhost:8040/apis/apps/v1/namespaces/demo/deployments?fieldManager=kubectl-create'  -d '{"kind":"Deployment","apiVersion":"apps/v1","metadata":{"name":"redis","namespace":"demo","creationTimestamp":null,"labels":{"app":"redis"}},"spec":{"replicas":1,"selector":{"matchLabels":{"app":"redis"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"redis"}},"spec":{"containers":[{"name":"redis","image":"redis","resources":{}}]}},"strategy":{}},"status":{}}'

Check for the pods and deployments using :

kubectl get pods -n demo
kubectl get deployments -n demo

Performing DELETE operation :

You can use the HTTP DELETE operation to delete a specific kind of resource. For example, you can delete a kind of pod within a namespace with a fieldselector(Read More) name as pod .

curl -XDELETE localhost:8040/api/v1/namespaces/test/pods/?fieldSelector=metadata.name=nginx

Check if the pod has been deleted or not using 

kubectl get pods -n test

Conclusion

In this hands-on lab, we have seen the Kubernetes API model and performed different CRUD operations on API endpoints.