Skip to content

Vipsharm gpu#676

Open
Medhakulam wants to merge 23 commits into
mainfrom
vipsharm-GPU
Open

Vipsharm gpu#676
Medhakulam wants to merge 23 commits into
mainfrom
vipsharm-GPU

Conversation

@Medhakulam

Copy link
Copy Markdown
Contributor

No description provided.

vipsharm and others added 23 commits July 9, 2026 17:15
…ped GPU Operator

Add scripts/install-nvidia-drivers.sh to bake the NVIDIA data-center driver and
its DKMS kernel modules into the Ubuntu base image, so GPU nodes can run the
NVIDIA GPU Operator with driver.enabled=false in fully air-gapped environments
(no host-side network, no operator driver container).

The script derives the target kernel from /lib/modules (not the builder's
uname -r), installs ABI-exact headers via install-kernel-headers.sh, forces DKMS
build/install/depmod against that kernel, and verifies nvidia*.ko landed in the
image kernel tree. It also blacklists nouveau, autoloads the nvidia stack,
enables nvidia-persistenced, and rebuilds the initrd.

Wire it into the base-image target (Ubuntu/amd64, after the kernel is finalized)
behind INSTALL_NVIDIA_GPU_DRIVERS, with tunable branch/type/repo/fabricmanager/
toolkit args. Document in .arg.template and docs/nvidia-gpu-airgapped.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…section

Explain that linux-headers/linux-image/linux-modules listed by NVIDIA belong to
the driver-container + local-apt-mirror strategy (driver.enabled=true), whereas
this integration uses the pre-installed-driver model (driver.enabled=false, no
mirror) and satisfies those three requirements at build time in the image.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… semantics

Clarify that the installer is version-agnostic (derives CUDA repo tag and kernel
codename from the image's os-release), so it works on both Ubuntu 22.04 and
24.04. Note that NVIDIA_DRIVER_BRANCH selects a driver branch (latest patch
within it), not an exact point release.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… Operator

Add scripts/install-amdgpu-drivers.sh, the AMD counterpart to the NVIDIA
installer. Bakes the amdgpu-dkms kernel driver into the Ubuntu base image so AMD
Instinct nodes can run the AMD GPU Operator with driver.enable=false in fully
air-gapped environments (no host-side network, no operator-built driver).

Reuses the same build-time approach: derive the image kernel from /lib/modules
(not the builder's uname -r), install ABI-exact headers via
install-kernel-headers.sh plus linux-modules-extra, register the AMD driver repo
via the version-matched amdgpu-install package (auto-discovered from
repo.radeon.com/amdgpu-install/<version>/), install amdgpu-dkms, force DKMS
build/install/depmod against the image kernel, and verify amdgpu.ko landed.
No nouveau-style blacklist is needed since amdgpu-dkms replaces the in-tree
amdgpu module.

Wire it into the base-image target behind INSTALL_AMD_GPU_DRIVERS with an
AMDGPU_ROCM_VERSION arg (default 7.2.4), alongside a build-time guard making the
NVIDIA and AMD pre-install paths mutually exclusive. Document in .arg.template,
docs/amd-gpu-airgapped.md, and cross-link from the NVIDIA doc.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e-installed

Add a "Building the air-gapped content" section to both the NVIDIA and AMD
guides. Clarify that pre-installing the driver only lets you drop the driver
image (NVIDIA) or the KMM/kaniko/ubuntu build images (AMD) -- the rest of the
operator still ships as container images that must be mirrored into the content
bundle.

Cover the easy-to-miss pieces: NVIDIA still needs container-toolkit (unless also
pre-installed on host) and the CUDA validation image, plus the k3s/rke2
containerd config env overrides for Palette Edge; AMD needs cert-manager
installed first, a DeviceConfig CR with driver.enable=false, and node labelling.
Recommend enumerating exact image tags via 'helm template' and note Palette
content-bundle additional-images handling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bump the default NVIDIA driver branch from 570 to 580 across the Earthfile ARG,
install-nvidia-drivers.sh, .arg.template, and docs. Refresh point-release
examples to 580.159.03. The 570 entries left in "e.g. 550, 570, 580" lists are
valid-branch examples, not defaults.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… hang

On modern NVIDIA data-center GPUs (Ada/Hopper/Blackwell — reproduced on
HPE ProLiant Compute DL380a Gen12 with a GH100-class GPU), a CanvOS image
built with INSTALL_NVIDIA_GPU_DRIVERS=true would hang forever at first
boot inside systemd-udev-settle. Console showed a kernel stack trace
ending at gh100_gsp_oneinit+0x2cf/0x440 [nouveau]: initramfs udev
auto-loaded nouveau before the rootfs modprobe.d blacklist could apply,
and nouveau's experimental GSP-RM path hung on the GPU. udev-settle
never returned; the node never came up; nvidia.ko never got to load.

Three changes, together sufficient to unbrick boot:

* Earthfile: when INSTALL_NVIDIA_GPU_DRIVERS is true, append
  rd.driver.blacklist=nouveau modprobe.blacklist=nouveau nouveau.modeset=0
  to /etc/cos/bootargs.cfg. This is the actual load-bearing fix:
  rd.driver.blacklist= is honored by dracut/initramfs *before* any udev
  event fires, so nouveau never binds. Mirrors the existing cgroup-v2
  append pattern immediately above.

* install-nvidia-drivers.sh: write /etc/dracut.conf.d/95-blacklist-nouveau.conf
  so BOTH the script's own dracut rebuild AND the later Earthfile-driven
  dracut rebuild (a) omit nouveau.ko from the initrd entirely and
  (b) carry the modprobe blacklist file into initramfs. Belt-and-braces
  in case the cmdline args are ever stripped downstream.

* install-nvidia-drivers.sh: drop nvidia_drm from /etc/modules-load.d/nvidia.conf.
  On headless GPU nodes it serves no purpose and loading it at early boot
  has a class of KMS/DRM-conflict failure modes. Loads on demand if
  anything actually needs it.

Follow-up: the UKI build path (--extend-cmdline in the build-uki targets)
also needs the same nouveau cmdline args when INSTALL_NVIDIA_GPU_DRIVERS
is true. Not addressed here since field failures were non-UKI grub boot;
worth adding in a subsequent commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…upport

Flip the default flavor of the pre-installed NVIDIA kernel modules from
"proprietary" to "open". The closed modules fail RmInitAdapter (0x22:0x56:897)
on Hopper (H100/H200) and Blackwell (RTX PRO 6000 Blackwell, B100/B200/GB200);
`nvidia-smi` on such a host reports "No devices were found" and the entire
GPU Operator stack downstream stays wedged (toolkit init loops, containerd
never registers the nvidia runtime, device plugin never advertises
nvidia.com/gpu, workload pods stay Pending on Insufficient nvidia.com/gpu).

The open modules also work fine on Turing, Ampere, and Ada, so the new
default is safe for every server-class NVIDIA GPU generation Turing and
newer -- essentially every card CanvOS is likely to target. Only Pascal /
Volta (V100/P100/P40) require the closed modules and now need an explicit
NVIDIA_DRIVER_TYPE=proprietary override.

Applied consistently across:
  * scripts/install-nvidia-drivers.sh -- runtime default + header comment
  * Earthfile -- ARG default
  * .arg.template -- user-facing hint
  * docs/nvidia-gpu-airgapped.md -- config table plus new "Choosing the
    module flavor" section with a hardware/flavor matrix and the RmInitAdapter
    symptom description for people googling the error.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The pre-install script silently shipped broken images when AMD's amdgpu-dkms
source did not build against the image kernel (observed on Ubuntu 24.04 HWE
6.17 with the previous 7.2.4 / 30.30.4 default, whose 6.16.13 source fails at
DKMS configure). The verify step accepted the in-tree amdgpu.ko.zst as
sufficient because it only searched anywhere under /lib/modules/$KVER/, and
apt-get failures were papered over. Nodes booted using the in-tree driver
instead of the DKMS one without any signal that this had happened.

Changes:
- Introduce AMDGPU_DRIVER_SOURCE={dkms,inbox}. dkms (default) DKMS-builds AMD's
  out-of-tree amdgpu; inbox skips the AMD apt repo entirely and only ensures
  the kernel's in-tree amdgpu autoloads. Any other value is a hard error.
- Rename AMDGPU_ROCM_VERSION -> AMDGPU_DRIVER_RELEASE (the URL segment is a
  driver-release marker, not a ROCm x.y.z). Bump default 7.2.4 -> 31.30
  (amdgpu-dkms 6.19.4, covers 22.04/24.04 kernels through 6.17).
- Fail hard in dkms mode: set -eo pipefail; remove '|| true' shims around
  dkms build/install; drop 'dpkg --configure -a --force-all' silent-fallback;
  verify amdgpu landed under $MODDIR/updates/dkms AND that dkms status shows
  ': installed' for the target kernel. Failure prints make.log tail and
  points at bumping AMDGPU_DRIVER_RELEASE or switching to inbox.
- Write /etc/canvos/amdgpu-driver-source on-node marker so ops can query
  which mode ran and, in dkms mode, the release + module/version + kernel.
- Docs: two-modes explainer up front, snapshot mapping table (2026-07-11)
  linking to AMD's canonical system-requirements page, "when the DKMS build
  fails" section documenting the bump-or-fallback flow.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…build container)

amdgpu-dkms >= 6.18 (observed on release 31.30 = amdgpu-dkms 6.19.4) invokes
mokutil from the DKMS sign_tool hook to enroll a Machine Owner Key. mokutil
reads /sys/firmware/efi/efivars, which is not exposed inside Docker/Earthly
RUN containers, so it aborts with:

    "EFI variables are not supported on this system /
     /sys/firmware/efi/efivars not found, aborting."

and the amdgpu-dkms postinst returns non-zero, failing the base-image build.

Drop /etc/dkms/framework.conf.d/canvos-no-mok-signing.conf with sign_tool=""
immediately before apt-get install amdgpu-dkms. DKMS honors this and skips
signing entirely, sidestepping the mokutil invocation. Modules are unsigned;
this path already documents that Secure Boot / UKI is unsupported.

The step-5 error message now lists this as the third common failure mode so
future regressions surface with a pointer at the drop-in.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…tor v1.5.0)

Empirical reproduction on the kairos-ubuntu:24.04-core-amd64-generic-v4.0.4
base image (kernel 6.17.0-35-generic) with the AMDGPU_ROCM_VERSION=7.2.4-era
script + Abhijit's masking reverted showed that amdgpu-dkms 6.16.13 builds
cleanly against Linux 6.17: DKMS reports the module `installed`, all 8 amd*.ko
files land under /lib/modules/<kver>/updates/dkms/, and apt-get returns 0.
The "EFI variables are not supported on this system / /sys/firmware/efi/efivars
not found, aborting" line printed during the 30.30.x postinst is a cosmetic
mokutil warning (sign_tool step); the postinst continues past it and finishes
normally. The signing config drop-in from ad4c6fa is still valuable as
defensive belt-and-suspenders for the 31.x line where the same message is
treated as fatal.

Given that, revert the previous 31.30 default (which crossed AMD's tech-
preview boundary) back to 7.2.1 -- the release AMD's GPU Operator v1.5.0
release notes explicitly pair the operator with. AMD publishes both ROCm-alias
and driver-release-marker URL segments at repo.radeon.com/amdgpu-install/, so
"7.2.1" is a valid AMDGPU_DRIVER_RELEASE (equivalent to "30.30.1").

Also refactor the docs' "Version alignment" section to lead with the
operator → ROCm → driver → kernel chain and explicitly label the 31.x line
as tech-preview.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…lure

Earthly's -i interactive debugger frequently hands out a broken tty in the
buildkit sandbox, making /var/lib/dkms/*/build/make.log unreachable when
amdgpu-dkms's postinst fails. Instead of asking users to debug interactively,
tail the make.log(s) and a few environment probes (kernel headers state,
Module.symvers presence, sign_tool drop-in state, MemAvailable) to stderr
before die-ing. The next non-interactive rebuild surfaces the underlying
compile error directly in the Earthly output.

No behavior change on the happy path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
amdgpu-dkms's ./configure runs a Kbuild probe to detect CFLAGS. In buildkit's
default unprivileged sandbox that probe fails with

    configure: error: cannot detect CFLAGS...
    grep: amd/dkms/config/config.h: No such file or directory
    make: *** No rule to make target 'amd/dkms/config/config.h'

Reproduced against a plain `docker run --privileged` baseline: same script,
same base image (kairos-ubuntu:24.04-core-amd64-generic-v4.0.4), same kernel
(6.17.0-35-generic), same AMDGPU_DRIVER_RELEASE=7.2.1 -- succeeds end-to-end
with modules landing under /lib/modules/<kver>/updates/dkms/. The only
observed difference is --privileged, so mark the AMD RUN step explicitly.

The wrapper (./earthly.sh) already passes --allow-privileged, and other RUN
steps in this repo use --privileged similarly, so no downstream change needed.
NVIDIA's driver install doesn't use the same ./configure sanity-check step
and continues to work unprivileged; its RUN block is left as-is.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
amdgpu-dkms's ./configure fails silently at "cannot detect CFLAGS..." when
Kbuild can't complete the `make -f -` heredoc probe it uses to extract
KBUILD_CFLAGS. build-essential covers gcc/make/libc but modern kernel
Makefiles unconditionally reach for bc, bison, flex, libelf-dev, libssl-dev,
and pahole (from dwarves). --no-install-recommends skips all of those.
Enumerate them explicitly to keep the image lean without breaking the AMD
DKMS build.

dwarves is AMD's own `Recommends:` on amdgpu-dkms -- it just wasn't pulled
because we use --no-install-recommends. cpio + xz-utils are added
defensively for the initramfs trigger that runs after DKMS install.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ild)

Compiles amdgpu-dkms against the kairos base image's kernel in a host-side
`docker run --privileged` container, then tars the produced kernel module +
firmware + config drop-ins into build/amdgpu-artifact-<release>-<kver>-<digest>.tar.gz.
The main Earthly build consumes that artifact via COPY, sidestepping the
buildkit RUN sandbox limitation that breaks AMD's ./configure heredoc probe.

Cache by (base-image digest x kernel version x AMDGPU_DRIVER_RELEASE); repeat
builds skip the ~8-10 min compile. Cache miss reproduces the same behavior we
already verified end-to-end via direct docker run on the jump host.

Prints "AMDGPU_ARTIFACT_PATH=<abs-path>" on the last stdout line so the
earthly.sh wrapper (next commit) can pick it up and thread it into Earthly.

Standalone; no other files touched by this commit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Before dispatching to earthly (build_with_proxy/build_without_proxy), detect
INSTALL_AMD_GPU_DRIVERS=true + AMDGPU_DRIVER_SOURCE=dkms from either .arg or
CLI overrides, derive BASE_IMAGE via the same tag formula the Earthfile uses,
and invoke scripts/prebuild-amdgpu-artifact.sh to compile the amdgpu module
on the host. The last line of prebuild output is parsed for the artifact
path; it's threaded to earthly as --AMDGPU_ARTIFACT_PATH=<abs>, which the
companion Earthfile change consumes via COPY + tar-extract.

Inbox mode skips this step entirely. Non-AMD builds skip this step entirely.
Existing CLI/.arg semantics for INSTALL_AMD_GPU_DRIVERS, AMDGPU_DRIVER_SOURCE,
AMDGPU_DRIVER_RELEASE, and BASE_IMAGE are preserved unchanged.

Ubuntu-only guard: prebuild refuses OS_DISTRIBUTION != ubuntu with a clear
error, mirroring the mutual-exclusion / Ubuntu-only checks already in the
Earthfile for the AMD block.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…+ docs

Complete the prebuild-artifact flow started in the previous two commits.

Earthfile:
  * new ARG AMDGPU_ARTIFACT_PATH (empty default)
  * base-image AMD block now branches on (AMDGPU_DRIVER_SOURCE, artifact):
      - dkms + artifact present  -> COPY tarball, extract, depmod, initrd
        (fast path used by ./earthly.sh + prebuild helper -- the release path)
      - inbox, or dkms without artifact -> unchanged legacy path (works under
        `docker run --privileged`; fails under buildkit's RUN sandbox at
        AMD's ./configure -- documented)

scripts/install-amdgpu-drivers.sh:
  * new AMDGPU_ARTIFACT_PATH fast path before the in-buildkit DKMS block:
    extract tarball, verify updates/dkms/amdgpu.ko*, depmod, rebuild initrd,
    write the on-node marker at /etc/canvos/amdgpu-driver-source. In-buildkit
    DKMS legacy path retained for direct `docker run` invocations and for
    scripts/prebuild-amdgpu-artifact.sh's own inner container.
  * docstring updated to describe the three execution paths.

docs/amd-gpu-airgapped.md:
  * new "two-stage build" explanation covering why the prebuild exists
    (buildkit RUN sandbox breaks AMD ./configure) and how it's wired up
    behind ./earthly.sh.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…d'd)

The prebuild's inner container bind-mounts the install scripts read-only
(-v ...:ro). chmod +x fails on RO mounts. Bash can execute scripts without
+x when invoked as `bash <path>`; no functional difference otherwise.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previous verify path deleted the tarball via STAGE_DIR trap before the user
could inspect it. Now:
  * mv to final path FIRST (before verify), so any failure leaves the file
    behind for inspection
  * on verify failure, dump the first 40 tar entries to stderr so we can
    see what path structure actually landed in the archive
  * grep pattern loosened to `updates/dkms/.*amdgpu\.ko` (regex) in case
    tar mangled paths in an unexpected way

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ld context)

Earthly's COPY expects paths relative to the Earthfile's directory (the
repo root), not absolute host paths. The prebuild helper emits an absolute
path for its own file-existence checks; the wrapper now converts that to
a repo-relative path before threading it into Earthly as
--AMDGPU_ARTIFACT_PATH=build/amdgpu-artifact-...tar.gz.

Fails fast with a clear message if the artifact somehow lands outside the
repo tree.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`build/*` in .earthlyignore was hiding the pre-built AMD driver tarball
from Earthly's build context, so COPY build/amdgpu-artifact-...tar.gz
failed with "no such file or directory" even though the artifact existed
on the host.

Add a negation pattern for build/amdgpu-artifact-*.tar.gz so this specific
artifact is visible while everything else under build/ (Earthly SAVE
ARTIFACT outputs, etc.) stays ignored.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ueue

Reported: node with baked-in DKMS amdgpu (8x MI325X) fails to boot -- drops
into dracut-emergency after `dracut-initqueue: Timed out for waiting the udev
queue being empty`. Screenshots show amdgpu still emitting per-XCP-partition
and per-ring init messages long after boot has given up.

Root cause: rebuilding the initrd (default true) pulled the DKMS amdgpu
modules under /lib/modules/<kver>/updates/dkms/ into the initrd. amdgpu then
loads *before* switch-root, and the sheer volume of udev events it emits on
multi-GPU MI silicon (8 GPUs x 8 XCP partitions + JPEG rings + SMU/PSP/KFD
handshakes) keeps systemd-udev-settle from ever seeing an empty queue.
initqueue times out (~5 min), boot fails, node reboots, loops.

amdgpu is not required to mount rootfs -- NVMe/SATA use their own drivers.
Load it *after* switch-root via /etc/modules-load.d/amdgpu.conf (which the
script was already writing), where there is no timeout pressure. This
matches kairos-a176's observed behavior with the in-tree driver.

Two guards:
  1. Flip default AMDGPU_REBUILD_INITRD to `false` (was `true`) in
     Earthfile, .arg.template, and install script.
  2. Even when someone sets AMDGPU_REBUILD_INITRD=true, drop
     /etc/dracut.conf.d/98-canvos-amdgpu-omit.conf with
     `omit_drivers+=" amdgpu amdttm amdkcl amd-sched amddrm_ttm_helper
     amddrm_buddy amddrm_exec amdxcp "` so dracut still leaves amdgpu out.

Applied consistently across all three code paths in install-amdgpu-drivers.sh
(artifact fast path, inbox mode, in-buildkit DKMS fallback).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants