Skip to content

Cluster Architecture Overview

This homelab runs a single-node, production-grade Kubernetes cluster on bare metal. The goal is to mirror real-world platform engineering practices — GitOps, observability, automated deployments, and secure secret management — in a resource-constrained environment.

musashi node — the single bare-metal machine running the entire cluster

The entire cluster runs on a single machine, musashi:

AttributeValue
CPUAMD Ryzen 7
RAM16 GB DDR5
Storage1 TB SSD
OSFedora Linux 43 (Workstation Edition)
IP Address192.168.1.133

Running a full Kubernetes stack on a single node is a deliberate design choice for this homelab: it forces efficient resource management and makes the infrastructure cheap enough to run 24/7, while still exercising every component a multi-node production cluster would have.

The cluster was bootstrapped with kubeadm and runs Kubernetes v1.34.3 with containerd v2.1.6 as the container runtime.

NAME STATUS ROLES AGE VERSION INTERNAL-IP OS-IMAGE
musashi Ready control-plane 69d v1.34.3 192.168.1.133 Fedora Linux 43

kubeadm gives full control over the cluster configuration. Unlike k3s or microk8s, every component (etcd, kube-apiserver, kube-scheduler, kube-controller-manager) runs as a standard Kubernetes pod — which is ideal for learning operational patterns that apply directly to production kubeadm clusters.

The CNI plugin is Cilium, running as a DaemonSet in kube-system. Cilium handles pod networking and NetworkPolicy enforcement; standard kube-proxy is used for service routing. Cilium was chosen for:

  • NetworkPolicy enforcement — enforces standard NetworkPolicy CRDs and extends them with CiliumNetworkPolicy for L7-aware rules
  • eBPF-based packet processing — efficient kernel-level dataplane for pod-to-pod traffic
  • Operational maturity — well-established in production Kubernetes environments
kube-system cilium DaemonSet 1/1 Running 69d
kube-system cilium-operator Deployment 1/1 Running 18d

Layer 7 routing is handled by Traefik running in the traefik namespace, exposed as a NodePort service:

PortProtocolNodePort
80HTTP30080
443HTTPS30443
8080Dashboard30081

Traefik implements the Kubernetes Gateway API (gateway.networking.k8s.io/v1) rather than legacy Ingress objects. All application routing is declared as HTTPRoute resources, which is the modern, vendor-neutral standard:

# Example HTTPRoute for ArgoCD
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: argocd-route
namespace: argocd
spec:
hostnames:
- argocd.kubefurlan.com
parentRefs:
- name: traefik-gateway
namespace: traefik

External access to cluster services uses a Cloudflare Tunnel (cloudflared) running as a systemd user service on the host. The tunnel terminates TLS at Cloudflare’s edge and forwards traffic to Traefik’s ClusterIP. This avoids opening inbound ports on the home router.

Traefik dashboard showing active routes and services

Persistent volumes are provided by the local-path-provisioner running in local-path-storage. It dynamically provisions hostPath-backed PVCs under /opt/local-path-provisioner/.

This is appropriate for a single-node homelab:

  • Zero overhead (no distributed storage layer)
  • Instant provisioning
  • Data lives on the fast local SSD

The limitation — no replication — is mitigated by the multi-layer backup strategy.

TLS certificates are managed by cert-manager in the cert-manager namespace:

cert-manager cert-manager-77f7698dcf 1/1 Running 19d
cert-manager cert-manager-cainjector 1/1 Running 19d
cert-manager cert-manager-webhook 1/1 Running 19d

Two ClusterIssuer resources are configured:

IssuerTypeUse
letsencrypt-prodACME / Cloudflare DNS-01Production TLS for *.kubefurlan.com
selfsigned-issuerSelf-signedInternal services, Harbor registry

Active certificates:

CertificateNamespaceStatus
harbor-tlsharborReady
traefik-gateway-certtraefikReady
traefik-letsencrypt-certtraefikReady

cert-manager certificates showing all entries as Ready

network visual diagram

Grouped by function:

NamespaceWorkloadPurpose
argocdargocd-server, application-controller, repo-server, dex-server, redisArgoCD GitOps controller
argo-rolloutsargo-rollouts, argo-rollouts-dashboardProgressive delivery (canary deployments)
NamespaceWorkloadPurpose
monitoringprometheus-kube-prometheus-stack-prometheus-0Metrics storage and query
monitoringkube-prometheus-stack-grafanaDashboards and visualization
monitoringalertmanager-kube-prometheus-stack-alertmanager-0Alert routing (Telegram + Gmail)
monitoringkube-prometheus-stack-kube-state-metricsKubernetes object metrics
monitoringkube-prometheus-stack-prometheus-node-exporterHost metrics (CPU, memory, disk)
monitoringalloy (DaemonSet)Log collection (pods + systemd journal)
monitoringloki-0Log storage
monitoringprometheus-blackbox-exporterHTTP endpoint probing
monitoringprometheus-pushgatewayBatch job metrics (restic, pg_dump)
NamespaceWorkloadPurpose
cert-managercert-manager, cainjector, webhookTLS certificate automation
kube-systemsealed-secrets-controllerEncrypted Kubernetes secrets
harborharbor-core, registry, trivy, jobservice, portalPrivate container registry + vulnerability scanning
kube-systemcilium (DaemonSet), cilium-operatorPod networking (CNI) and NetworkPolicy enforcement
NamespaceWorkloadPurpose
postgrespostgres-cluster-1CloudNativePG managed PostgreSQL
cnpg-systemcnpg-controller-managerCloudNativePG operator
NamespaceWorkloadPurpose
veleroveleroKubernetes resource backup
veleronode-agent (DaemonSet)Kopia-based volume backup
NamespaceWorkloadPurpose
backstagebackstageInternal Developer Portal (IDP)
n8nn8nWorkflow automation
minifluxminifluxRSS feed reader