Documentation menu

Networking & L3 routing

Most local-Kubernetes tools hide cluster services behind port-forwards or NAT. klimax does the opposite: it routes the kind bridge subnet from your Mac into the VM at layer 3, so a pod IP is the address you connect to — and the pod sees your Mac's real source IP back.

Your Mac curl VIP macOS route 172.30/16 → lima0 lima0 vzNAT ip_forward=1 kind bridge br-xxxx 172.30.0.1 Pod / VIP MetalLB 172.30.1.200 REQUEST → dst 172.30.1.200 reply — src 172.30.1.200, dst = your Mac (no SNAT, source IP preserved)
A request and its reply. No port-mapping, no address translation rewriting the source.

The network stack

macOS host
  bridge1xx (host IP, macOS-assigned)
      │  vzNAT — Apple VZNATNetworkDeviceAttachmentLima VZ guest
  lima0 (guest IP, macOS-assigned)
  br-xxxx (172.30.0.1/16)   ← Docker bridge "kind"
      │
  kind nodes (172.30.N.x)

vzNAT IPs are assigned by macOS and can't be configured. klimax detects the VM's lima0 IP at runtime — nothing is hardcoded — so multiple Lima VMs each get a distinct IP on their own bridge and coexist without conflict.

How pure L3 routing works

  1. Host route. klimax up adds 172.30.0.0/16 → <lima0-IP> on macOS via sudo /sbin/route (this is the one-time sudo prompt).
  2. Forwarding + SNAT exemption. Inside the VM, ip_forward=1 and a systemd oneshot apply idempotent iptables rules:
    • a NAT exemption (before Docker's MASQUERADE) so kind→host traffic leaves lima0 without SNAT;
    • DOCKER-USER forward rules that explicitly allow host→kind and established return traffic.
  3. Survives Docker restarts. A docker.service.d drop-in re-runs the rules whenever Docker restarts.

The result: curl http://172.30.1.200/ on your Mac reaches the MetalLB VIP directly, and the pod sees your real source address.

Reaching the API server: two modes

klimax supports two ways for kubeconfigs to address cluster API servers, controlled by network.disablePortMirroring.

Direct IP — disablePortMirroring: true · default kubectl on your Mac lima0 VM NIC · 192.168.64.3 kube-apiserver :700N · cert SAN += lima0 DIRECT L3 NO LIMA PORT MIRROR ~/.kube/config → https://192.168.64.3:700N Loopback — disablePortMirroring: false kubectl on your Mac Lima port mirror host + guest agent · gRPC kube-apiserver 0.0.0.0:700N in VM 127.0.0.1:700N MIRRORS LISTEN SOCKETS ~/.kube/config → https://127.0.0.1:700N
Same kubectl, two address paths. The default (direct L3 to lima0) coexists with other Lima VMs; set disablePortMirroring: false to fall back to stable 127.0.0.1 loopback.

Direct-IP mode (default — disablePortMirroring: true)

  • Lima's TCP port mirroring is off, so klimax coexists with other Lima-based VMs (Colima, Rancher Desktop) that also manage kind clusters — otherwise both VMs race to mirror the same port (e.g. 7001) to 127.0.0.1 and collide.
  • Kubeconfigs use the VM's lima0 IP (e.g. https://192.168.64.3:700N), L2-reachable from the host via vzNAT; the API-server cert gets the lima0 IP added as a SAN automatically.

Loopback mode (disablePortMirroring: false)

  • API servers listen on 0.0.0.0:700N inside the VM.
  • Lima's hostagent mirrors those ports to 127.0.0.1:700N on the host.
  • Kubeconfigs point at https://127.0.0.1:700N — a stable address that survives VM restarts. Use it when running a single klimax VM, or when host security software (e.g. CrowdStrike) blocks direct vzNAT IPs.

disablePortMirroring is a VM-level setting — it only takes effect on a fresh VM (klimax destroy && klimax up). With the default, the lima0 IP is assigned dynamically and may change on restart; re-run klimax kubeconfig merge <name> afterwards to refresh ~/.kube/config.

Registry traffic

Every cluster's containerd is patched to transparently cache pulls from docker.io, quay.io, gcr.io, and Google Artifact Registry (us-docker.pkg.dev, us-central1-docker.pkg.dev) through the pull-through mirrors. All mirror containers join the kind Docker network, so nodes resolve them by hostname. See Registry mirrors.

🔍

klimax status shows the VM state, the host route, and whether the iptables rules are present — start there when connectivity looks off, then klimax doctor.