How is LXD able to create VMs inside a GitHub runner and is able to fire up a desktop and graphical interface? How is it able to run graphical apps inside that runner? Can someone kindly explain the underlying tech a bit, or may be point to some documentation?
Are you sure LXD is creating actual Virtual Machines? The technology to do that would involve “Nested Virtualisation” which is a fairly recent (~10 years) addition to X86_64. Whilst I’d be happy to believe the Github Actions runners have that enabled (though to be clear, I’ve not checked), LXD as a technology is meant to look like a Virtual Machine without actually being one, the VM management aspect is actually new on the scale of LXDs lifetime.
So if you are creating actual virtual machines with LXD as the manager, that’s fundamentally interactions between the KVM subsystems and the CPU/Hypervisor and isn’t really anything LXD specific. I’d imagine it’s much more likely however you’re still running LXD containers rather than VM’s unless you’ve specifically gone out your way to do otherwise. It’s just that LXD in comparison to say Docker, is much more focused around a container that looks like a traditional VM by design, whereas approaches with say Docker focus more on singular applications/services rather than entire persistent OS environments like you’d use say VirtualBox for.
Regarding graphics then, it could be a Virtual Machine with its own emulated FrameBuffer, or it could be X11/Wayland forwarding (they’re network capable over sockets afterall) that runs the application in the container but the graphics support is run directly on the host (like Snaps!) - without having concrete examples to point to, you could easily end up with the same kind of user experience with massively different backends.
Essentially, you could use Virtual Machines for this stuff, but you’d also probably find that at least historically, a Virtual X11 FrameBuffer would work just fine for CI testing without any GPU or real video output, and it could be an overlap of both (WSL2 takes this to an extreme, the Wayland/Pulseaudio servers run in a separate Virtual Machine to the Linux environment you’re using - and Windows itself runs as a VM too, so you really have 3 different VM’s sharing graphical contexts!)
What do you mean by actual virtual machines?
You can see here, how LXD is being ghvmctl
tool. I also think that it’s kind of an emulated display and not a real one.
As in, is LXD using a hypervisor to run a secondary kernel - the default is no (including for e.g., the Snapcraft Build action).
In this exact example however, the answer is yes, the script is running with a VM, because the script explicitly asks for that.
Ultimately I’d expect the usage of a VM isn’t for the FrameBuffer alone. I imagine the primary motivation for an LXD VM in this context is specifically the kernel; this script tests snaps, and snaps have a lot of Ubuntu kernel specific patches. The Github Actions runner isn’t necessarily running an Ubuntu kernel and could be lacking patches for snap confinement; so to get capture a test that accurately proves the confinement isn’t blocking the basic GUI initialisation, you need to use a Virtual Machine due to the kernel requirements, otherwise you could forget to add the desktop
or wayland
interfaces, and the app would still open because the confinement might not be in place properly; but would break in real use on end user systems.
You’d be able to run other VM’s in Github actions (Terraform is popular in devops for instance), and the virtualised FrameBuffer would be something most hypervisors could handle. In this case I imagine LXD is just being used because it’s already used elsewhere for Snaps heavily; it does the job just fine, and it’s part of the Canonical space. I’m not sure there’s anything particularly special LXD is doing at an architectural level here, as I say, you could give the Actions Runners GUI support without LXD or any other VM’s, it’s just not the primary use of GHA.
Yes, that’s supported and enabled by default since a while.
LXD grew support for VMs exactly 5 years and one month ago