If you have to stay in emacs, then the two options I've tried are:
(process-send-string "my-vm-1" "command to vm")
where I'd change my-vm-1 to my-vm-2 and so on in a macro. The other option I use now is to run gnu-parallel via M-x !
.
A more recent solution for VMs to use their own mgmt interface to send commands to to multiple instances. This may turn out to be the most robust in the long-run especially if you rely on nagios-type remote management tools.
ADDENDUM:
Would gnu-parallel be able to jump these multiple hops?
I don't see why not. At its most simplest, just invoke another gnu-parallel command on each remote VM. If you need to customize some portion of your command to each VM, look into gnu-parallel's --hostgroup option under sshlogin. This script might give you ideas on how to loop through them.
You realize all this is far from tweaking with emacs buffers but not all that different from Tramp's multi-hops. Maybe a custom external method in Tramp can hop into each container, run a custom command, and return the results as a log buffer back to emacs.