Skip to main content

First Bare Metal Cluster

Purpose: For platform engineers, walks through deploying a first Kubernetes cluster on bare metal servers using openCenter (20 minutes configuration + 30–50 minutes deployment).

What You'll Do

  1. Initialize a bare metal cluster configuration with node IPs and VIP
  2. Validate, generate the GitOps repository, and deploy
  3. Verify nodes, MetalLB, Longhorn storage, and platform services are running

End result: A 6-node HA Kubernetes cluster on bare metal with MetalLB load balancing, Longhorn distributed storage, Kyverno policies, monitoring, and GitOps — ready for application workloads (~50 minutes total).

Prerequisites

  • openCenter CLI installed (CLI Installation)
  • At least 3 servers for control plane + 3 for workers (or 3 combined for non-HA)
  • Ubuntu 22.04 or Rocky Linux 9 installed on all nodes
  • SSH access to all nodes from the machine running the CLI
  • Servers reachable on a shared L2/L3 network
  • A virtual IP address available for the Kubernetes API (used by kube-vip or MetalLB)
  • DNS records or wildcard domain for ingress
  • A Git repository for GitOps

Step 1: Initialize the Cluster Configuration

opencenter cluster init my-baremetal-cluster --org my-org --type baremetal

This creates the configuration at ~/.config/opencenter/clusters/my-org/.my-baremetal-cluster-config.yaml and auto-generates SOPS Age keys and an SSH key pair.

Edit the configuration:

opencenter cluster edit my-baremetal-cluster

Key sections:

opencenter:
cluster:
cluster_name: my-baremetal-cluster
organization: my-org

infrastructure:
provider: baremetal
baremetal:
masters:
- ip: 10.0.1.10
hostname: master-1
- ip: 10.0.1.11
hostname: master-2
- ip: 10.0.1.12
hostname: master-3
workers:
- ip: 10.0.1.20
hostname: worker-1
- ip: 10.0.1.21
hostname: worker-2
- ip: 10.0.1.22
hostname: worker-3
vip: 10.0.1.100
vip_interface: eth0
ssh_user: ubuntu
ssh_key_path: ~/.ssh/id_ed25519

kubernetes:
version: 1.33.5
control_plane_count: 3
worker_count: 3
cni: calico

services:
keycloak:
enabled: true
kube-prometheus-stack:
enabled: true
loki:
enabled: true
longhorn:
enabled: true
metallb:
enabled: true
velero:
enabled: true

secrets:
sops:
age_keys:
- age1... # Auto-generated during init

Step 2: Validate Configuration

opencenter cluster validate my-baremetal-cluster

Validation checks: schema compliance, SSH connectivity to all nodes (if --validation=online), node IP uniqueness, VIP availability, and network configuration.

Step 3: Generate GitOps Repository

opencenter cluster generate my-baremetal-cluster

This generates:

  • Kubespray inventory with node IPs and security hardening (k8s_hardening.yml)
  • FluxCD application manifests with MetalLB and Longhorn enabled
  • SOPS-encrypted secrets

For bare metal, there is no Terraform infrastructure step — the nodes already exist.

Step 4: Deploy the Cluster

opencenter cluster deploy my-baremetal-cluster

The deploy command:

  1. Prepares nodes via Ansible (container runtime, kernel parameters, br_netfilter, IP forwarding) (5–10 minutes)
  2. Installs Kubernetes via Kubespray with containerd, etcd HA, kube-vip for API VIP (20–35 minutes)
  3. Bootstraps FluxCD which reconciles platform services from openCenter-gitops-base (10–15 minutes)

Step 5: Verify the Cluster

# Check cluster status
opencenter cluster status my-baremetal-cluster

# Verify all nodes
kubectl get nodes

# Confirm MetalLB is advertising IPs
kubectl get svc -A | grep LoadBalancer

# Check Longhorn storage
kubectl get sc
kubectl get volumes -n longhorn-system

# Check FluxCD reconciliation
flux get kustomizations

Check Your Work

  • All nodes show Ready status
  • kube-vip is serving the API on the VIP address (curl -k https://10.0.1.100:6443/healthz)
  • MetalLB speaker pods are running on every node
  • Longhorn storage class is available as default (kubectl get sc)
  • FluxCD kustomizations show Ready=True

Platform Services Deployed

After FluxCD reconciles, these services from openCenter-gitops-base are running:

ServiceVersionNamespace
cert-managerv1.18.2cert-manager
Gateway API (Envoy)latestenvoy-gateway-system
Keycloak26.4.2keycloak
Kyverno3.6.0kyverno
kube-prometheus-stack77.6.0observability
Loki6.45.2observability
Longhorn1.11.0longhorn-system
MetalLB0.15.2metallb-system
Velero10.1.1velero

Troubleshooting

SymptomLikely CauseFix
SSH connection refusedWrong key or userVerify ssh_user and ssh_key_path; test with ssh -i ~/.ssh/id_ed25519 ubuntu@10.0.1.10
Nodes not joiningFirewall blocking 6443, 10250, 2379-2380Open required ports between all nodes
VIP unreachableWrong interface nameCheck vip_interface matches the host NIC (ip addr show)
No storage classLonghorn prerequisites missingEnsure open-iscsi is installed on all workers

Next Steps