Skip to content

Run a task in a VM

This example shows how to run a one-shot task in a VM via API. You can also use the CLI if you wish.

Tasks could include: CI jobs, databases for testing, isolated environments for privileged AI agents, crons, batch jobs and other kinds of temporary processes.

Watch a demo of the tutorial to see how fast it is to launch microVMs for one-shot tasks.

Tutorial

Create an empty hostgroup configuration.

For the fastest possible boot times, use ZFS for storage.

If you don't have ZFS set up yet, you can simply replace the storage option with something like:

storage: image
storage_size: 20G

Create tasks.yaml:

config:
  host_groups:
  - name: task
    storage: zfs
    count: 0
    vcpu: 1
    ram_gb: 2
    network:
      bridge: brtsk0
      tap_prefix: tsktap
      gateway: 192.168.138.1/24

  github_user: alexellis

  api:
    bind_address: 127.0.0.1
    port: 8081

  kernel_image: "ghcr.io/openfaasltd/actuated-kernel:5.10.240-x86_64-latest"
  image: "ghcr.io/openfaasltd/slicer-systemd:5.10.240-x86_64-latest"

  hypervisor: firecracker

Now start up slicer:

sudo -E slicer up ./tasks.yaml

Now set up a HTTP endpoint using a free service like ReqBin.com or webhook.site.

Write a userdata script to send a POST request to your HTTP endpoint on boot-up, then have it exit.

Save task.sh:

cat > task.sh <<'EOF'
#!/bin/bash
curl -i -X POST -d "$(cat /etc/hostname) booted\nUptime: $(uptime)" \
    https://webhook.site/f38eddbf-6285-4ff8-ae3e-f2e782c73d8f

sleep 1
sudo reboot
exit 0
EOF

Then run your task by booting a VM with the script as its userdata:

curl -isLSf http://127.0.0.1:8081/hostgroup/task/nodes \
    -H "Content-Type: application/json" \
    --data-binary "{
  \"userdata\": $(cat ./task.sh | jq -Rs .)
}"

Check your HTTP bin for the results.

You can also run this in a for loop:

for i in {1..5}
do
  curl -sLSf http://127.0.0.1:8081/hostgroup/task/nodes \
      -H "Content-Type: application/json" \
      --data-binary "{\"userdata\": $(cat ./task.sh | jq -Rs .)}"
done

Each of the 5 tasks that executed and exited, posted to the endpoint

Each of the 5 tasks that executed and exited, posted to the endpoint

Optimise the image for start-up speed

After various Kernel modules are loaded, and the system has performed its self-checking, your code should be running at about the 2.5s mark, or a bit earlier depending on your machine.

To optimise the boot time further for one-shot use-cases, the SSH host key regenerate step that is present on start-up. It can add a few seconds to the boot time, especially if entropy is low on your system.

You can derive your own image to use, with this disabled:

FROM ghcr.io/openfaasltd/slicer-systemd:5.10.240-x86_64-latest

RUN systemctl disable regen-ssh-host-keys &&
    systemctl disable ssh && \
    systemctl disable sshd && \
    systemctl disable slicer-vmmeter

After SSH is disabled, the only way to debug a machine is via the Slicer agent using slicer vm exec to get a shell.

You can also disable slicer-ssh-agent (not actually a full SSH daemon), however the slicer vm commands will no longer work.

If you publish an image to the Docker Hub, make sure you include its prefix i.e. docker.io/owner/repo:tag.

Cache the Kernel to a local file

Rather than downloading an extracting the Kernel on each run of Slicer, you can extract a given vmlinux file and tell the YAML file to use that.

The Kernel must agree with the root filesystem image, which means using a proper tag and not a latest tag.

Why? The Kernel is built as a vmlinux, however its modules are packaged into the root filesystem image.

Run the following:

$ arkade get crane
$ crane ls ghcr.io/openfaasltd/actuated-kernel:5.10.240-x86_64-latest

5.10.240-x86_64-3d7a67d1683b524b4128ad338f90b1da710f2fd9
5.10.240-kvm-x86_64-3d7a67d1683b524b4128ad338f90b1da710f2fd9
5.10.240-x86_64-ea04b63b9117c966a57e17e1bc1bfcf713cd6276
5.10.240-x86_64-bb71bdd1cd06bad2cc11f8ab3f323c3f19d41c8b
5.10.240-x86_64-2f2ebc0bbefe128aa3061e6ea6806cbcdc975208
6.1.90-aarch64-2f2ebc0bbefe128aa3061e6ea6806cbcdc975208
6.1.90-aarch64-5c59e9b9b08eea49499be8449099291c93469b80
5.10.240-x86_64-5c59e9b9b08eea49499be8449099291c93469b80

Pick a stable for your architecture i.e. x86_64-SHA or aarch64-SHA, then run:

$ arkade oci install ghcr.io/openfaasltd/actuated-kernel:5.10.240-x86_64-2f2ebc0bbefe128aa3061e6ea6806cbcdc975208 --output ./
$ ls
vmlinux

Next, find the matching root filesystem image:

$ crane ls ghcr.io/openfaasltd/slicer-systemd

Use it in your YAML file, replacing kernel_image with kernel_file:

  kernel_file: "./vmlinux"
  image: "ghcr.io/openfaasltd/slicer-systemd:5.10.240-x86_64-2f2ebc0bbefe128aa3061e6ea6806cbcdc975208"