The problem above GitOps
GitOps manages what runs inside clusters. But who creates the clusters themselves? Manually clicking through a cloud console to provision 50 clusters is error-prone and not reproducible. Cluster API (CAPI) solves this by applying the Kubernetes operator pattern to cluster lifecycle management.
How Cluster API works
Cluster API runs on a Management Cluster (separate from your workload clusters). You describe the desired cluster topology using Kubernetes custom resources, and CAPI's controllers provision the actual infrastructure.
A top-level Cluster resource names the network configuration and points to two other resources: a controlPlaneRef (e.g. a KubeadmControlPlane, describing how the control plane nodes should be bootstrapped) and an infrastructureRef (e.g. an AWSCluster, describing the cloud-specific details like region and networking). A separate provider-specific resource, like AWSCluster, holds the actual cloud parameters — region, SSH key, and so on.
CAPI providers exist for AWS, GCP, Azure, vSphere, bare metal, and more. The same declarative model works across all of them.
The full lifecycle:
- Applying the Cluster resource → CAPI provisions VMs, installs Kubernetes, configures networking.
- Scaling the cluster by editing MachineDeployment replicas → CAPI adds or removes nodes.
- Deleting the Cluster resource → CAPI tears down all infrastructure.
Combining CAPI with GitOps
The production pattern is to store your Cluster resources in Git and have a GitOps controller on the Management Cluster apply them. New clusters are created by opening a pull request. This gives you:
- Audit trail: Every cluster creation/deletion is a Git commit with an author.
- Reproducibility: Recreating a cluster after a disaster is
git push. - Drift detection: If someone manually modifies a node group, the GitOps controller detects and corrects the drift.