Giving a pod the LAN address another host still holds
MetalLB only hands out addresses from its own pool, so a pod that has to own a LAN address (a scanner target, say) needs a macvlan interface. The hard part is the handover: two hosts answering ARP for one address break both.
My document scanner uploads to a fixed address on the home LAN, over FTP and SMB. That address belonged to the old server. When I moved the document system into the cluster, the new ingest pod had to answer on exactly that address, because the scanner’s setting isn’t something I wanted to touch.
Why not a LoadBalancer
A MetalLB pool can only contain addresses MetalLB can announce on the nodes’ own subnet. Mine is the cluster VLAN, so a Service of type LoadBalancer can never be handed an address on the household LAN. A pod that must own a LAN address needs a second interface instead. I used a Multus macvlan attachment with static IPAM and no gateway, which I describe in the note on putting a pod on the LAN. FTP and SMB can share one pod, and so one address.
The pod ships switched off
Two machines answering ARP for one address break both of them, for a while and
unpredictably. So the Deployment goes into Git with replicas: 0, and scales to
one only after the old host has given the address up.
I wanted the scale-up to stay under my control, and Flux didn’t help. A manually
suspended child Kustomization gets un-suspended by the parent within minutes,
which re-applies replicas: 0 or whatever Git says. What held was the
annotation kustomize.toolkit.fluxcd.io/reconcile=disabled on the single
Deployment, until the pull request with the new state was merged.
The handover order
The old host’s address changes first, and it has to be possible to undo each step:
- Reserve a new address for the old host in the router or DHCP server, and check that it is free.
- Add the new address next to the old one (
nmcli con mod <con> +ipv4.addresses <new>/22) and confirm SSH works on the new address. - From that new session, remove the old address. That ends the old session, so don’t do it from the old one.
- Check from the workstation that the old address no longer answers.
- Only now scale the pod to one.
Test from the workstation, not from the node that runs the pod. A macvlan pod’s own node can’t reach its address, which looks exactly like a broken setup.
Things that broke on the way
The FTP image I used (kibatic/proftpd) crashed in a fresh container. Its
entrypoint runs useradd --gid 33 and then chown paperless:paperless, but no
group of that name exists, so it exits with status 1. The old server only worked
because its long-lived container had been set up earlier. Creating the group
first, with groupadd -o -g 33 paperless, before the entrypoint runs, fixed it.
For testing, curl smb:// can’t talk to a Samba with SMB1 disabled and just says
it could not connect. smbclient works, and the Samba image has it. And a fresh
volume’s root directory is mode 0755, which the application’s init script
recursively chowns but doesn’t loosen, so the FTP user (a different uid) was
refused until an init container ran chmod 0777.