revert(vpn-ingress): withdraw the L2 lease-collision fix — a node CAN reach a VIP it announces
PR #69 claimed a node cannot reach a LoadBalancer VIP whose Cilium L2 announcement
lease it holds, and excluded the VPN ingress node from announcing on that basis.
The claim makes a sharp prediction; today's power-cycle put ALL EIGHT
cilium-l2announce-* leases on k3s-prod-1, and the prediction failed.
Measured 2026-10-17 from the wireguard pod's host netns on each node: the holder
reaches 192.168.2.20/.22/.23/.24 normally (curl 200 in 18ms on .20) while its
ip neigh for every one of them sits at FAILED. The asserted cause is present
without the asserted effect, which falsifies it. .21 (unifi) fails from all three
nodes and is a separate pre-existing fault.
It is inert because no path resolves a VIP by ARP: cilium-dbg reports
KubeProxyReplacement on [eno1, wg0] and programs 192.168.2.20:443 =>
127.0.0.1:13606, so VIPs are DNAT'd in BPF before any neighbour lookup, on the
forwarded path as well as the host one.
Both probes behind the original diagnosis were bad. `ip neigh` FAILED is
permanent and harmless, and a ping artefact. `curl --interface wg0` — the control
used to rule out a host-netns artefact — fails on all three nodes, including ones
whose ARP resolves, so it discriminates nothing. The deeper error: a MASQUERADEd
client is FORWARDED while every pod-runnable probe is socket-originated. Sharing
a netns is not sharing a hook.
Reverted the policy nodeSelector, the Ansible node label, both alerts, their
promtool tests and the kube-state-metrics allowlist entry. Kept documentation
only: the measurements, which probes lie, and the fact that the forwarded path
remains unmeasured without a connected client.
Also recorded, for the reported "LAN and cluster work, internet does not":
new-peer.sh has emitted a FULL tunnel (0.0.0.0/0) by default since f92707f, so
there is no full-tunnel option to add and no code change is made. The server side
is capable — ip_forward=1, the 10.90.0.0/24 MASQUERADE present with an empty
CILIUM_POST_nat ahead of it, FORWARD accepts, default route intact, nodes reach
1.1.1.1. A full tunnel egresses the HOUSE WAN, not PIA: the egress policy selects
pods by egress-class=vpn, this pod is labelled internet, and tun0 exists on
k3s-prod-3 only. Root cause NOT found; no client has connected since the
power-cycle (0 forwarded packets, no handshake), so it is not reproducible here.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
1 parent
4656b07178
commit
e82dab5df5
13 files changed
+338
-871
No files matched your search
@@ -259,30 +259,3 @@ node_baseline_dns_options:
|
||||
# Written as ONE marked block, so removing an entry here removes it from the node, and
|
||||
# an empty list removes the block entirely.
|
||||
node_baseline_hosts_pins: []
|
||||
|
||||
# --- The node that terminates remote-access WireGuard (tags: vpn-ingress) ----------------------
|
||||
# Hostname of the node the SOHO router forwards WAN udp/51820 to, i.e. the one platform/vpn-ingress
|
||||
# actually serves remote clients from. Set it in group_vars for the environment; EMPTY by default,
|
||||
# because dev has no such forward and because a wrong value is worse than none.
|
||||
#
|
||||
# WHAT IT IS FOR, AND WHY IT IS NOT COSMETIC. The matching node gets
|
||||
# `homelab.keithjackson.dev/vpn-ingress=true`, and
|
||||
# platform-config/cilium/l2-announcement-policy.yaml EXCLUDES that label from announcing any
|
||||
# LoadBalancer VIP. MEASURED on prod 2026-10-08: a node cannot reach a VIP whose Cilium L2
|
||||
# announcement lease it holds itself (the announcer does not answer its own ARP request -- the
|
||||
# neighbour entry goes to `FAILED`). Because vpn-ingress runs on `hostNetwork` and MASQUERADEs
|
||||
# clients to the node's own address, a VPN client inherits that: with the forward on the node
|
||||
# holding the `shared` Gateway lease, all 16 Gateway hostnames were dead over the VPN while PiHole
|
||||
# DNS still resolved. Names worked, every app hung, nothing alerted.
|
||||
#
|
||||
# [parity] MUST name the node the router's forward actually points at. The forward is off-repo and
|
||||
# no check can read it (runbooks/vpn-remote-access.md step 3). Changing the forward is therefore a
|
||||
# two-part change: this value (then re-run the role), and the router line.
|
||||
#
|
||||
# Only ONE node should ever carry the label: it removes that node from VIP announcement candidacy,
|
||||
# so labelling all three would leave nothing announcing any VIP at all. The task below removes the
|
||||
# label from a node that no longer matches, so moving the value moves the label.
|
||||
node_baseline_vpn_ingress_node: ""
|
||||
node_baseline_vpn_ingress_label_key: homelab.keithjackson.dev/vpn-ingress
|
||||
# k3s ships its kubeconfig here; every prod node is a k3s server, so `k3s kubectl` works locally.
|
||||
node_baseline_vpn_ingress_kubeconfig: /etc/rancher/k3s/k3s.yaml
|
||||
Reference in new issue
Block a user