From a2a5c7f4af3b899947142e2952872edbcd7f2b7e Mon Sep 17 00:00:00 2001 From: danbugs Date: Tue, 27 Oct 2026 21:52:38 +0000 Subject: [PATCH 1/3] feat(urunc-deploy): ship hluk and install it on the nodes urunc-deploy installs urunc and every hypervisor it drives, except hluk, the monitor of Hyperlight guests, which had to be put on the PATH of each node by hand. A build stage downloads the hluk release for the build architecture, checks it against the sums the release publishes and places it next to the other hypervisors. hluk embeds the kernel it boots and its Linux releases are static binaries, so that one file is all a node needs. The version is a build argument with the release as its default, and the Dockerfile notes what it moves together with. hluk joins the default HYPERVISORS list of the DaemonSet and is copied to /opt/urunc/bin like the rest; uninstall already removes that directory. The shipped configuration points the hyperlight-unikraft monitor at that path, which urunc takes over a PATH lookup. The path is only kept when urunc-deploy installed hluk: a deployment whose HYPERVISORS leaves it out keeps resolving a hand-installed hluk from the PATH as it does today, and the URUNC_MONITORS_HYPERLIGHT_UNIKRAFT_PATH variable sets it either way. Signed-off-by: danbugs --- deployment/urunc-deploy/Dockerfile | 22 +++++++++++++++++++ deployment/urunc-deploy/config.toml | 1 + deployment/urunc-deploy/scripts/install.sh | 13 ++++++++++- .../urunc-deploy/base/urunc-deploy.yaml | 2 +- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/deployment/urunc-deploy/Dockerfile b/deployment/urunc-deploy/Dockerfile index d8334be63..f2f2fd646 100644 --- a/deployment/urunc-deploy/Dockerfile +++ b/deployment/urunc-deploy/Dockerfile @@ -74,6 +74,27 @@ RUN ARCH=$(uname -m) && \ WORKDIR /artifacts RUN cp /cloud-hypervisor . +FROM alpine:3.21@sha256:b6a6be0ff92ab6db8acd94f5d1b7a6c2f0f5d10ce3c24af348d333ac6da80685 AS hluk-builder +RUN apk update && apk add --no-cache curl tar +# hluk, the monitor of Hyperlight guests, embeds the Unikraft kernel it boots +# and its Linux releases are static binaries, so the release tarball is all a +# node needs. The download is checked against the checksums of the release. +# Images built for one hluk release do not run on another, so this version +# moves together with HLUK_VERSION in vm_test.yml, hyperlight-unikraft in +# docs/variables/versions.yml and the image tag in urunc-deploy-test.yml. +ARG HLUK_VERSION=v0.18.0 +RUN ARCH=$(uname -m) && \ + VERSION="${HLUK_VERSION}" && \ + RELEASE_URL="https://github.com/hyperlight-dev/hyperlight-unikraft/releases" && \ + ASSET="hluk-${VERSION}-${ARCH}-unknown-linux-musl.tar.gz" && \ + curl -fL -o "${ASSET}" "${RELEASE_URL}/download/${VERSION}/${ASSET}" && \ + curl -fL -o SHA256SUMS "${RELEASE_URL}/download/${VERSION}/SHA256SUMS" && \ + grep " ${ASSET}\$" SHA256SUMS | sha256sum -c - && \ + tar xzf "${ASSET}" && \ + test -x hluk +WORKDIR /artifacts +RUN cp /hluk . + FROM quay.io/kata-containers/kata-deploy:3.15.0@sha256:fbab8bdbe910b52cf9396261f887f894cd3e71f86abe68ec11595ab7628b4a10 AS qemu-builder WORKDIR /artifacts RUN ARCH=$(uname -m) && \ @@ -88,6 +109,7 @@ COPY --from=qemu-builder /opt/kata-artifacts/opt/kata/share/kata-qemu/qemu /urun COPY --from=qemu-builder /opt/kata-artifacts/opt/kata/libexec/virtiofsd /urunc-artifacts/libexec/virtiofsd COPY --from=firecracker-builder /artifacts /urunc-artifacts/hypervisors COPY --from=cloud-hypervisor-builder /artifacts /urunc-artifacts/hypervisors +COPY --from=hluk-builder /artifacts /urunc-artifacts/hypervisors COPY --from=urunc-builder /artifacts/dist /urunc-artifacts RUN apk update && \ diff --git a/deployment/urunc-deploy/config.toml b/deployment/urunc-deploy/config.toml index 2043efd0c..d04666d36 100644 --- a/deployment/urunc-deploy/config.toml +++ b/deployment/urunc-deploy/config.toml @@ -45,6 +45,7 @@ path = "/opt/urunc/bin/solo5-hvt" [monitors.hyperlight-unikraft] default_memory_mb = 256 default_vcpus = 1 +path = "/opt/urunc/bin/hluk" [extra_binaries.virtiofsd] path = "/opt/urunc/libexec/virtiofsd" diff --git a/deployment/urunc-deploy/scripts/install.sh b/deployment/urunc-deploy/scripts/install.sh index a9e8bc4aa..bfcf821f5 100644 --- a/deployment/urunc-deploy/scripts/install.sh +++ b/deployment/urunc-deploy/scripts/install.sh @@ -62,7 +62,7 @@ container_runtime_version_file="${urunc_install_dir}/container-runtime-version" # Configurable keys discovered from config.toml urunc_config_keys="" -HYPERVISORS="${HYPERVISORS:-"firecracker cloud-hypervisor qemu solo5-hvt solo5-spt"}" +HYPERVISORS="${HYPERVISORS:-"firecracker cloud-hypervisor qemu solo5-hvt solo5-spt hluk"}" IFS=' ' read -a hypervisors <<< "$HYPERVISORS" function host_systemctl() { @@ -120,6 +120,10 @@ function install_artifacts() { echo "Installing solo5-hvt" install_artifact /urunc-artifacts/hypervisors/solo5-hvt /host${urunc_bin_dir}/solo5-hvt ;; + hluk) + echo "Installing hluk" + install_artifact /urunc-artifacts/hypervisors/hluk /host${urunc_bin_dir}/hluk + ;; *) echo "Unsupported hypervisor: $hypervisor" ;; @@ -276,6 +280,13 @@ function install_urunc_config() { echo "Installing urunc configuration file" mkdir -p /host${urunc_config_dir} sed "s|qemu-system-x86_64|qemu-system-$(uname -m)|" /deployment/config.toml > /host${urunc_config_file} + # The path of hluk is only kept when urunc-deploy installed it: until now + # hluk went on the PATH by hand, and a configured path that does not exist + # would hide a binary that does. URUNC_MONITORS_HYPERLIGHT_UNIKRAFT_PATH + # still sets it either way. + if ! printf '%s\n' "${hypervisors[@]}" | grep -qx hluk; then + sed -i '\|^path = "/opt/urunc/bin/hluk"$|d' /host${urunc_config_file} + fi override_urunc_config_from_env "/host${urunc_config_file}" echo "urunc configuration file installed at ${urunc_config_file}" } diff --git a/deployment/urunc-deploy/urunc-deploy/base/urunc-deploy.yaml b/deployment/urunc-deploy/urunc-deploy/base/urunc-deploy.yaml index 2166ea76f..aa8582617 100644 --- a/deployment/urunc-deploy/urunc-deploy/base/urunc-deploy.yaml +++ b/deployment/urunc-deploy/urunc-deploy/base/urunc-deploy.yaml @@ -48,7 +48,7 @@ spec: fieldRef: fieldPath: spec.nodeName - name: HYPERVISORS - value: "firecracker cloud-hypervisor qemu solo5-hvt solo5-spt" + value: "firecracker cloud-hypervisor qemu solo5-hvt solo5-spt hluk" - name: DEBUG value: "false" # Optional overrides for /etc/urunc/config.toml. Any URUNC_* variable From 7d81d6cf8d636cec68da614f7b255486817d834d Mon Sep 17 00:00:00 2001 From: danbugs Date: Tue, 27 Oct 2026 21:52:38 +0000 Subject: [PATCH 2/3] docs: say that urunc-deploy installs hluk The Kubernetes tutorial documents the HYPERVISORS variable of the DaemonSet, which names the hypervisors urunc-deploy installs, and the hypervisor support page says that urunc-deploy ships hluk, so on Kubernetes there is nothing to install by hand. Signed-off-by: danbugs --- docs/hypervisor-support.md | 5 +++++ docs/tutorials/How-to-urunc-on-k8s.md | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/hypervisor-support.md b/docs/hypervisor-support.md index db32d08da..5a2b8bd66 100644 --- a/docs/hypervisor-support.md +++ b/docs/hypervisor-support.md @@ -298,6 +298,11 @@ install it: sudo install -m0755 hluk /usr/local/bin/hluk ``` +On Kubernetes, [`urunc-deploy`](../tutorials/How-to-urunc-on-k8s#urunc-deploy) +ships `hluk` and, with `hluk` in its `HYPERVISORS` list as it is by default, +installs it on every node under `/opt/urunc/bin` and points the configuration +it writes at it, so there is nothing to install by hand. + #### Hyperlight and `urunc` In the case of [Hyperlight](https://github.com/hyperlight-dev/hyperlight), diff --git a/docs/tutorials/How-to-urunc-on-k8s.md b/docs/tutorials/How-to-urunc-on-k8s.md index d6b73352b..38c847b33 100644 --- a/docs/tutorials/How-to-urunc-on-k8s.md +++ b/docs/tutorials/How-to-urunc-on-k8s.md @@ -230,7 +230,9 @@ During installation, the following steps take place: - The `urunc-deploy` Pod is deployed with privileges on the host, and the `containerd` configuration is mounted inside the Pod. - `urunc-deploy` performs the following tasks: * Copies `urunc` and `containerd-shim-urunc-v2` binaries to the host under `/usr/local/bin`. - * Copies hypervisor binaries to the host under `/opt/urunc/bin`. + * Copies the hypervisor binaries to the host under `/opt/urunc/bin`. The + `HYPERVISORS` environment variable of the DaemonSet names the ones to + install, all of them by default. * Copies QEMU data files to `/opt/urunc/share`. * Installs a configuration file at `/etc/urunc/config.toml`. * Registers `urunc` as a `containerd` runtime: with containerd 2.x through a From 13dcdd36e8f36c6e0bc682c42217de093689374a Mon Sep 17 00:00:00 2001 From: danbugs Date: Tue, 27 Oct 2026 21:52:38 +0000 Subject: [PATCH 3/3] ci(urunc-deploy): test that hluk is installed and boots a guest The urunc-deploy test checks for the binary on the node and, on amd64, runs the hello-hyperlight-unikraft image through the installed hluk, which prints its greeting. The step describes the pod before reading its logs, so a failure shows why. Signed-off-by: danbugs --- .github/workflows/urunc-deploy-test.yml | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/urunc-deploy-test.yml b/.github/workflows/urunc-deploy-test.yml index cd7a186a8..6c2a3e1c6 100644 --- a/.github/workflows/urunc-deploy-test.yml +++ b/.github/workflows/urunc-deploy-test.yml @@ -161,6 +161,7 @@ jobs: run: | docker exec urunc-deploy-test-control-plane ls -la /usr/local/bin/urunc || exit 1 docker exec urunc-deploy-test-control-plane ls -la /usr/local/bin/containerd-shim-urunc-v2 || exit 1 + docker exec urunc-deploy-test-control-plane ls -la /opt/urunc/bin/hluk || exit 1 - name: Deploy nginx-spt unikernel (arm64) if: matrix.arch == 'arm64' @@ -228,6 +229,36 @@ jobs: cat /tmp/logs.txt kubectl describe pod httpreply-fc-amd64 || true + - name: Deploy hello-hyperlight-unikraft unikernel (amd64) + if: matrix.arch == 'amd64' + run: | + cat <