Homelab Kubernetes IP Planning: The Step Nobody Mentions

June 8, 2026

Some of the links in this post may be affiliate links. If you click through and make a purchase, I may earn a commission at no extra cost to you.

You've settled on a 3-node k3s cluster. You've picked your hardware. You're ready to install. Stop. There's one thing you need to do first — and if you skip it, you'll either reinstall your ENTIRE cluster later or spend months debugging intermittent failures that look like cluster bugs but are actually IP conflicts. You need a homelab kubernetes IP plan.

Every k3s guide jumps straight to install commands. None of them tell you to plan your IPs first. But the install command requires a VIP you haven't picked yet, and three networking components need reserved IPs that must never overlap with DHCP — and kube-vip and the MetalLB pool must not overlap with each other (Traefik's IP is deliberately chosen from inside the MetalLB pool). Skip this step and you're building on a cracked foundation.

By the end of this post, you'll have an IP plan — a single page of notes with the exact IPs your cluster needs, verified against your router's DHCP range, ready to plug into the install commands in the next post. This ip planning takes 10 minutes. No special tools. Just pencil, paper, and your router's admin page.

Make sure you're following along with our Production k3s HA In Your Homelab: The Complete Architecture guide to get the full picture.

Key Takeaways

  • Your k3s cluster needs three reserved IP ranges on your LAN, carved from a static block outside DHCP range: kube-vip (1 IP), MetalLB (pool), and Traefik (first pool IP).
  • The k3s install command's --tls-san flag requires the kube-vip VIP at install time — if you don't know your VIP before you run the command, you're reinstalling later.
  • kube-vip and MetalLB both auto-discover network interfaces — you do NOT need to hardcode NIC names in any config. Leave vip_interface blank and kube-vip finds the default route interface on its own.
  • This entire planning session takes 10 minutes. The IPs you write down today will be referenced in the k3s install, kube-vip deployment, and MetalLB configuration posts. One planning session, one page of notes, three posts of copy-paste config.

What IPs Does a Homelab Kubernetes Cluster Need?

Three components need reserved IPs on your LAN subnet. All three use ARP (Address Resolution Protocol), which operates at Layer 2 — same broadcast domain, same subnet as your nodes and your router. kube-vip and the MetalLB pool must not overlap with each other. Traefik's IP is deliberately chosen from inside the MetalLB pool — that overlap is by design. None can be handed out by DHCP.

Here's the lineup:

ComponentIPs NeededPurposeWhat Happens If It Conflicts
kube-vip1 IPControl plane VIP that floats between nodes — this is the IP your kubectl talks tokubectl unreachable, TLS certificate errors, cluster API dead
MetalLBIP range (pool)Provides external IPs for LoadBalancer servicesServices stuck in <pending> forever, no external access
Traefik1 IP (first in MetalLB pool)Ingress controller — HTTP/S routing into your clusterEvery ingress broken, all web UIs unreachable

If DHCP assigns your MetalLB pool's first IP to a random device on your network — say, your kid's tablet — Traefik silently breaks. Not sometimes. Not intermittently. EVERY time that device is on. When the tablet leaves the house? Traefik magically works again. You'll waste a weekend debugging Traefik when the problem was your router's DHCP server the whole time.

I know this because I've done it. The failure is maddening because it looks like a cluster bug. It's not. It's an ARP conflict, and no amount of kubectl describe will find "your kid's tablet stole Traefik's IP" in the logs. Proper ip planning prevents this entire category of failure before you ever touch a terminal.

DHCP-assigned IPs can change. If Traefik's IP changes, every DNS record and internal reference breaks. If the kube-vip VIP changes, your kubeconfig and TLS certificate break. Static IPs aren't optional — they're the foundation everything else sits on.


How Do You Carve a Static IP Block from Your Subnet?

Pick a block of IPs at the top (or bottom) of your subnet, outside your router's DHCP range. For a /24 subnet — that's 254 usable addresses for anyone keeping score at home — a 20-IP static block is plenty.

Here's the math: DHCP range .100–.200 (100 IPs for devices), static block .201–.210 (20 IPs for cluster), remaining .1–.99 and .221–.254 for your router, switches, and future use. Your DHCP range will be different. The principle is the same.

Find Your Numbers

Step 1: Find your subnet. Run ip addr show on any node and look for the interface with that node's IP. Note the CIDR notation — probably /24, maybe /23 if you have a larger network.

Step 2: Find your DHCP range. Open your router's admin page, navigate to the DHCP server settings, and note the pool start and end addresses. Write them down.

Step 3: Pick your static block. Choose a contiguous range outside the DHCP pool — big enough for 3 components plus growth. 20 IPs is safe. 10 is the minimum. Write it down.

A Real Example

My homelab: subnet 192.168.5.0/24. DHCP hands out .100–.200. Static block .201–.210:

  • kube-vip = .201
  • MetalLB pool = .202–.210
  • Traefik = .202 (first IP in the pool)
  • Reserved = .211–.220 (future static assignments — because there's always something)

Here's what that looks like visually:

These are the exact IPs running a cluster with 18+ apps right now. You can see them in the bootstrap README in the homelab-k8s repo. Your numbers will be different. The structure is the same.

Write this down. You'll reference these exact IPs in the k3s install post (--tls-san flag), the kube-vip deployment post (DaemonSet env vars), and the MetalLB configuration post (IPAddressPool CRD). One planning session, one page of notes, three posts of copy-paste config.

New to subnetting? The Subnet Cheat Sheet from freeCodeCamp covers CIDR notation and usable addresses in one page. But the math above is all you need for this planning step.


How Do You Prevent DHCP from Stealing Your Static IPs?

Your router must never hand out an IP from your static block. If DHCP assigns 192.168.5.202 to a random device, and that's your Traefik IP, your ingress breaks. The fix takes 30 seconds in your router's admin panel.

Router-Specific Instructions

pfSense / OPNsense: Services → DHCP Server → LAN → "Address Pool Range" → set the range to not include your static block.

OpenWRT: Network → DHCP and DNS → Static Leases. Configure the DHCP pool to end before your static block starts. Same effect.

Consumer routers (Asus, TP-Link, Netgear): LAN → DHCP Server → adjust "IP Pool End" to end before your static block starts. Most consumer routers don't have explicit exclusion fields — shrinking the pool achieves the same thing.

If You Can't Configure Exclusions

Shrink the DHCP pool. Move the end address to just before your static block. The router won't hand out those IPs because they're not in the pool. It's not elegant, but it works.

Once your DHCP exclusions are set, verify: nmap -sn <static block range> should return no results. If anything responds, that IP is in use — find it and move it before you proceed to Why k3s? Choosing and Installing k3s for Your Homelab, where you'll use the VIP you planned here as the --tls-san value.


Do You Need to Hardcode NIC Names for kube-vip and MetalLB?

Here's something nobody tells you: kube-vip and MetalLB both auto-discover network interfaces. You do not need to find your NIC name, hardcode it in any config, or worry about whether your nodes have matching interface names. The software handles it.

How kube-vip Finds Your Interface

When vip_interface is set to "" (empty string), kube-vip looks up the routing table and finds whichever interface has the default gateway. No config needed. Each node figures it out independently:

# kube-vip DaemonSet — leave blank for auto-detection
env:
- name: vip_interface
  value: ""  # leave blank to auto-detect the default interface

enp1s0 on a BeeLink, eth0 on a Raspberry Pi, ens18 on a Proxmox VM — all work simultaneously because each node discovers its own interface. You don't configure it. You don't even need to know the name.

How MetalLB Finds Your Interfaces

MetalLB's speaker DaemonSet runs with hostNetwork: true and announces on ALL host interfaces by default. An excludel2 ConfigMap filters out virtual and non-physical interfaces:

# MetalLB excludel2 ConfigMap — filters out virtual interfaces
apiVersion: v1
kind: ConfigMap
metadata:
  name: metallb-excludel2
  namespace: metallb-system
data:
  excludel2.yaml: |
    announcedInterfacesToExclude:
      - "^docker.*"
      - "^cali.*"
      - "^veth.*"
      - "^tunl.*"
      - "^flannel.*"
      - "^kube-ipvs.*"
      - "^cni.*"
      - "^lo$"

Everything matching those regex patterns gets skipped. Everything else — your real physical interfaces — gets announced on. No positive selection needed.

What This Means for Your Hardware

Mixed NIC names are fine. The homogeneous-hardware rule from the architecture comparison post applies to CPU architecture (all amd64 or all arm64), NOT NIC names. You can run a BeeLink, a Raspberry Pi, and a Proxmox VM in the same cluster — each finds its own interface.

The ONE thing you do need: ensure each node has a default route on a physical interface. If a node has no default gateway configured, kube-vip can't find the interface. But that's a basic networking requirement, not a Kubernetes one.

The one time you DO want to set a specific NIC: when a node has multiple physical NICs and you need to tell kube-vip which one carries the VIP traffic. In that case, set vip_interface to the interface name (e.g., eth1). For single-NIC nodes — which covers most homelab hardware — leave it blank and let auto-discovery handle it.

Every homelab guide tells you to find your NIC name and hardcode it. They're solving a problem the software already solved. Telling you what you DON'T need to do — that's the real value here.


Your IP Plan — Put It All Together

You now have everything you need for a one-page IP plan. Here's the template:

My IP Plan
----------
Subnet: _______._______._______._______/_____
DHCP Range: _______._______._______._______ - _______._______._______._______
Static Block: _______._______._______._______ - _______._______._______._______

kube-vip VIP: _______._______._______._______  (one IP from static block)
MetalLB Pool: _______._______._______._______ - _______._______._______._______  (range)
Traefik IP:   _______._______._______._______  (first IP in MetalLB pool)

DHCP exclusion confirmed: [ ]
All nodes have default gateway: [ ]

Fill in the blanks. Check the boxes. Stick this on a sticky note or save it in your notes app. You'll reference it in the k3s install, kube-vip deployment, and MetalLB configuration posts — and your ip planning is done for good.


Frequently Asked Questions

Can I use a different subnet for the MetalLB pool?

No. MetalLB uses ARP (Layer 2), which requires all IPs to be on the same broadcast domain as your nodes. A different subnet requires routing (Layer 3), which MetalLB's ARP mode doesn't support. If you need cross-subnet LoadBalancer IPs, you need BGP mode — and a BGP-capable router. For homelab, keep everything on the same subnet.

What if I already installed k3s without planning IPs?

Find your node IPs (kubectl get nodes -o wide). Check your router's DHCP range. Pick an unused IP outside DHCP for kube-vip. Pick a contiguous unused range for MetalLB. If you didn't set --tls-san during install, you need to reinstall k3s on each node to add it — there's no post-install fix. Better plan: do this BEFORE installing. That's why this post exists before the k3s install post.

How many IPs do I need for a single-node cluster?

One: the node's own IP. kube-vip is pointless on a single node — there's nowhere for the VIP to float to. MetalLB can use a single IP if you only need one LoadBalancer service. But if you read the architecture comparison post, you already know why single-node isn't production homelab. Three nodes, plan your IPs. If you're not sure, plan for kube-vip anyway. If you decide to add more nodes in the future, you'll thank past you!


What's Next?

You've got your IP plan. The numbers are written down. DHCP is configured. You know your interfaces auto-discover. Now you're ready to install k3s.

Why k3s? Choosing and Installing k3s for Your Homelab walk through the exact install commands — with your VIP ready for --tls-san. No guesswork. No "pick an IP" buried in a code comment. Your IPs are planned, documented, and DHCP-proof. Let's install a cluster.

Don't be afraid to break things. Just do something.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.