Breaking Down The Kubernetes API
Tags: kubernetes, docker, git, cloud
Published: 2022-05-11 11:05:58

When an engineer, programming language, or CICD system is interacting with Kubernetes, it’s interacting with an API. 9 times out of 10 any time you interact with Kubernetes, you’re interacting directly with the API. Although it’s one API, there are many versions and groups to make sure all Kubernetes resources work efficiently.

In this blog post, you’ll learn about the Kubernetes API and how it works under the hood.

## Where The API Runs

In the opening section of this blog post, you read that any time you interact with Kubernetes, you’re interacting with an API. The API lives on the Control Plane, sometimes referred to as the API server or the Master Node. Depending on your Kubernetes environment, you may either be running Kubernetes in the cloud or on-prem.

If you’re running Kubernetes in the cloud, like AKS, GKE, or EKS, the Control Plane is completely abstracted from you. You have no control over it other than what version of the Kubernetes API it’s running. The scaling, management, and underlying infrastructure are handled by the cloud provider.

If you’re running Kubernetes on-prem, using something like k3s or Kubeadm, you’re deploying both the Control Plane(s) and the Worker Node(s). The Control Plane, when you deploy it, consists of the API server (amongst other components like etcd, kube-scheduler, etc.). The main implementation of the API in Kubernetes is called the kube-apiserver. It scales horizontally, as in, creates more Control Planes if needed. The core job of kube-apiserver is to validate objects like Pods, Deployments, etc... You’ll learn more about that in the upcoming section.

## How it Works

Typically when you’re interacting with Kubernetes, you’re most likely using the `kubectl` command, which is the Kubernetes CLI. Although many people use `kubectl`, there are many other ways to interact with Kubernetes. For example:

- If you’re on OpenShift, you can use the `oc` CLI or the `oda` CLI
- If you use Terraform, you can create Kubernetes Deployments, Pods, etc.
- If you use Python, Go, or any other programming language, you can create Kubernetes Deployments, Pods, etc.

The reason why this works is that even though they’re all different tools and methodologies for interacting with k8s, they’re doing the same thing; interacting with the Kubernetes API

When you use `kubectl`, Terraform, Python, or any other tool to create a resource in Kubernetes, all you’re doing is sending a `POST` request to the Kubernetes API.

When you’re calling resources that are already created to view them, like when running `kubectl get pods`, you’re sending a `GET` request to the Kubernetes API

Mostly everything in Kubernetes is API-centric.

## API Groups and Versioning

Now that you know how the API works and a few different ways to interact with the Kubernetes API, let’s dive a bit deeper into how the APIs themselves work. First, let’s talk about API groups and versions.

In the previous section, you learned that running commands like `kubectl get pods` reaches out to the Kubernetes API. Even though it’s typically one API, there are several API groups. The primary groups are:

- Core Group
- Named Group

Each group has a different API path, for example, `api/v1` or`/apis/rbac.authorization.k8s.io`. You’ll see an example of both in a Kubernetes Manifest in a second, but first, let's break down Core Group and Named Group.

The Core Group are all of the original Kubernetes resources. For example, Pods and Deployments. The Named Group are all of the new APIs, for example, RBAC and Ingress Controllers.

Below is an example of using the Core Group:

```jsx
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginxdeployment
  replicas: 2
  template:
    metadata:
      labels:
        app: nginxdeployment
    spec:
      containers:
      - name: nginxdeployment
        image: nginx:latest
        ports:
        - containerPort: 80
```

Below is an example of using the Named Group:

```jsx
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-nginxservice-a
spec:
  ingressClassName: nginx-servicea
  rules:
  - host: localhost
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginxservice
            port:
              number: 8080
```

As you can see, the way that you define the Kubernetes Manifest via YAML isn’t any different from a syntax perspective. The only difference is the API you’re using

You can check out the full Kubernetes API reference list [here](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/).

## API Extensions

Let’s say there’s something in Kubernetes that doesn’t currently exist. What do you do? Well, since Kubernetes is an open-source project, you can create extensions. These extensions are sometimes called Controllers or Operators (typically Controllers for the most part). With Operators, you can extend the Kubernetes API based on the OpenAPI Kubernetes spec.

As an example, [here’s a Spec](https://www.vaultproject.io/docs/platform/k8s/csi) that was created by HashiCorp for a Vault Container Storage Interface (HCI).

Per the code below, you can see that it’s using a completely separate API compared to Kubernetes Pods or Deployments.

```jsx
apiVersion: secrets-store.csi.x-k8s.io/v1alpha1
kind: SecretProviderClass
metadata:
  name: vault-db-creds
spec:
  # Vault CSI Provider
  provider: vault
  parameters:
    # Vault role name to use during login
    roleName: 'app'
    # Vault's hostname
    vaultAddress: 'https://vault:8200'
    # TLS CA certification for validation
    vaultCACertPath: '/vault/tls/ca.crt'
    objects: |
      - objectName: "dbUsername"
        secretPath: "database/creds/db-app"
        secretKey: "username"
      - objectName: "dbPassword"
        secretPath: "database/creds/db-app"
        secretKey: "password"
```

[Here’s a cool step-by-step guide](https://developers.redhat.com/articles/2021/09/07/build-kubernetes-operator-six-steps) from Red Hat on how you can get started building your very own Kubernetes Operator.