Working with the Kubernetes API
Tags: kubernetes, devops
Published: 2023-03-13 12:34:49

Kubernetes exposes a robust API that lets you control every aspect of the cluster.

Most of the time, it's hidden behind kubectl, but no one stops you from using it directly.

In this article, you will learn how to navigate and issue requests to the Kubernetes API with `curl` or your favourite programming language.

But first, let's recap how the Kubernetes API works.

When you type a command, kubectl:

- Validates the request client-side.
- Generate YAML on the file (e.g. `kubectl run`).
- Construct the runtime object.

![Client side validation in kubectl](https://res.cloudinary.com/learnk8s/image/upload/v1678674987/threads/work-with-api-2_hfz4f4.png)

At this point, kubectl just acted locally without issuing any request to the cluster.

As the next step, it queries the current API server and discovers all available API endpoints.

![OpenAPI discovery in kubectl](https://res.cloudinary.com/learnk8s/image/upload/v1678674986/threads/work-with-api-3_vbno7i.png)

**Finally, kubectl uses the runtime objected and endpoints to negotiate the correct API call.**

If your resource is a Pod, kubectl reads the `apiVersion` and `kind` fields and ensures those are available and supported in the cluster.

Then it sends the request.

![API negotiation in kubectl](https://res.cloudinary.com/learnk8s/image/upload/v1678674986/threads/work-with-api-4_wepmxe.png)

**It's important to understand that APIs in Kubernetes are grouped.**

To further segregate multiple versions, resources are versioned.

![Kubernetes API groups, versions and resources](https://res.cloudinary.com/learnk8s/image/upload/v1678674986/threads/work-with-api-5_gwltue.png)

Now that you mastered the basics, let's look at an example.

You can start a local tunnel to the API server with `kubectl proxy`.

_But how can you retrieve all deployments?_

![Starting a proxy to the Kubernetes API](https://res.cloudinary.com/learnk8s/image/upload/v1678674986/threads/work-with-api-6_uov3ll.png)

Deployments belong to the "app" group and have a `v1` version.

You can list them with: `curl localhost:8001/apis/apps/v1/namespaces/{namespace}/deployments`.

![List deployments in Kubernetes with curl](https://res.cloudinary.com/learnk8s/image/upload/v1678674987/threads/work-with-api-7_tl7yva.png)

_What about listing all running pods?_

Pods belong to the `""` (empty) group and have a `v1` version.

You can list them with: `curl localhost:8001/api/v1/namespaces/{namespace}/pods`.

![Listing pods in Kubernetes with curl](https://res.cloudinary.com/learnk8s/image/upload/v1678674987/threads/work-with-api-8_zkgdnb.png)

_The empty group is… weird — are there more exceptions?_

**Well, the reality is that there's an easier way to construct URLs.**

I usually use [the Kubernetes API reference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.26/#list-pod-v1-core) as the paths are all neatly listed.

Let's look at another example but this time with the help of the API reference.

_What if you want to be notified of changes to the pod?_

That's called "watch" in the API, and the command is: `GET /api/v1/watch/namespaces/{namespace}/pods/{name}`.

![Watching for changes to pods with curl](https://res.cloudinary.com/learnk8s/image/upload/v1678675203/threads/watch_pbnfu7.png)

_Great, but what's the point of all of this?_

**Accessing the API directly allows you to build scripts to automate tasks.**

Or you can build your own kubernetes extensions.

Let me show you.

[This is a small kubernetes dashboard in ~130 lines of Javascript.](https://github.com/learnk8s/k8bit)

![A simple Kubernetes dashboard in Javascript](https://res.cloudinary.com/learnk8s/image/upload/v1678674562/threads/preview-k8bit_cwardt.gif)

It uses 2 API calls:

1. List all pods.
1. Watch for changes to pods.

The remaining code is used to group and display the nodes.

**In Kubernetes, combining the listing and updating resources is so common that it's a pattern called shared informer.**

The Javascript/Typescript API has an excellent example of the [shared informer in action](https://github.com/kubernetes-client/javascript/blob/master/examples/typescript/informer/informer.ts).

But it's just a fancy name for 2 GET requests (and some caching).

**The API doesn't stop at reading resources.**

You can also create new resources and amend existing ones.

For example, you can amend the replicas for a deployment with: `PATCH /apis/apps/v1/namespaces/{namespace}/deployments/{name}`.

![Patching Kubernetes deployments with curl](https://res.cloudinary.com/learnk8s/image/upload/v1678674987/threads/work-with-api-10_lu5dkm.png)

To experiment, I built something… unconventional.

[xlskubectl is my attempt at controlling a kubernetes cluster using Excel/Google Sheets.](https://github.com/learnk8s/xlskubectl)

![Sheetops — controlling Kubernetes with a spreadsheet](https://res.cloudinary.com/learnk8s/image/upload/v1678674563/threads/preview-xlsctl_v3xlzv.gif)

The code is remarkably similar to the Javascript dashboard:

1. It uses the shared informer (almost).
2. It polls for updates from google sheets.
3. It renders everything as cells.

Is it a good idea? **Probably not.**

Hopefully, it helps you realize the potential of using the Kubernetes API directly.

**None of this code was written in Go — you can use any programming language.**

And finally, if you've enjoyed this thread, you might also like:

- The Kubernetes workshops that we run at Learnk8s https://learnk8s.io/training
- This collection of past threads https://twitter.com/danielepolencic/status/1298543151901155330
- The Kubernetes newsletter I publish every week https://learnk8s.io/learn-kubernetes-weekly