Just install LXD on your already running Ubuntu install. Then you can have nested containers and create more K8s nodes (workers or masters) inside LXD containers. Do another LXD container with Pi-Hole in it and call it a day.
For the network side of things, you could install libvirt and run a single *BSD VM using Virt-Manager (either locally if you are running a desktop environment / window manager, or from another Linux box, you can install virt-manager on another linux PC or VM or server and connect from that to your Ubuntu server to manage VMs).
I’d say to stay away from Citrix. As for a router, you can either get something that can run dd-wrt or openwrt, or make your own with either a x86 box (Protectli) or ARM SBCs (NanoPi R4S) or RockPro64 with a PCI-E network card.
You have Raspberry Pis already. My main router is a Pi 3. I use the WiFi as WAN and the LAN side has VLANs set on it. I run iptables as the firewall. You don’t need to use the WiFi (or you can use it to give WiFi to other devices, i.e. an Access Point). Grab a copy of Alpine Linux and follow my Easy to Follow guide, maybe adapt it a bit for your own infrastructure.
This wiki will guide you through all the setup steps, from DHCP to firewall rules. I don’t have the VPN setup, but I have linked PLL’s Wireguard setup in there. Also, Wendell just released a wireguard guide, I can’t wait to watch it.
Then you can install something like Unbound on the Pi and run DNS too (or maybe Pi-Hole, but I don’t know its support for Alpine.
You can either buy a USB to Ethernet adapter and have 2 ethernet ports on your Pi, or setup VLANs on the single Pi port. But keep in mind your speed will be a bit limited by your port (100 Mbps for Pi 3 and older, 1 Gbps for Pi 4). On Alpine, you can run ip link add link eth0 name eth0.70 type vlan id 70 && ip link set dev eth0.70 up to create a VLAN with ID 70 (assuming your switch supports it obviously). I just put this command in my startup script that I described in the guide.