The admin path is one jump host; this is the firewall layer that makes that statement true. The whole trick is ordering — and one kubernetes-specific detail that quietly bites everyone.

First: let Kubernetes forward

Ubuntu ships ufw with DEFAULT_FORWARD_POLICY="DROP", which silently breaks pod traffic that traverses a node. Fix before anything else:

sudo sed -i 's/DEFAULT_FORWARD_POLICY=.*/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw

The rules

sudo ufw allow in from 10.22.50.0/24   # nodes: etcd, kubelet, VXLAN
sudo ufw allow in from 10.22.10.120    # jump: SSH + API
sudo ufw allow in from 10.22.10.50     # break-glass springboard
sudo ufw deny in 2379,2380             # etcd: nodes only
sudo ufw deny in 22
sudo ufw deny in 6443
sudo ufw enable

Why the order is the whole article

UFW is first-match-wins. The three allows match their sources and stop; the two denies only ever catch everyone else. Move a deny above the allows and you have silently locked out your own jump host. Note what is not listed: web, DNS and node ports stay reachable, because the INPUT policy itself is left permissive — the deny lines are targeted, not a blanket.

Operating discipline

Apply per node, one at a time, with an SSH session already open (ufw keeps established connections alive). Verify before closing it: from the jump kubectl get nodes is green, from anywhere else port 22/6443 on the node answers refused, and the public services are untouched. Rollback is one command on the offending node — sudo ufw disable — which is exactly why this change is allowed to be boring.

Keep the etcd deny in even though the nodes are already trusted: defense in depth costs one line, and 2379 is the root of the whole cluster.