/ Docs / 04 — Cluster Setup
Document 04 · Cluster setup
3-node homelab Kubernetes cluster

How kube1, kube2, and kube3 were built — kubeadm, ContainerD, Flannel CNI, MetalLB, NFS provisioner, and Wazuh SIEM. Running Oracle Linux 10, v1.31.14, 237 days and counting.

Nodes
kube1
10.99.0.30
control-plane
kube2
10.99.0.31
worker
kube3
10.99.0.32
worker
PropertyValue
OSOracle Linux Server 10.0
Kubernetesv1.31.14
Container runtimeContainerD
CNIFlannel
CPU per node4 cores
Memory per node7Gi
Architectureamd64
Uptime237+ days
Control-plane taint: kube1 has the default control-plane taint (node-role.kubernetes.io/control-plane). Regular pods don't schedule there unless you explicitly add a toleration. All workloads run on kube2 and kube3.
Cluster components
ComponentPurposeNamespace
CoreDNSCluster DNS resolutionkube-system
kube-proxyNetwork rules on each nodekube-system
kube-flannelPod network CNI (VXLAN overlay)kube-flannel
MetalLBLoadBalancer IP assignment (Layer 2)metallb-system
NFS provisionerDynamic PV provisioning from NFSnfs-provisioner
local-pathSimple hostPath storage classlocal-path-storage
LonghornDistributed block storagelonghorn-system
Wazuh agentSIEM — runs on all nodes via DaemonSetdefault
Kubernetes dashboardWeb UI for cluster managementkubernetes-dashboard
Storage classes

Three storage classes available, each with different characteristics:

ClassProvisionerBest for
local-path (default)rancher.io/local-pathSingle-node dev workloads
longhorndriver.longhorn.ioReplicated block storage, HA workloads
nfs-clientnfs-subdir-external-provisionerReadWriteMany — shared across pods
Static NFS PVs: When binding a PV directly by volumeName, set storageClassName: "" on both PV and PVC. This bypasses StorageClass matching entirely and prevents "storageClassName does not match" errors when multiple classes exist.
Namespaces
NamespaceWhat runs there
wordpress6WordPress + MySQL (the migrated legacy site)
cluster-dashboardLive cluster reference dashboard
mfa2fa-docsThis documentation site
redisRedis master + replica StatefulSet
defaultTomcat base, demo-nginx, Kafka manager, Wazuh agents
devTomcat webapp dev environment
prodTomcat webapp prod environment
metallb-systemMetalLB controller + speaker DaemonSet
kube-flannelFlannel CNI DaemonSet
kube-systemCoreDNS, kube-proxy, etcd, API server
Useful cluster commands
# Full cluster overview
kubectl get all --all-namespaces

# Node status and details
kubectl get nodes -o wide
kubectl describe node kube2

# Check resource usage per node (requires metrics-server)
kubectl top nodes

# Check all LoadBalancer services and their IPs
kubectl get svc -A | grep LoadBalancer

# Check all PVs and PVCs
kubectl get pv
kubectl get pvc -A

# Check storage classes
kubectl get storageclass

# etcd health (run on kube1)
ETCDCTL_API=3 etcdctl \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  endpoint health