Kubernetes API Server Discovery

A little excursion into the Kubernetes API server

Itchimonji
CP Massive Programming

--

Kubernetes API Server Discovery

The Kubernetes API server is the gateway to the cluster. The server is used by all users, automation, and components in the Kubernetes cluster. The API server implements a RESTful API over HTTP, and performs all API operations. It is also responsible for storing some API objects into a persistent storage backend.

When using kubectl, k9s, or any other CLI tool that communicates with a Kubernetes cluster, then this tool communicates with the API server.

The server itself is stateless, and any persistent state is stored in a database that is external to the API server.

Starting a local Kubernetes cluster

To send requests to an existing API server, we need to have a running Kubernetes cluster. For this, we can use kind to start a local docker-based Kubernetes cluster.

The following config will raise a cluster with one control plane node and two worker nodes.

# kind.config.yaml

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: api-server-discovery

nodes:
- role: control-plane
- role: worker
- role: worker

To start the cluster, we need to run the following command.

kind create cluster --config=kind.config.yaml
Logs of kind at the start

To delete all resources, we need to run the following command.

kind delete cluster --name api-server-discovery

We can also use another tool to start a local Kubernetes cluster. Here are some examples.

API Discovery

Now that we have a local cluster, we can send requests to the Kubernetes API server.

To make it easy to use the curl tool to explore the API server, run the kubectl tool in proxy mode to expose an unauthenticated API server on localhost:8001 using the following command. [“Managing Kubernetes” by Brendan Burns & Craig Tracey]

kubectl proxy

Now we can use the server to discover the API.

The most simple request is by examining the /api prefix.

curl --location --request GET 'http://localhost:8001/api'

The response is an API object with the type of APIVersions.

{
"kind": "APIVersions",
"versions": [
"v1"
],
"serverAddressByClientCIDRs": [
{
"clientCIDR": "0.0.0.0/0",
"serverAddress": "172.20.0.4:6443"
}
]
}

We can use this version to continue the discovery.

curl --location --request GET 'http://localhost:8001/api/v1'

The response of this call is much larger than the one before. We can see specific resources and their definitions.

{
"kind": "APIResourceList",
"groupVersion": "v1",
"resources": [
{
"name": "bindings",
"singularName": "",
"namespaced": true,
"kind": "Binding",
"verbs": [
"create"
]
},
{
"name": "componentstatuses",
"singularName": "",
"namespaced": false,
"kind": "ComponentStatus",
"verbs": [
"get",
"list"
],
"shortNames": [
"cs"
]
},
{
"name": "configmaps",
"singularName": "",
"namespaced": true,
"kind": "ConfigMap",
"verbs": [
"create",
"delete",
"deletecollection",
"get",
"list",
"patch",
"update",
"watch"
],
"shortNames": [
"cm"
],
"storageVersionHash": "qFsyl6wFWjQ="
},
...
]
}

We can continue this approach forever now.

The API distinguishes between 2 different resource paths: namespaced and non-namespaced.

Here are some examples of namespaced resource types.

# /api/v1/namespaces
curl --location --request GET 'http://localhost:8001/api/v1/namespaces'

# /api/v1/namespaces/{namespace-name}/{resource-type-name}
curl --location --request GET 'http://localhost:8001/api/v1/namespaces/kube-system/pods'

# /api/v1/namespaces/{namespace-name}/{resource-type-name}/{resource-name}
curl --location --request GET 'http://localhost:8001/api/v1/namespaces/kube-system/pods/coredns-565d847f94-bv45c'

# /api/v1/namespaces/{namespace-name}/{resource-type-name}/{resource-name}/logs
curl --location --request GET 'http://localhost:8001/api/v1/namespaces/kube-system/pods/coredns-565d847f94-bv45c/logs'

And here are some examples of non-namespaced resource types.

# /api/v1/{resource-type-name
curl --location --request GET 'http://localhost:8001/api/v1/persistentvolumes'

# /api/v1/{resource-type-name}
curl --location --request GET 'http://localhost:8001/api/v1/persistentvolumeclaims'

# /api/v1/{resource-type-name}/{resource-name}
curl --location --request GET 'http://localhost:8001/api/v1/persistentvolumeclaims/postgres-0'

Besides, by using GET to get information from the API server, we can use POST, or DELETE requests to manipulate objects at the API server.

If you want to know the REST call of your kubectl command, you can extend the command with -v=6.

# http://localhost:8001/api/v1/pods?limit=500 200 OK in 38 milliseconds
kubectl get pods -A -v=6

# http://localhost:8001/api/v1/namespaces?limit=500 200 OK in 96 milliseconds
kubectl get namespaces -A -v=6

# http://localhost:8001/api/v1/namespaces/kube-system/pods/metrics-server-5f9f776df5-rl996 200 OK in 98 milliseconds
kubectl get pod metrics-server-5f9f776df5-rl996 -n kube-system -v=6

Watch Operations

The API server also supports a watch API. Instead of polling in specific intervals for some updates, we can use the watch API to get low-latency updates with a single connection.

We only need to add ?watch=true as a parameter to our API server requests. After this, the API server switches into watch mode, and leaves the connection between the client and the server open.

OpenAPI Specification

The API server also provides information about the schema for all Kubernetes resources. The schema is represented by the Swagger syntax. We can receive the specification by running the following curl command.

curl --location --request GET 'http://localhost:8001/openapi/v2'

If we want to program a client that communicates with the API server, we can use this schema to generate a Swagger library in it.

Conclusion

Most Kubernetes tools like kubectl, or k9s interact with the Kubernetes API server. It is the central touchpoint that is accessed by all users, automation, and components in the Kubernetes cluster. If you want to learn more about the API Server, I recommend reading Managing Kubernetes by Brendan Burns & Craig Tracey.

Thanks for reading! Follow me on Medium, Twitter, or Instagram, or subscribe here on Medium to read more about DevOps, Agile & Development Principles, Angular, and other useful stuff. Happy Coding! :)

--

--

Itchimonji
CP Massive Programming

Freelancer | Site Reliability Engineer (DevOps) / Kubernetes (CKAD) | Full Stack Software Engineer | https://patrick-eichler.com/links