Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/heimdall

docs/bench/ovn-bench/README.md

Rusternetes + OVN: three rows, two hosts

Lane TUNNR-OPEN, 2026-11-07. Stock ovn-kubernetes (release-1.4, by digest) on two-node clusters. 3 measured runs per row, medians over the runs. Row P ran on dwarf, rows B and A on oden (see "Host and load per run"). Every bench pod ran under a seccomp profile learned from the bench itself (see "Seccomp profiles"). Raw JSON per run: results/<row>/all<n>.json, beside this file, with each row's evidence receipt. This page is a copy of the bench report kept in tunnr (a private repo, commit 07ddaa8), where the bench scripts (scripts/ovn-bench/) live; the tables below are printed from the JSON here.

Setup OS Runs Nodes ready OVN ready Idle RAM cp / worker Warm pod start Cold pod start Network across / same node Functional Loaded RAM cp / worker (mean) Peak RAM cp / worker Iggy msgs/s
P: Rusternetes + podman + OVN Debian 13 3 15.6 s 51.3 s 785 / 798 MiB 6.44 s 15.27 s 3.38 / 24.93 Gbit/s 3/3 runs 6/6 953 / 1104 MiB 986 / 1174 MiB 24 846
B: k3s + OVN Debian 13 3 29.4 s 92.5 s 1073 / 856 MiB 0.74 s 4.21 s 3.24 / 34.70 Gbit/s 3/3 runs 6/6 1127 / 1079 MiB 1141 / 1098 MiB 20 855
A: Rusternetes + OVN + youki (tunnr) tunnr 3 7.0 s 37.5 s 570 / 545 MiB 0.48 s 3.62 s 2.90 / 25.19 Gbit/s 3/3 runs 6/6 689 / 743 MiB 720 / 755 MiB 20 810

Host and load per run

Setup Run Host (cores) load1 at boot load1 at bench start load1 at Iggy window end Foreign work at boot
P: Rusternetes + podman + OVN 1 dwarf (12) 0.5 1.7 8.7 0 process(es)
P: Rusternetes + podman + OVN 2 dwarf (12) 0.4 3.0 10.7 0 process(es)
P: Rusternetes + podman + OVN 3 dwarf (12) 0.4 2.3 12.4 0 process(es)
B: k3s + OVN 1 oden (32) 40.1 35.6 29.9 18 process(es)
B: k3s + OVN 2 oden (32) 23.6 24.9 40.6 8 process(es)
B: k3s + OVN 3 oden (32) 31.0 29.2 20.9 8 process(es)
A: Rusternetes + OVN + youki (tunnr) 1 oden (32) 37.6 36.7 29.7 12 process(es)
A: Rusternetes + OVN + youki (tunnr) 2 oden (32) 22.8 23.5 31.5 6 process(es)
A: Rusternetes + OVN + youki (tunnr) 3 oden (32) 37.3 33.7 33.3 10 process(es)

Rows

Row Kubernetes Container runtime path OS
P: Rusternetes + podman + OVN Rusternetes, fork node/podman-seccomp 12d6f49b: one static binary (API server, controller manager, scheduler, kubelet, embedded store) on the control plane, kubelet only on the worker the kubelet's Docker-API backend → podman system service (podman 5.4.2, crun 1.21) Debian 13 genericcloud, kernel 6.12
B: k3s + OVN k3s v1.36.5+k3s1 (flannel, network policy and kube-proxy off) containerd (k3s), runc 1.4.2 Debian 13 genericcloud, kernel 6.12
A: Rusternetes + OVN + youki (tunnr) Rusternetes, fork node/tunnr-open 0a978bdb, on the tunnr node image (media ob13) the kubelet's built-in runtime (youki 0.7.0, vendored libcontainer, seccomp-bpf backend) tunnr (no general-purpose OS), kernel 6.12.104

Rows P and B run on the same base image with the same VM shape. They differ only in the Kubernetes layer. On every row the kubelet runs a pod that names no profile under the runtime's default profile (seccompDefault).

Method

Seccomp profiles: learned from the bench itself

Every bench container states a Localhost seccomp profile, the same five files on all three rows: busybox, iperf3, nginx-alpine, iggy-server and iggy-bench. A call that is not in a profile kills the process.

Profile Allowed calls Distinct calls learned on P / B / A Distinct calls merged Container runs merged
busybox 91 74 / 86 / 60 100 76
iperf3 89 80 / 84 / 63 102 27
nginx-alpine 64 44 / 46 / 24 68 24
iggy-server 96 98 / 85 / 65 114 4
iggy-bench 91 90 / 75 / 53 105 16

What was enforced

Per row, from the seccomp audit pods of the counted runs (a privileged pod per node that reads every process's Seccomp mode and filter count; mode 2 = filtered) and the row's evidence receipt. On tunnr a pod's process also carries the filters of the node programs above it (PID 1, Rusternetes, the shim), so it shows 4 filters; on the Debian rows it shows the pod's one.

P: Rusternetes + podman + OVN: what was enforced

Evidence receipt debian-p sha256 3e980547db34f5d6, profile generator 0.4.3 (f093633c1166), kernel Debian 13 genericcloud 6.12.115+deb13.1-cloud-amd64 (the base image's kernel, from the nodes' boot logs).

Container (command) Node Profile stated Seccomp mode / filters seen Snapshots
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - cp bench/iggy-bench.json 2 / 1 57
httpd -f -p 8000 -h /w cp bench/busybox.json 2 / 1 35
iperf3 -c 10.244.0.20 -t 10 -J cp bench/iperf3.json 2 / 1 3
iperf3 -c 10.244.1.10 -t 10 -J cp bench/iperf3.json 2 / 1 5
iperf3 -s cp bench/iperf3.json 2 / 1 43
sh -c iperf3 -c 10.244.0.20 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 1 4
sh -c iperf3 -c 10.244.1.10 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 1 6
sh -c iperf3 -s cp bench/iperf3.json 2 / 1 43
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` cp bench/busybox.json 2 / 1
sleep 5 cp bench/busybox.json 2 / 1 2
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - worker bench/iggy-bench.json 2 / 1 46
httpd -f -p 8080 -h /w worker bench/busybox.json 2 / 1 137
iggy-server --with-default-root-credentials worker bench/iggy-server.json 2 / 1 32
iperf3 -s worker bench/iperf3.json 2 / 1 38
sh -c iperf3 -s worker bench/iperf3.json 2 / 1 38
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` worker bench/busybox.json 2 / 1
sleep 3600 worker bench/busybox.json 2 / 1 88
sleep 5 worker bench/busybox.json 2 / 1 3

Exceptions, as the receipt lists them:

B: k3s + OVN: what was enforced

Evidence receipt debian-b sha256 d491eca7f02de25e, profile generator 0.4.3 (f093633c1166), kernel Debian 13 genericcloud 6.12.115+deb13.1-cloud-amd64 (the base image's kernel, from the nodes' boot logs).

Container (command) Node Profile stated Seccomp mode / filters seen Snapshots
/pause cp sandbox: RuntimeDefault (seccompDefault) / runtime default 0 / 0 468
/pause cp sandbox: RuntimeDefault (seccompDefault) / runtime default 2 / 1 347
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - cp bench/iggy-bench.json 2 / 1 144
httpd -f -p 8000 -h /w cp bench/busybox.json 2 / 1 75
iperf3 -c 10.244.0.10 -t 10 -J cp bench/iperf3.json 2 / 1 11
iperf3 -c 10.244.1.21 -t 10 -J cp bench/iperf3.json 2 / 1 9
iperf3 -s cp bench/iperf3.json 2 / 1 27
sh -c iperf3 -c 10.244.0.10 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 1 11
sh -c iperf3 -c 10.244.1.21 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 1 9
sh -c iperf3 -s cp bench/iperf3.json 2 / 1 27
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` cp bench/busybox.json 2 / 1
sleep 5 cp bench/busybox.json 2 / 1 67
/pause worker sandbox: RuntimeDefault (seccompDefault) / runtime default 0 / 0 456
/pause worker sandbox: RuntimeDefault (seccompDefault) / runtime default 2 / 1 812
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - worker bench/iggy-bench.json 2 / 1 140
httpd -f -p 8080 -h /w worker bench/busybox.json 2 / 1 152
iggy-server --with-default-root-credentials worker bench/iggy-server.json 2 / 1 72
iperf3 -s worker bench/iperf3.json 2 / 1 28
sh -c iperf3 -s worker bench/iperf3.json 2 / 1 28
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` worker bench/busybox.json 2 / 1
sleep 3600 worker bench/busybox.json 2 / 1 26
sleep 5 worker bench/busybox.json 2 / 1 65

Exceptions, as the receipt lists them:

A: Rusternetes + OVN + youki (tunnr): what was enforced

Evidence receipt rusternetes-node sha256 e8db242c4d816f40, profile generator 0.4.3 (f093633c1166), kernel tunnr-kernel-k8s 6.12.104.

Container (command) Node Profile stated Seccomp mode / filters seen Snapshots
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - cp bench/iggy-bench.json 2 / 4 144
httpd -f -p 8000 -h /w cp bench/busybox.json 2 / 4 75
iperf3 -c 10.244.0.10 -t 10 -J cp bench/iperf3.json 2 / 4 4
iperf3 -c 10.244.0.11 -t 10 -J cp bench/iperf3.json 2 / 4 4
iperf3 -c 10.244.0.20 -t 10 -J cp bench/iperf3.json 2 / 4 4
iperf3 -c 10.244.1.10 -t 10 -J cp bench/iperf3.json 2 / 4 4
iperf3 -c 10.244.1.20 -t 10 -J cp bench/iperf3.json 2 / 4 7
iperf3 -s cp bench/iperf3.json 2 / 4 27
sh -c iperf3 -c 10.244.0.10 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 4 4
sh -c iperf3 -c 10.244.0.11 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 4 4
sh -c iperf3 -c 10.244.0.20 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 4 4
sh -c iperf3 -c 10.244.1.10 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 4 4
sh -c iperf3 -c 10.244.1.20 -t 10 -J; echo; echo CLIENT-DONE cp bench/iperf3.json 2 / 4 7
sh -c iperf3 -s cp bench/iperf3.json 2 / 4 27
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` cp bench/busybox.json 2 / 4
sleep 5 cp bench/busybox.json 2 / 4 71
/w/iggy-bench --message-size 1000 --messages-per-batch 100 - worker bench/iggy-bench.json 2 / 4 141
httpd -f -p 8080 -h /w worker bench/busybox.json 2 / 4 137
iggy-server --with-default-root-credentials worker bench/iggy-server.json 2 / 4 74
iperf3 -s worker bench/iperf3.json 2 / 4 27
sh -c iperf3 -s worker bench/iperf3.json 2 / 4 27
`sh -c while true; do echo T $(date +%s); grep -E 'MemTotal M` worker bench/busybox.json 2 / 4
sleep 3600 worker bench/busybox.json 2 / 4 28
sleep 5 worker bench/busybox.json 2 / 4 74

Exceptions, as the receipt lists them:

What the rows needed in Rusternetes (each fix test first)

Known open issue

ovn-kubernetes' pod-annotation PATCH sometimes never returns on Rusternetes. The logical port is then missing and that pod starts late or not at all. It showed once in this round, in row A's first learning run (one warm pod start of 120 s), and in none of the counted runs.

Workload (memory under load)