Core Cluster Networking and High Availability Setup

📅 Published: February 2026 ⏱️ Read time: ~10 minutes
MetalLB
NGINX Ingress
High Availability
etcd
Load Balancing

Detailed Summary

This phase of the cluster configuration establishes the foundation for both robust external traffic routing and a fault-tolerant administrative brain. Because this is a bare-metal/local environment, it lacks the native managed load balancers provided by cloud vendors (like AWS ALBs). Therefore, we must implement our own Layer 4 and Layer 7 routing layers.

First, we utilize MetalLB operating in Layer 2 mode to act as our local network load balancer, provisioning Virtual IPs (VIPs) via ARP. We bind this VIP to an NGINX Ingress Controller, which serves as the "smart" Layer 7 router, directing HTTP/HTTPS traffic to internal microservices based on decoupled Ingress routing rules.

Second, we protect the cluster from a single point of failure by establishing a High Availability (HA) Control Plane using a 3-node stacked topology. This ensures the etcd database maintains a quorum (a strict voting majority) even if a node crashes. To route internal and kubectl administrative traffic seamlessly, a secondary VIP sits in front of the API servers, managed by an internal load balancing mechanism (such as HAProxy + Keepalived or kube-vip), ensuring traffic is always sent to a healthy control plane node.

1. External Traffic Management: MetalLB and NGINX Ingress

To expose internal Kubernetes Services to the local network, two distinct components work together to handle the physical network connection and the application-level routing.

MetalLB: The Layer 4 Load Balancer

# MetalLB IPAddressPool configuration apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: homelab-pool namespace: metallb-system spec: addresses: - 192.168.1.200-192.168.1.210 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: homelab-l2 namespace: metallb-system spec: ipAddressPools: - homelab-pool

NGINX Ingress Controller: The Layer 7 Router

# Example Ingress resource apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: myapp-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules: - host: myapp.local http: paths: - path: / pathType: Prefix backend: service: name: myapp-service port: number: 80

Traffic Flow: Client → Router → MetalLB VIP → NGINX Pod → Internal ClusterIP Service → Application Pod

2. High Availability Control Plane (Stacked etcd)

To prevent the cluster from collapsing if the master node fails, the control plane is distributed across three physical or virtual machines.

The 3-Node Quorum Requirement

The cluster's state is stored in a distributed key-value database called etcd. To prevent data corruption or "split-brain" scenarios, etcd uses the Raft consensus algorithm, which requires a strict majority (quorum) to approve any read or write.

The Control Plane VIP and Load Balancing

Because there are three identical kube-apiserver instances, worker nodes and administrators cannot point their kubeconfig to a single node's IP.

# kube-vip static pod manifest example apiVersion: v1 kind: Pod metadata: name: kube-vip namespace: kube-system spec: containers: - name: kube-vip image: ghcr.io/kube-vip/kube-vip:v0.6.4 args: - manager env: - name: vip_arp value: "true" - name: vip_interface value: "eth0" - name: address value: "192.168.1.10" - name: port value: "6443" - name: vip_leaderelection value: "true" hostNetwork: true

The Stacked etcd Write Flow

In a "stacked" topology, each control plane node runs its own kube-apiserver and its own local etcd instance. When an event occurs (e.g., creating a Pod), the data flows as follows:

  1. Request Arrival: The request hits the Control Plane VIP and is routed to one of the API servers (e.g., Node 2).
  2. Local Handoff: Node 2's API server validates the request and attempts to save it by talking only to its local etcd instance (127.0.0.1:2379).
  3. Raft Consensus:
    • Node 2's etcd forwards the write request to the elected etcd Leader (e.g., Node 1).
    • The Leader broadcasts the request to all followers.
    • Once a majority of nodes acknowledge the data, the Leader permanently commits the write.
  4. Confirmation: The local etcd on Node 2 informs its API server that the data is safely committed, and the API server returns a success response to the user.
┌─────────────────────────────────────────────────────────────────────┐ │ WRITE FLOW │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ kubectl create pod ───► VIP (192.168.1.10:6443) │ │ │ │ │ ▼ │ │ ┌───────────────────────────────┐ │ │ │ kube-vip / HAProxy / LB │ │ │ └───────────────────────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Node 1 │ │ Node 2 │ │ Node 3 │ │ │ │ API Server │ │ API Server ◄│ │ API Server │ │ │ │ etcd │ │ etcd │ │ etcd │ │ │ │ (Leader) │ │ (Follower) │ │ (Follower) │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ ▲ │ ▲ │ │ │ │ │ │ │ └───────────────┼───────────────┘ │ │ │ │ │ Raft Consensus (majority ack) │ │ │ └─────────────────────────────────────────────────────────────────────┘

Key Takeaways

Related Resources

MetalLB Documentation →
NGINX Ingress Controller Docs →
Kubernetes HA Topology →

← Back to Projects