Kubernetes API
Introduction
The Kubernetes API is the core of Kubernetes and serves as the foundation for all operations within a Kubernetes cluster. It's a RESTful API that allows you to create, read, update, and delete Kubernetes resources (like pods, services, and deployments) programmatically. When you use tools like kubectl
or a dashboard, you're actually interacting with the Kubernetes API behind the scenes.
In this guide, we'll explore how the Kubernetes API works, how to interact with it, and see some practical examples that will help you understand its importance in the Kubernetes ecosystem.
Understanding the Kubernetes API
What is the Kubernetes API?
The Kubernetes API is an HTTP-based interface that provides endpoints for:
- Creating resources (pods, deployments, services, etc.)
- Reading the state of resources
- Updating resources
- Deleting resources
- Watching for changes to resources
All operations in a Kubernetes cluster, whether performed through the command line, a GUI, or programmatically, ultimately go through this API.
API Structure
The Kubernetes API is organized into:
- API Groups: Collections of related resources (e.g.,
apps
,batch
,networking.k8s.io
) - Versions: Each API group has multiple versions (e.g.,
v1
,v1beta1
) - Resources: The actual objects you can create and manage (pods, services, etc.)
An API path generally follows this structure:
/apis/{GROUP}/{VERSION}/namespaces/{NAMESPACE}/{RESOURCE}
For core resources (like pods and services), the path is slightly different:
/api/v1/namespaces/{NAMESPACE}/{RESOURCE}
Key Components of the API
- API Server: The component that serves the API
- Authentication: Verifies who's making the request
- Authorization: Checks if the authenticated user has permission
- Admission Controllers: Optional plugins that can modify or validate requests
- Resource Validation: Ensures requests are well-formed
- etcd: The database where all cluster state is stored
Interacting with the Kubernetes API
There are several ways to interact with the Kubernetes API:
1. Using kubectl
The most common way to interact with the Kubernetes API is through the kubectl
command-line tool.
Example: Creating a Pod using kubectl
kubectl create -f pod.yaml
Where pod.yaml
contains:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: default
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Example: Getting information about Pods
kubectl get pods
Output:
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 45s
2. Direct HTTP Requests
You can also interact with the API directly using HTTP requests:
Example: Getting a Pod with curl
First, set up proxy access to the API:
kubectl proxy
Then, in another terminal:
curl http://localhost:8001/api/v1/namespaces/default/pods/nginx-pod
Output (truncated for brevity):
{
"kind": "Pod",
"apiVersion": "v1",
"metadata": {
"name": "nginx-pod",
"namespace": "default",
"uid": "1a2b3c4d-5e6f-7g8h-9i0j-1k2l3m4n5o6p",
"creationTimestamp": "2023-01-01T12:00:00Z"
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:latest",
"ports": [
{
"containerPort": 80
}
]
}
]
},
"status": {
"phase": "Running",
"conditions": [
{
"type": "Ready",
"status": "True"
}
]
}
}
3. Client Libraries
For programmatic access, Kubernetes provides client libraries in various languages.
Example: Using the official Go client
package main
import (
"context"
"fmt"
"os"
"path/filepath"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
// Use the current context in kubeconfig
kubeconfig := filepath.Join(os.Getenv("HOME"), ".kube", "config")
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
panic(err.Error())
}
// Create the clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Get pods in the default namespace
pods, err := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
fmt.Printf("There are %d pods in the default namespace
", len(pods.Items))
for _, pod := range pods.Items {
fmt.Printf("Pod name: %s
", pod.Name)
}
}
Example: Using the Python client
from kubernetes import client, config
# Load kube config
config.load_kube_config()
# Create a client
v1 = client.CoreV1Api()
# List pods in the default namespace
print("Listing pods in default namespace:")
pods = v1.list_namespaced_pod(namespace="default")
for pod in pods.items:
print(f"Pod name: {pod.metadata.name}")
Understanding API Resources and Versions
API Resources
Kubernetes resources are the objects you create and manage in your cluster. Common resources include:
- Pods: The smallest deployable units
- Services: Provides network access to a set of pods
- Deployments: Manages pod replicas and updates
- ConfigMaps: Configuration data for applications
- Secrets: Sensitive configuration data
- Namespaces: Logical partitions within a cluster
API Versions
Kubernetes uses API versions to indicate the stability and support level:
- Alpha (v1alpha1): May be buggy, disabled by default, support may be dropped
- Beta (v1beta1): Well-tested, enabled by default, details may change
- Stable (v1): Will be supported for many versions
You can see available API resources with:
kubectl api-resources
Output (partial):
NAME SHORTNAMES APIVERSION NAMESPACED KIND
bindings v1 true Binding
configmaps cm v1 true ConfigMap
endpoints ep v1 true Endpoints
pods po v1 true Pod
services svc v1 true Service
deployments deploy apps/v1 true Deployment
daemonsets ds apps/v1 true DaemonSet
Practical Applications
Example 1: Watching for Changes
One powerful feature of the Kubernetes API is the ability to "watch" resources for changes:
kubectl get pods --watch
This command doesn't exit after listing pods but continues running and updates you when pods change state.
In code, you can do this with:
from kubernetes import client, config, watch
config.load_kube_config()
v1 = client.CoreV1Api()
w = watch.Watch()
for event in w.stream(v1.list_namespaced_pod, namespace="default"):
print(f"Event: {event['type']}, Pod: {event['object'].metadata.name}")
Example 2: Creating Custom Resources with the API
Kubernetes allows you to extend the API with Custom Resource Definitions (CRDs):
First, define a CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: websites.example.com
spec:
group: example.com
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
url:
type: string
replicas:
type: integer
scope: Namespaced
names:
plural: websites
singular: website
kind: Website
shortNames:
- ws
Apply it:
kubectl apply -f website-crd.yaml
Now you can create instances of your custom resource:
apiVersion: example.com/v1
kind: Website
metadata:
name: my-website
spec:
url: "https://example.com"
replicas: 3
Save as my-website.yaml
and apply:
kubectl apply -f my-website.yaml
This demonstrates how the API can be extended for custom use cases.
Example 3: Using API for Rolling Updates
The API enables sophisticated operations like rolling updates:
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
Behind the scenes, this:
- Creates new pods with the updated image
- Waits for them to be ready
- Gradually terminates old pods
- All orchestrated through the API
API Security
Security for the Kubernetes API involves several layers:
- TLS: Communication with the API is encrypted using TLS
- Authentication: Determining who is making the request
- X.509 certificates
- Bearer tokens
- OpenID Connect
- Webhook authentication
- Authorization: Determining if the authenticated user can perform the requested operation
- Role-Based Access Control (RBAC)
- Attribute-Based Access Control (ABAC)
- Node authorization
- Webhook authorization
RBAC Example
Here's a simple RBAC configuration that allows reading pods:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
Apply with:
kubectl apply -f rbac-example.yaml
Summary
The Kubernetes API is the foundation of everything you do with Kubernetes. It provides a consistent interface for creating, reading, updating, and deleting resources in a Kubernetes cluster. Key points to remember:
- The API follows REST principles with resources organized into groups and versions
- Multiple ways to interact with the API exist: kubectl, direct HTTP, client libraries
- The API can be extended with Custom Resource Definitions
- Security is implemented through TLS, authentication, and authorization
Understanding the Kubernetes API gives you a deeper knowledge of how Kubernetes works and enables you to build more advanced applications and automation.
Exercises
- Use
kubectl
to list all available API resources in your cluster - Create a simple Pod using a YAML file
- Try using
kubectl proxy
and then access the API directly with curl - Implement a simple Go or Python program that lists pods using the client libraries
- Create a Custom Resource Definition and an instance of that resource
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)