AIL-262: feat(edge): collect launchpad-ai + GPU + storage state for AI-appliance triage#37
Open
rishi-anand wants to merge 5 commits into
Open
AIL-262: feat(edge): collect launchpad-ai + GPU + storage state for AI-appliance triage#37rishi-anand wants to merge 5 commits into
rishi-anand wants to merge 5 commits into
Conversation
Extend the edge support bundle to capture the state needed to
troubleshoot Palette AI-inference appliances (launchpad-ai on
MI325X / H200 / B200), where the standard k8s/system collection
alone is insufficient for root-cause on GPU-side failures.
Three changes:
1. SYSTEM_NAMESPACES: add launchpad-ai, amd-gpu-operator, gpu-operator
so their pods, previous-instance logs, and CRs (models,
launchpadconfigs, modelgroupquotas, modelgroupapikeys,
quotasettings) are pulled by the existing generic namespace +
CRD walks. No changes to API_RESOURCES needed — the launchpad.
spectrocloud.com CRDs are already picked up automatically.
2. journald-log: also grab the PREVIOUS boot's kernel log
(dmesg-previous-boot, journalctl-previous-boot) when journald
has persistent storage. Post-crash forensics on GPU wedges that
force a host reboot depend on this — the current-boot dmesg is
post-recovery and useless.
3. gpu-info: new function that emits gpu/ with vendor-specific state
* AMD (amdgpu present): module version + parameters, per-card
VBIOS, per-card firmware components (sdma_fw, sos_fw, smc,
xgmi_ta, mec, rlc, etc.), RAS/ECC counters, hwmon
(temp/power/fan), rocm-smi -a and detailed views (from host or
via kubectl exec into an operator/vLLM pod), and any AMD GPU
devcoredumps preserved to /var/log/amdgpu-devcoredump/ by the
OS profile udev rule.
* NVIDIA (nvidia driver present): driver version, nvidia-smi -q +
topo -m + summary CSV, nvidia-bug-report.sh if installed, and
any NVIDIA devcoredumps from /var/log/nvidia-devcoredump/.
* launchpad-ai: directory shape of /opt/data/spectrocloud/models/
(never copies weights — hundreds of GB), plus every model's
metadata.yaml (~20 KB each; declares the launch recipe).
Companion to the OS-profile PRs (launchpad-ai#512 for AMD, #530 for
NVIDIA) that install the udev rules producing the devcoredump files
this collector reads.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add a storage-info() step that captures block devices, filesystems, LVM, NVMe inventory + SMART health. Every tool is gated on its own binary presence, so this is a no-op on hosts that don't have LVM / nvme-cli / smartmontools installed. Palette edge hosts run on LVM (spectro-data-vg / spectro-data-lv with persistent partition at /opt). AI appliances additionally park model weights under /opt/data/spectrocloud/models/. LVM or NVMe health issues are a common load-bearing failure mode that the previous bundle collected zero data for. Collected commands (all optional-per-tool): - lsblk -f, lsblk with FSTYPE/UUID/MODEL/SERIAL/TRAN/ROTA/STATE - df -h, df -i, /proc/mounts, /etc/fstab - fdisk -l - pvdisplay, vgdisplay, lvdisplay, pvs, vgs, lvs - nvme list, nvme id-ctrl, nvme smart-log per drive - smartctl -a per block device Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ystem Mirrors the read-only sysfs paths that stylus/pkg/disk uses for disk enumeration (dm UUIDs for LVM/dm-crypt/multipath detection, rotational flag for SSD vs HDD, hidden/removable/ro flags). Also captures the /dev/disk/by-* symlink tree (covers by-uuid, by-partuuid, by-label, by-partlabel, by-path, by-id) and device-mapper topology via dmsetup. Every command added here is READ-ONLY: - cat of sysfs attributes (size, rotational, dm/uuid, dm/name, etc.) - ls -laR /dev/disk (symlink listing only) - dmsetup ls --tree, dmsetup info (query-only subcommands) - ls -laR /sys/class/nvme-subsystem No state-modifying subcommands anywhere in this file (verified: no smartctl -t, no rocm-smi --set*, no nvme format, no dmsetup remove, no fdisk without -l). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Every added command is now either (a) gated on tool presence via 'command -v <tool>' / '[ -d /sys/... ]' / '[ -b /dev/... ]', or (b) wrapped in 'timeout N' so a wedged controller / unresponsive pod can't block the entire bundle run. Specific hardening: - nvme list / id-ctrl / smart-log: 10-15s timeouts per drive - smartctl -a: 20s timeout per drive (failing drives can spin) - kubectl exec (rocm-smi / nvidia-smi fallback path): 30s timeout per exec, 10s on pod listing / 'which' probe - nvidia-smi (direct): 10-20s per query - nvidia-bug-report.sh: hard 180s cap (60s typical; hangs on wedged nodes) - Merged the two AMD kubectl fallback loops (amd-gpu-operator + launchpad-ai) into one with 'break 2' for clarity Read-only guarantee: no state-modifying subcommands present in this file. Verified via grep for --set/--reset/-t (smartctl test)/ format/create/remove/mkpart. All GPU/storage tools are called with query/show/list/display/id-ctrl/smart-log flags only. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
On Palette NVIDIA appliances the driver + userspace tools live inside
the GPU Operator's driver DaemonSet container, not on the host (Kairos
is minimal by design). So 'command -v nvidia-bug-report.sh' on the
host misses the majority case. Mirror the rocm-smi fallback pattern:
1. Try host binary first (works for BYO-driver / driver-in-image
deployments)
2. If not found or failed, exec inside any Running pod in
gpu-operator or launchpad-ai that has the tool
3. Stream the .gz output back over stdout (no kubectl cp, no in-pod
cleanup needed)
4. Sanity-check the received file is non-empty before declaring
capture success
5. If nothing worked, write a status file explaining why
Read-only from the system's perspective; the tool only writes to its
declared output path. 180s hard cap kept — nvidia-bug-report.sh can
hang on wedged GPUs.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira: AIL-262
Summary
Extends
support-bundle-edge.shto capture the host + cluster state needed to root-cause failures on Palette AI-inference appliances (launchpad-ai on MI325X / H200 / B200), and to close storage/LVM/NVMe gaps that affect any edge host. Every command added is read-only and fails gracefully if its dependency isn't installed or its target isn't present.What's added
1. AI namespaces to
SYSTEM_NAMESPACESlaunchpad-ai,amd-gpu-operator,gpu-operator. Their pods, previous-instance logs, and CRs get pulled by the existing generic namespace + CRD walks. Alllaunchpad.spectrocloud.comCRDs (models,launchpadconfigs,modelgroupquotas,modelgroupapikeys,quotasettings) are covered automatically.2. Previous boot's kernel log
journald-log()now also collectsdmesg-previous-bootandjournalctl-previous-bootwhen persistent journald is enabled. Critical for post-crash forensics — GPU wedges typically freeze host networking and force a reboot, so the current-boot dmesg after such a reboot is post-recovery and useless.3. New
storage-info()— always safe to runRead-only host storage collection, every tool gated on
command -v,timeout-wrapped where a wedged controller could hang:lsblk -f,lsblk -o …(fs/UUID/model/serial/rotational)df -h,df -i,/proc/mounts,/etc/fstabfdisk -lpvdisplay,vgdisplay,lvdisplay,pvs,vgs,lvsnvme list,nvme id-ctrl,nvme smart-logper drive (10-15s each)smartctl -aper block device (20s each; no-t— never triggers tests)size,hidden,rotational,dm/uuid,dm/name,device/{model,vendor,serial}) — mirrors whatstylus/pkg/diskreads for enumeration/dev/disk/by-*full symlink tree (coversby-uuid,by-partuuid,by-label,by-partlabel,by-path,by-id)dmsetup ls --tree,dmsetup info— device-mapper topology for LVM / multipath / dm-crypt/sys/class/nvme-subsystem/— native-NVMe-multipath subsystem tree4. New
gpu-info()— hardware-vendor gatedEmits
gpu/directory. AMD block gated on[ -d /sys/module/amdgpu ]; NVIDIA block gated on[ -e /proc/driver/nvidia ] || command -v nvidia-smi. Emits an emptygpu/dir on non-GPU hosts.AMD (when amdgpu present):
modinfo+/sys/module/amdgpu/parameters/*(lockup_timeout, reset_method, gpu_recovery)/sys/bus/pci/devices/*/vbios_versionsdma_fw_version,sos_fw_version,smc_fw_version,ta_xgmi_fw_version,mec_fw_version,rlc_fw_version, …)/sys/bus/pci/devices/*/ras/*hwmonrocm-smi -aandrocm-smi --show{hw,driverversion,vbios,temp,use,power,fw,bios}— from host if installed, else viakubectl execinto an operator/vLLM pod (timeout-guarded)/var/log/amdgpu-devcoredump/*.bin(populated by AIL-263 / launchpad-ai#512)/sys/class/devcoredump/listing (no reads ofdata— reads would consume)NVIDIA (when nvidia driver present):
/proc/driver/nvidia/versionnvidia-smi -q,nvidia-smi topo -m, compact query CSV (pstate/temp/util/memory/ECC-corrected/ECC-uncorrected)nvidia-bug-report.shif installed (comprehensive vendor dump; 180s hard cap)/var/log/nvidia-devcoredump/*.bin(populated by AIL-264 / launchpad-ai#530)launchpad-ai on-disk (both vendors):
/opt/data/spectrocloud/models/— weights are hundreds of GB, never copied into the bundlemetadata.yaml(~20 KB each; declares the launch recipe)Read-only + graceful-fail guarantee
Read-only. Verified by grepping for
--set,--reset,smartctl -t,nvme format,dmsetup remove/create/load,pvcreate/pvremove,vgcreate/vgremove,lvcreate/lvremove/lvresize,parted mkpart. Zero matches. Every GPU/storage tool uses only--show*/--query*/-l/list/display/info/id-ctrl/smart-logflags.Graceful-fail.
command -v— silent skip if not installed/sys/module/amdgpu,/proc/driver/nvidia) — no-op on non-GPU nodestimeout N: nvme (10-15s), smartctl (20s), kubectl exec (10-30s), nvidia-bug-report.sh (180s hard cap)set -e(verified — existing pattern), so individual command failures don't abort the bundletimeoutwrappers in the new code; 61 gated conditionals totalMotivation
Grounded in the July 2026 MI325X incident (see AIL-262) where two vLLM crashes each wedged the host. We had to log in mid-triage and hand-run every one of these commands. This PR turns the ad-hoc triage checklist into a first-class collector so support engineers don't repeat it.
Companion PRs that install the udev rules this collector reads:
Diff size
Test plan
137.220.60.220): confirmgpu/amd/gets rocm-smi + per-card firmware/VBIOS + RAS state;storage/gets pvdisplay + lsblk + nvme SMART.gpu/nvidia/gets nvidia-smi + optional nvidia-bug-report.gpu/is empty and everything else is unaffected. ← critical graceful-fail teststorage/still gets the sysfs + lsblk output and skips the missing tools without erroring. ← critical graceful-fail testbash -n support-bundle-edge.sh— passes ✅🤖 Generated with Claude Code