Cluster API on OpenStack: Part 1 - Introduction and Architecture
Cluster API (CAPI) brings declarative, Kubernetes-style management to the lifecycle of Kubernetes clusters themselves. Instead of manually provisioning VMs and running kubeadm, you define your desired cluster state in YAML and let controllers reconcile reality to match. On OpenStack, this means treating Kubernetes clusters as first-class resources—scalable, versionable, and managed through familiar kubectl workflows.
This series walks through deploying CAPI on OpenStack:
- Introduction and Architecture (this post)
- Building CAPI Images
- Deploying Workload Clusters
- Day-2 Operations
Why Cluster API?
Traditional Kubernetes deployment tools like kubespray or kubeadm work well for initial setup, but ongoing management becomes manual and error-prone. CAPI changes this by:
- Treating clusters as declarative resources
- Enabling rolling updates for Kubernetes version upgrades
- Providing consistent APIs across different infrastructure providers
- Integrating with GitOps workflows naturally
OpenStack users have two main options: Magnum (OpenStack’s native container orchestration service) or standalone CAPI. Recent versions of Magnum actually use CAPI under the hood via the magnum-cluster-api driver, giving you the best of both worlds.
Architecture Overview
CAPI uses a management cluster to provision and manage workload clusters. The management cluster runs the CAPI controllers, while workload clusters are the actual Kubernetes environments your applications run on.
For OpenStack, you need:
- Management cluster - A lightweight Kubernetes cluster (K3s works well) running CAPI controllers
- CAPO (Cluster API Provider OpenStack) - The infrastructure provider that translates CAPI resources into Nova instances, Neutron networks, and Cinder volumes
- Bootstrap provider - Typically kubeadm, handles the initial cluster bootstrapping
The Resource Hierarchy
Understanding how CAPI resources connect is crucial for troubleshooting and day-2 operations. Here’s the ownership chain:
Cluster
├── infrastructureRef → OpenStackCluster
│ (API endpoint, external network, DNS, subnets)
│
├── controlPlaneRef → KubeadmControlPlane
│ ├── machineTemplate.infrastructureRef → OpenStackMachineTemplate
│ │ (flavor, image, rootVolume, security groups)
│ └── creates → Machine → OpenStackMachine
│
└── MachineDeployment (workers)
├── infrastructureRef → OpenStackMachineTemplate
├── bootstrap.configRef → KubeadmConfigTemplate
└── creates → MachineSet → Machine → OpenStackMachineThe key insight is that templates are immutable. When you need to change VM specifications (like disk size), you create a new template and update the reference. CAPI then performs a rolling update, creating new nodes with the updated spec and draining the old ones.
Setting Up the Management Cluster
A K3s cluster works well as a management cluster. You also need a clouds.yaml with information on how to connect to your Openstack cloud. On a dedicated VM:
# Install K3s
curl -sfL https://get.k3s.io | sh -
# Install clusterctl
CAPI_VERSION=v1.12.1
curl -Lo /usr/local/bin/clusterctl \
https://github.com/kubernetes-sigs/cluster-api/releases/download/${CAPI_VERSION}/clusterctl-linux-amd64
chmod +x /usr/local/bin/clusterctl
# Initialize CAPI with OpenStack provider
export OPENSTACK_CLOUD=openstack
export OPENSTACK_CLOUD_YAML_B64=$(base64 -w0 ~/.config/openstack/clouds.yaml)
clusterctl init --infrastructure openstackVerify the controllers are running:
kubectl get pods -n capo-system
kubectl get pods -n capi-system
kubectl get pods -n capi-kubeadm-bootstrap-system
kubectl get pods -n capi-kubeadm-control-plane-systemOpenStack Prerequisites
Before creating clusters, ensure your OpenStack environment is ready.
Create a Flavor with Root Disk
CAPO needs flavors with root disk defined, or you must specify a boot volume:
openstack flavor create m1.medium-disk \
--vcpus 2 \
--ram 4096 \
--disk 20Note Your Network IDs
openstack network list
openstack subnet listYou’ll need the external network UUID for floating IPs. Internal network is usually managed by CAPI.
Integration with Magnum
If you’re already using OpenStack, Magnum with the magnum-cluster-api driver provides a nice abstraction. You get the benefits of CAPI with the familiar OpenStack CLI:
# Create a cluster template
openstack coe cluster template create k8s-flatcar-capi \
--image flatcar-kube-v1.27.4 \
--external-network public \
--master-flavor m1.medium-disk \
--flavor m1.medium-disk \
--network-driver calico \
--master-lb-enabled \
--coe kubernetes \
--labels kube_tag=v1.32.0
# Create a cluster
openstack coe cluster create prod-cluster \
--cluster-template k8s-flatcar-capi \
--master-count 3 \
--node-count 3 \
--keypair mykeyUnder the hood, Magnum creates CAPI resources in a management cluster it maintains. You can still access these resources directly for advanced operations:
# From the Magnum conductor
kubectl --kubeconfig=/var/lib/magnum/.kube/config get clusters -AWhat’s Next
With the management cluster running, the next step is building CAPI-compatible images for your workload clusters.