Article 05 – Kube API Server: The Cluster’s Front Door

The Central Database Bottleneck

If you have multiple developer teams, automated scripts, and various controller agents all running inside a cluster, they need to read and update the cluster state. If all these entities could communicate directly with the etcd database, you would face race conditions and data corruption. One developer might update a pod’s specification at the same microsecond another team attempts to delete the parent namespace, causing inconsistent data states.

Furthermore, without a central gatekeeper, there would be no clean way to validate the syntax of configurations, enforce security permissions, or log access history. You need a single, secure gateway to manage all incoming traffic.

Additionally, we need to handle concurrency safety. If two users try to update the exact same Pod at the same time, we need a mechanism to prevent one from silently overwriting the other’s changes. Direct database access does not provide this abstraction.

The API Pipeline and Concurrency Control

This gateway is the Kube API Server (kube-apiserver). It is the only component in the cluster that talks directly to etcd. Every command you run via kubectl, and every update sent by the Kubelet or controllers, must go through the API Server.

When a request hits the API Server, it passes through a structured pipeline:
1. Authentication: The server verifies your identity using client certificates, bootstrap tokens, webhook tokens, or OpenID Connect (OIDC) identity providers.
2. Authorization: The server evaluates your permissions against Role-Based Access Control (RBAC), Node Authorization, or Webhook policies to ensure you are allowed to perform the requested action.
3. Admission Control: The request is evaluated by admission plugins (like NodeRestriction, LimitRanger, or custom Mutating and Validating Admission Webhooks). Mutating plugins can modify the request to inject defaults (like sidecars), while Validating plugins reject requests that violate security policies.
4. Validation: The resource schema is validated to ensure it matches the Kubernetes API specification.
5. Persistence: The validated resource is written to the etcd database.

To prevent write conflicts, the API Server uses Optimistic Concurrency Control (OCC). Every resource stored in etcd has a metadata.resourceVersion field. When you modify a resource, you must send back the current resourceVersion. If another process modified that resource in the meantime, the resourceVersion in etcd will be higher, and the API Server will reject your write with a 409 Conflict error, forcing your client to read the updated resource and retry.

Querying the API Server Manifest and Endpoints

In a kubeadm cluster, the API Server runs as a static pod. You can view its command configuration by reading the manifest:

$ sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml

Inside this YAML file, you can inspect the flags that connect the server to etcd and configure its security options:

spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.49.2
    - --etcd-cafile=/etc/kubernetes/pki/etcd/ca.crt
    - --etcd-certfile=/etc/kubernetes/pki/apiserver-etcd-client.crt
    - --etcd-keyfile=/etc/kubernetes/pki/apiserver-etcd-client.key
    - --etcd-servers=https://127.0.0.1:2379
    - --authorization-mode=Node,RBAC
    - --enable-admission-plugins=NodeRestriction,NamespaceLifecycle,LimitRanger,ServiceAccount

You can query the API Server directly using curl if you provide the admin certificates. First, extract the server address from your config:

$ APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')

Now, query the API endpoints to retrieve the list of namespaces:

$ curl -k --cert /etc/kubernetes/pki/apiserver-kubelet-client.crt \
         --key /etc/kubernetes/pki/apiserver-kubelet-client.key \
         $APISERVER/api/v1/namespaces

{
  "kind": "NamespaceList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "24510"
  },
  "items": [
    {
      "metadata": {
        "name": "default"
      }
    }
  ]
}

Since the API Server is stateless, you can run multiple instances behind a load balancer to ensure high availability. This prevents the API from becoming a single point of failure in your control plane.