#!/usr/bin/env bash # knelperf-toolbox LXC — the on-demand perf analysis container for a PVE node. # STOPS to zero footprint; started only when a human/agent runs a workload. # lxc-toolbox.sh [--vmid N] {--create|--upgrade|--remove|--facts} # Why privileged + apparmor unconfined: bpftrace/perf need host kernel BPF, # tracefs and debugfs (pct skips virtual-fs bind sources, so the knelperf-toolbox # wrapper mounts tracefs/debugfs at runtime). Binds: /host/cgroup, /host/var/log # (ro, offline sar analysis), block devs for smart/nvme. Package list lives in # toolbox-pkgs.txt next to this script. # Docs: https://community.turnsys.com/t/328 set -euo pipefail [ "$(id -u)" = 0 ] || { echo "run as root" >&2; exit 1; } here=$(cd "$(dirname "$0")" && pwd) VMID=950 TPL=debian-12-standard_12.12-1_amd64.tar.zst case "${1:-}" in --vmid) VMID=$2; shift 2 ;; esac case "${1:-}" in --facts) pct config "$VMID" 2>/dev/null || echo "vmid $VMID not present" pct status "$VMID" 2>/dev/null || true exit 0 ;; --remove) pct shutdown "$VMID" --timeout 60 2>/dev/null || pct stop "$VMID" 2>/dev/null || true pct destroy "$VMID" --purge 1 rm -f /usr/local/sbin/knelperf-toolbox echo "toolbox $VMID removed" exit 0 ;; --create|--upgrade) action=$1 ;; *) sed -n 's/^# \?//p' "$0" | sed -n '2,5p'; exit 1 ;; esac if [ "$action" = --create ]; then if ! pct status "$VMID" >/dev/null 2>&1; then pveam list local 2>/dev/null | grep -q "$TPL" || pveam download local "$TPL" # block-device passthrough for smartctl/nvme (first 8 devices) dev_args=() for d in /dev/nvme[0-9]n1 /dev/sd[a-z]; do [ -b "$d" ] || continue [ "${#dev_args[@]}" -ge 16 ] && break dev_args+=("--dev$(( ${#dev_args[@]} / 2 ))" "$d") done pct create "$VMID" "local:vztmpl/$TPL" \ --hostname knelperf-toolbox \ --ostype debian \ --cores 2 --memory 2048 --swap 512 \ --rootfs local-lvm:8 \ --net0 name=eth0,bridge=vmbr0,ip=dhcp \ --unprivileged 0 --onboot 0 \ --mp3 /sys/fs/cgroup,mp=/host/cgroup \ --mp4 /var/log,mp=/host/var/log,ro=1 \ "${dev_args[@]}" fi # apparmor unconfined for host-kernel BPF/tracing access. PVE 9 dropped # `pct set --raw.lxc`; lxc.* keys go straight into the config file and # PVE::LXC honors an explicit profile over its generated one. if ! grep -q '^lxc.apparmor.profile:' /etc/pve/lxc/"$VMID".conf; then echo 'lxc.apparmor.profile: unconfined' >> /etc/pve/lxc/"$VMID".conf pct status "$VMID" 2>/dev/null | grep -q running && pct reboot "$VMID" fi fi # --create continues here; --upgrade rejoins an existing container was_running=1 pct status "$VMID" 2>/dev/null | grep -q running || { was_running=0; pct start "$VMID"; } i=0 until pct exec "$VMID" -- true 2>/dev/null; do i=$((i + 1)); [ $i -gt 60 ] && { echo "boot timeout" >&2; exit 1; } sleep 2 done pkgs=$(sed 's/#.*//' "$here/toolbox-pkgs.txt" | tr '\n' ' ') pct exec "$VMID" -- bash -c \ "DEBIAN_FRONTEND=noninteractive apt-get -qq update && DEBIAN_FRONTEND=noninteractive apt-get -qq -y install $pkgs" install -m 0755 "$here/knelperf-toolbox" /usr/local/sbin/knelperf-toolbox [ "$was_running" = 0 ] && pct shutdown "$VMID" --timeout 60 echo "toolbox $VMID $action done: knelperf-toolbox wrapper installed" pct status "$VMID"