Kubernetes Cluster API (CAPI)

Introduction

I manage multiple Kubernetes clusters: a local development cluster, staging on AWS, production on Azure. Before Cluster API (CAPI), each cluster was provisioned with a different tool and a different workflow β€” eksctl for EKS, az aks create for AKS, kind for local. Updating them involved different CLI flags, different templates, different processes. Cluster API changed all of that.

Cluster API is a Kubernetes sub-project that lets you declaratively manage entire cluster lifecycles β€” create, scale, upgrade, and delete cluster infrastructure β€” using the same kubectl apply workflow you already know. You manage clusters the same way you manage deployments.

This article covers CAPI v1.12 (the current release at time of writing).


Core Concept: Management Cluster

The central CAPI concept is the management cluster β€” a Kubernetes cluster that runs CAPI controllers and stores cluster manifests as CRDs. The management cluster provisions and manages workload clusters (the clusters where your applications actually run).

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             Management Cluster                   β”‚
β”‚                                                   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”‚  CAPI Controllers (capi-controller-mgr)  β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β”‚                                                   β”‚
β”‚  Cluster CRD ──────────────────────────────────► │─────► Workload Cluster A (AWS)
β”‚  MachineDeployment CRD ────────────────────────► │─────► Workload Cluster B (Azure)
β”‚  KubeadmControlPlane CRD ──────────────────────► │─────► Workload Cluster C (vSphere)
β”‚                                                   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

One management cluster can manage tens or hundreds of workload clusters.


CAPI CRD Overview

All CRDs use API group cluster.x-k8s.io/v1beta1:

CRD
Purpose

Cluster

Top-level cluster definition β€” links control plane + infrastructure

Machine

Single node declaration β€” immutable, replaced not updated

MachineSet

Maintains a stable set of Machines (like ReplicaSet)

MachineDeployment

Rolling update controller for Machines (like Deployment)

MachinePool

Provider-managed group of machines (e.g., AWS ASG, Azure VMSS)

MachineHealthCheck

Auto-remediation for unhealthy nodes

ClusterClass

Reusable cluster topology template

MachineClass

(deprecated β€” use ClusterClass topology + variables)

Infrastructure-provider CRDs (provider-specific, same API group pattern):

  • AWSCluster, AWSMachine, AWSMachineTemplate β€” from CAPA

  • AzureCluster, AzureMachine β€” from CAPZ

  • vSphereCluster, VSphereMachine β€” from CAPV

  • DockerCluster, DockerMachine β€” from CAPD (for local development)

Bootstrap-provider CRDs:

  • KubeadmConfig, KubeadmConfigTemplate β€” from CABPK

  • KubeadmControlPlane β€” from KCP provider


Setting Up the Management Cluster

Prerequisites

Bootstrap with kind (Local Development)

Initialize with AWS Provider (CAPA)


Creating a Workload Cluster

Using clusterctl generate cluster (quick start)

The Cluster CRD

The generated YAML contains a Cluster resource linking infrastructure and control plane:

KubeadmControlPlane

KubeadmControlPlane manages the control plane nodes as a unit β€” it handles initial bootstrap, upgrades, and replacement of failed control plane nodes.

MachineDeployment (Worker Nodes)

MachineDeployment manages worker nodes with the same rolling update model as a Deployment manages pods.

KubeadmConfigTemplate (Worker Bootstrap)

Machine: The Immutable Node Unit

Individual Machine objects are created by MachineSet (managed by MachineDeployment). They are immutable β€” if you need to change the machine type or OS image, you update the MachineDeployment template, and CAPI creates new Machines then deletes the old ones.


MachineHealthCheck (Auto-Remediation)

MachineHealthCheck monitors node health and replaces unhealthy machines automatically.

The maxUnhealthy safeguard is critical β€” without it, CAPI could attempt to replace the entire cluster if a network partition makes all nodes appear unhealthy.


MachinePool (Cloud-Native Autoscaling)

MachinePool maps to the cloud provider's native autoscaling group (AWS ASG, Azure VMSS). The cloud provider manages the actual machine instances.


ClusterClass (Topology API)

ClusterClass is the recommended way to create clusters at scale β€” it defines a reusable cluster topology with variables, similar to Helm values.

Create a cluster from the ClusterClass:


Cluster Operations

Get kubeconfig for a Workload Cluster

Inspect Cluster Status

Scale Worker Nodes

Upgrade a Cluster

Update spec.version in KubeadmControlPlane and MachineDeployment β€” CAPI handles the rest:

The MachineDeployment rolling update replaces nodes one at a time following maxUnavailable: 0.

Delete a Cluster

CAPI cascades the deletion β€” it removes Machines, Secrets, and cloud infrastructure in the correct order.


Infrastructure Providers Reference

Provider
Name
API Import Path

AWS

CAPA

sigs.k8s.io/cluster-api-provider-aws

Azure

CAPZ

sigs.k8s.io/cluster-api-provider-azure

GCP

CAPG

sigs.k8s.io/cluster-api-provider-gcp

vSphere

CAPV

sigs.k8s.io/cluster-api-provider-vsphere

Docker (local)

CAPD

sigs.k8s.io/cluster-api/test/infrastructure/docker

OpenStack

CAPO

sigs.k8s.io/cluster-api-provider-openstack

Initialize a Production AWS Management Cluster


Deploying the Go Microservice to a CAPI Workload Cluster

Once kubectl get nodes shows healthy nodes on the workload cluster:


What I Learned

  • Immutable Machines change how you think about upgrades β€” instead of kubectl edit, you update the template and CAPI replaces machines one at a time. This is safer and more auditable.

  • ClusterClass is worth the initial setup cost β€” once I defined the class, spinning up a new cluster for a new team takes less than 10 minutes with a 5-line YAML file.

  • MachineHealthCheck maxUnhealthy is a safety valve β€” always set it. A network partition that makes 80% of your nodes look unhealthy should pause remediation, not trigger a mass replacement.

  • Always upgrade control plane before workers β€” CAPI does not enforce this ordering automatically, but Kubernetes version skew policy requires it.

  • CAPI management cluster itself needs to be production-grade β€” backing it up, HA-ing its etcd, and having a bootstrap procedure for disaster recovery is important infrastructure work.


Next Steps


Further Reading

Last updated