API Aggregation
API aggregation extends the Kubernetes API server by registering additional API servers that handle custom resource types. Unlike CRDs, aggregated APIs run their own server process and can implement complex logic.
APIService
An APIService resource tells the main API server to proxy requests for a specific API group/version to your extension server:
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.custom.example.com
spec:
group: custom.example.com
version: v1beta1
service:
name: my-api-server
namespace: custom-system
groupPriorityMinimum: 1000
versionPriority: 15
caBundle: LS0tLS1CRUd...
# List registered API services
kubectl get apiservices
# Check status of an API service
kubectl get apiservice v1beta1.custom.example.com -o yaml
# Filter for non-local API services (aggregated ones)
kubectl get apiservices | grep -v Local
Extension API Servers
The extension server implements the Kubernetes API conventions and handles CRUD operations for your custom types:
# Verify your extension API server is running
kubectl get pods -n custom-system -l app=my-api-server
# Test the aggregated API
kubectl get --raw /apis/custom.example.com/v1beta1
# Use kubectl normally with aggregated resources
kubectl get myresources.custom.example.com
Custom Metrics
The most common use of API aggregation is the metrics API, used by kubectl top and the Horizontal Pod Autoscaler:
# The metrics-server registers an aggregated API
kubectl get apiservice v1beta1.metrics.k8s.io
# This enables kubectl top
kubectl top pods
kubectl top nodes
# Custom metrics adapter for application-specific metrics
kubectl get apiservice v1beta1.custom.metrics.k8s.io
# Query custom metrics
kubectl get --raw /apis/custom.metrics.k8s.io/v1beta1
When to Use Aggregation vs CRDs
CRDs are simpler and sufficient for most use cases. Choose API aggregation when you need custom storage backends, complex validation beyond webhooks, subresources with custom behavior, or protocol-level features like protobuf support.
# Debug aggregation layer issues
kubectl get apiservices -o custom-columns=\
NAME:.metadata.name,STATUS:.status.conditions[0].status