The only thing you can do as an unprivileged user is get a user namespace which maps your own single uid and gid to any uid/gid that you want.
Anything else requires privileges, either in obvious ways by running the logic directly as root, or indirectly through setuid/setcap helpers.
Anything that needs to put mounts in place (and doesn’t rely solely on FUSE) needs root privileges, so in our case, that means interacting with ZFS, LVM, btrfs, Ceph, …
The same goes on the network side, only root can create network interfaces on the host system, so all our network stuff requires root (create and run bridges, create veth pairs to attach to the containers, create tap devices for VMs, apply tc/iptables/nft rules, …).
Then the same is true for the security stuff, we need root to generate AppArmor namespaces, generate custom per-instance apparmor policies and load them into the kernel, …
It’s certainly possible to split out every bit of privileged logic into their own setuid/setcap binaries to give the illusion of everything actually being done by the unprivileged user, but it’s basically just that, an illusion 
There are ways to do the filesystem stuff without privileges, but that involves FUSE and so gets rather slow. Similarly, it’s possible to do a bunch of network stuff in userspace by using a tun device inside the container and connecting that to a userspace relay daemon, but again, that’s going to be very slow.
Getting more than one uid/gid isn’t possible without extra privileges (such as using newuidmap/newgidmap), at least until we complete our work on implementing isolated user namespaces (see https://www.youtube.com/watch?v=mOLzSzpVwHU)