#!/usr/bin/env bash # # k8s/proxmox-tuning.sh — apply ultix-style Proxmox tuning to k8s VMs # # Codifies the config applied 2026-09-01 during the #367 rebuild: # - disk: ssd=1,discard=on (guest sees non-rotational; qcow2 trims) # - net: queues=2 on both NICs (multiqueue; guest activates via ethtool) # - cpu: cpuunits so etcd/control plane wins host CPU contention # - boot: onboot=1 + startup order (cnodes before wnodes) # - balloon was already 0 on every k8s VM (etcd memory predictability) # # Pending items (ssd/discard, queues) activate at the VM's next restart. # Reboot waves are SERIAL with a health gate between hops — never batch. # # DRY RUN by default. Apply with RUN=1. Run on each Proxmox host, or via # PROX_HOST= bash tests/remote.sh prox 'bash -s' < k8s/proxmox-tuning.sh # set -uo pipefail RUN="${RUN:-0}" # vmid|cpuunits|startup|scsi0-line|net0-line|net1-line # scsi0/net lines are the FULL desired config (Proxmox replaces wholesale). TUNINGS=( "102|4000|order=20,up=180|S2:102/vm-102-disk-0.qcow2,cache=writeback,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:CB:97:10,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:47:13:08,bridge=datanet,queues=2" "705|4000|order=20,up=180|S1:705/vm-705-disk-0.qcow2,cache=writeback,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:40:25:F8,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:AF:3D:89,bridge=datanet,queues=2" "603|4000|order=20,up=180|D1:603/vm-603-disk-0.qcow2,cache=writeback,format=qcow2,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:38:C0:58,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:1F:F1:E1,bridge=storagenet,queues=2" "313|2000|order=40,up=120|local-lvm:vm-313-disk-0,iothread=1,ssd=1,discard=on,size=300G|virtio=BC:24:11:EE:7E:7B,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:DF:C2:E9,bridge=datanet,queues=2" "601|2000|order=40,up=120|local-lvm:vm-601-disk-0,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:FA:6E:B5,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:39:7D:0B,bridge=storagenet,queues=2" "701|2000|order=40,up=120|S2:701/vm-701-disk-0.qcow2,cache=writeback,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:30:B8:07,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:C8:0E:8A,bridge=datanet,queues=2" "905|2000|order=40,up=120|S2:905/vm-905-disk-0.qcow2,cache=writeback,iothread=1,ssd=1,discard=on,size=32G|virtio=BC:24:11:EE:2B:B6,bridge=vmbr0,firewall=1,queues=2|virtio=BC:24:11:9B:57:06,bridge=datanet,queues=2" ) apply() { local vmid="$1" cpuunits="$2" startup="$3" scsi0="$4" net0="$5" net1="$6" if [ "$RUN" = "1" ]; then qm set "$vmid" --cpuunits "$cpuunits" --startup "$startup" \ --scsi0 "$scsi0" --net0 "$net0" --net1 "$net1" else echo "DRY: qm set $vmid --cpuunits $cpuunits --startup $startup --scsi0 $scsi0 --net0 $net0 --net1 $net1" fi } for t in "${TUNINGS[@]}"; do IFS='|' read -r vmid cpuunits startup scsi0 net0 net1 <<< "$t" # Skip VMs that live on other hosts (qm set errors on unknown VMID) if ! qm status "$vmid" >/dev/null 2>&1; then echo "skip: VM $vmid not on this host" continue fi echo "== VM $vmid ==" apply "$vmid" "$cpuunits" "$startup" "$scsi0" "$net0" "$net1" done echo if [ "$RUN" = "1" ]; then for t in "${TUNINGS[@]}"; do vmid="${t%%|*}" qm status "$vmid" >/dev/null 2>&1 || continue echo "--- pending VM $vmid ---" qm pending "$vmid" | grep -E "^(new|cur) (scsi0|net0|net1|cpuunits|startup)" || true done fi