Learn how to deploy production-grade Kubernetes clusters on bare metal, OpenStack, and public cloud using a single Cluster API-based workflow with Navos. Step-by-step tutorial with manifests.
Most teams don't run Kubernetes on one thing.
They run it on OpenStack in their private data center. On bare metal for GPU workloads. On a public cloud region for a specific customer requirement. And somewhere along the way, they end up with three different deployment tools, three different upgrade processes, and three different mental models for doing the same job.
That's not an infrastructure problem. That's a tooling problem. And it's exactly what Navos was built to fix.
This post is a hands-on walkthrough of how Navos lets you deploy, manage, and upgrade Kubernetes clusters across bare metal, OpenStack, and any cloud, using a single, consistent API. Same primitives. Same workflow. Different substrates.
The Architecture First
Before the commands, the model.
Navos runs on unmodified upstream Kubernetes and Cluster API, and that architectural choice is what makes portability and no-lock-in cluster management possible.
Cluster API is the key. All of the different users of cloud platforms realized that the deployment process, once you have machines, is essentially the same. The community came up with a simple but effective concept: Cluster API encompasses all the common bits, deploying the actual software, cluster lifecycle management, while different providers focus on supplying the underlying infrastructure.
What that means in practice: the object model you use to declare a cluster on OpenStack is structurally identical to the one you use on bare metal or a public cloud. The provider changes. The core Cluster API model and workflow remain consistent — provider-specific CRDs and parameters describe the underlying infrastructure, while everything above that layer stays the same.
There are providers for OpenStack, VMware, AWS, and many others. Once a new cluster is created, Cluster API goes out to the providers to request the machines, and once the machines are created, it takes over operations.
This is the foundation. Everything that follows is built on it.
What You Need Before You Start
- Access to a Navos-managed environment — on VEXXHOST's Atmosphere Cloud, a hosted private cloud, or your own on-premise deployment
- kubectl and clusterctl installed locally
- A valid kubeconfig pointing at your management cluster
- Provider credentials configured for your target substrate (OpenStack clouds.yaml, bare metal IPMI credentials, or a public cloud IAM key)
Deploying on OpenStack
OpenStack is the most common substrate for teams running Navos on private infrastructure. Atmosphere's Kubernetes service integrates natively with block storage using CSI and leverages Cluster API on the backend, supporting auto-healing, auto-scaling, and rolling upgrades.
Start by initializing Cluster API with the OpenStack provider:
clusterctl init --infrastructure openstack
Then declare your cluster. The core resource looks like this:
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: prod-openstack
namespace: default
spec:
clusterNetwork:
pods:
cidrBlocks: ["192.168.0.0/16"]
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha7
kind: OpenStackCluster
name: prod-openstack
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
name: prod-openstack-control-plane
The OpenStackCluster object handles what OpenStack-specific - network IDs, floating IPs, security groups, and Nova flavor references. Through integration with Cinder, users can provision persistent volumes that don't rely on the lifecycle of their bound pod. The Kubernetes integration with Keystone also makes it possible to authenticate clusters using existing OpenStack credentials.
Apply it:
kubectl apply -f prod-openstack-cluster.yaml
Watch the cluster come up:
kubectl get clusters -A --watch
With OpenStack's load balancer service integrated with Kubernetes, users can deploy an external load balancer in front of a Kubernetes service, creating an external IP that distributes traffic across pods. This happens automatically as part of the provider integration; no manual wiring required.
Deploying on Bare Metal
For workloads that need direct hardware access - GPU inference, high-frequency networking, latency-sensitive compute - bare metal is the right substrate. Regardless of whether you're using virtual machines or bare metal, Navos can deploy certified Kubernetes on your system.
The bare metal provider for Cluster API uses Metal3 to manage physical machine lifecycle through IPMI and Redfish. Initialize it alongside the core Cluster API components:
clusterctl init --infrastructure metal3
Your cluster declaration follows exactly the same top-level structure. The infrastructureRef now points to a Metal3Cluster instead of OpenStackCluster:
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: prod-baremetal
namespace: default
spec:
clusterNetwork:
pods:
cidrBlocks: ["192.168.0.0/16"]
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: Metal3Cluster
name: prod-baremetal
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
name: prod-baremetal-control-plane
The BareMetalHost objects in Metal3 represent your physical inventory. Once enrolled, with IPMI credentials and a provisioning image, Cluster API treats them like any other machine. It provisions, joins them to the cluster, and manages their lifecycle from that point forward.
Notice what didn't change: the Cluster kind, the KubeadmControlPlane kind, the clusterNetwork block, the kubectl apply workflow. The substrate is different. The API is not.
Deploying on a Public Cloud
The same pattern applies to public cloud infrastructure. VEXXHOST only uses upstream Kubernetes, so there's no dependency on proprietary abstractions, deploy on OpenStack, or bare metal, and your manifests travel with you.
Initialize with your target provider:
For AWS
clusterctl init --infrastructure aws
For GCP
clusterctl init --infrastructure gcp
The Cluster manifest is structurally identical. Only the infrastructureRef kind changes — AWSCluster or GCPCluster — while the KubeadmControlPlane, network config, and worker MachineDeployment objects remain the same.
This isn't an abstraction for its own sake. It means your cluster definitions are portable artifacts. A Cluster manifest tested on OpenStack can be promoted to run on bare metal with a targeted change to the infrastructureRef and provider-specific parameters. The rest of the declaration doesn't change because it doesn't need to.
The Single-API Experience in Practice
Here's what the single-API model looks like across Day 1 and Day 2:
Provisioning a cluster: kubectl apply -f cluster.yaml — regardless of substrate.
Scaling workers: Edit the replicas field on your MachineDeployment. Cluster API reconciles the difference.
Upgrading Kubernetes: The upgrade path depends on how your cluster is declared. If you're using ClusterClass with managed topology, update spec.topology.version on the Cluster resource; Cluster API then reconciles the generated control-plane and worker resources, upgrading control plane machines first and worker machines afterward in strict order. If you're using classic Cluster API manifests without spec.topology, upgrades are driven by updating the relevant KubeadmControlPlane, MachineDeployment, and machine-template resources directly. Either way, no custom scripts, no manual sequencing.
Auditing: The process is reproducible and auditable because it's declared. It runs the same way every time because the same controller drives it every time.
This behavioral consistency is not a coincidence, it's the architectural argument for building on Cluster API rather than wrapping proprietary tooling in a compatibility layer.
Built-In Operational Readiness
Navos doesn't stop at provisioning. Navos gives you production Kubernetes on any cloud with built-in monitoring, security scanning, and expert support.
You get a certified Kubernetes distribution that seamlessly integrates with block storage using CSI, with features like auto-healing, auto-scaling, and rolling upgrades and fully isolated clusters inside private networks.
VEXXHOST continuously monitors and manages the Kubernetes control plane to ensure uninterrupted accessibility. That applies across all substrates — bare metal, OpenStack, or public cloud. The monitoring stack doesn't care where the cluster lives.
No Lock-In Is a Technical Guarantee, Not a Marketing Claim
Navos is 100% upstream Kubernetes and Cluster API - no fork, no lock-in. That distinction matters operationally.
When you fork Kubernetes, you own the delta. Every upstream patch has to be evaluated, rebased, and re-validated against your modifications. That work accumulates. OpenStack private cloud gives organizations genuine infrastructure ownership, not just geographic proximity, and the same principle applies to your Kubernetes toolchain. Owning the fork means owning the divergence, forever.
Navos sidesteps that entirely by staying on mainline. Your manifests are valid upstream YAML. Your tooling is standard kubectl and clusterctl. If you ever need to move to a different cloud, a different provider, a different managed service, the cluster definitions move with you.
VEXXHOST is a Silver member of the Cloud Native Computing Foundation (CNCF), the governing body behind the Kubernetes Project. VEXXHOST's Kubernetes solution is certified as part of the CNCF Certified Kubernetes Conformance Program, meaning you can easily migrate your cluster.
Where to Go from Here
The substrate decision is an infrastructure concern. The operational model, how you declare, upgrade, scale, and observe clusters, should be independent of it.
That's what Navos delivers. One API. One workflow. One upgrade process. Whatever the substrate under it.
Run it yourself with VEXXHOST's guidance or let the team operate it entirely — on VEXXHOST's cloud or in your own data center. Either way, the Cluster API model stays the same, and so does the support behind it.
Ready to deploy your first cluster? Talk to the VEXXHOST team and get your environment configured for Navos across the substrates that matter to your infrastructure.