Skip to main content

Provisioning K8s clusters

My method to bring a local-first, on-premises Kubernetes cluster to life quickly using the pairing of virtualistion and Kubespray.

Note that quickly does not mean its the fastest way to deploy a cluster. There are many Kubernetes environments available to you. See types.

This section includes preparing hosts, creating a resilient Virtual IP (VIP) for the Kubernetes API, and using Kubespray to bootstrap the cluster. Ingress is provided by Ingress-NGINX with a MetalLB service that are documented in other sections of the Sphere.

If you already have an operational Kubernetes cluster, this section may still be useful if you’re interested in building a cluster with Kubespray.

What this covers

  • Preparation. Subnets and host addressing, a clean Ubuntu VM template you can clone, and DNS entries that keep names consistent on your LAN. See preparation.
  • Load balancers (API only). Keepalived for VIP failover and HAProxy for TCP pass-through to the Kubernetes API. Note that this VIP is not used for ingress. See load balancers.
  • Kubespray. The Ansible playbooks I use to create the cluster. Inventory examples and the exact commands to run. See kubespray.

Prerequisites

  • A working hypervisor or hardware for your nodes (for example, I use Parallels for the initial development cluster, then switch to a hybrid setup using an old computer later).
  • Ubuntu LTS on each node with a static IPv4 address and SSH access.
  • Local DNS or /etc/hosts entries that resolve every hostname and FQDN.
  • A service CIDR and a pod CIDR reserved in your design, with room to grow.

Provisioning flow at a glance

  1. Prepare hosts. Build a base VM template, clone per role, and assign static IPs and hostnames. Confirm DNS resolution and SSH access.
  2. Create the API VIP. Configure Keepalived and HAProxy on two small nodes. Verify failover and that the Kubernetes API is reachable via the VIP. Skip ingress here.
  3. Bootstrap with Kubespray. Build an inventory to match your hosts, choose sensible defaults, and run the Ansible playbooks to create the cluster.
  4. Smoke tests. Confirm kubectl get nodes, deploy a trivial service, and check ingress via the MetalLB-assigned address.

Pages in this section

  • Preparation. Subnets, VM template, and DNS. Short steps you can repeat quickly.
  • Load balancers. Keepalived + HAProxy configs for a simple API VIP. Includes verification commands.
  • Kubespray. Repo setup, Python requirements, inventory examples, and the playbooks to run.

Verification

  • ssh <host> to each node to confirm access.
  • nc -vz <vip> 8443 or curl -sk https://<vip>:8443/healthz to check API reachability through HAProxy.
  • kubectl get nodes and kubectl -n kube-system get pods to confirm a healthy control plane.

Rollback and rebuild

  • Because each step is scripted, you can safely rebuild: destroy clones, recreate from the VM template, and rerun Kubespray.
  • Keep configuration files for Keepalived, HAProxy, and Kubespray inventory in version control so changes are clear and reversible.

Next up

Once the cluster is healthy, move on to cluster add-ons (container network interface (CNI), metrics, ingress controller), storage (CSI), and backups. The goal remains the same: fit for purpose, automatic where it helps, observable, and reversible.