Repository navigation
fix(gcp): install Docker on the VM at boot and fail apply fast on a failed startup script - #363
Merged
Merged
Conversation
…ailed startup script The Deep Learning VM image ships the NVIDIA driver but not Docker or the NVIDIA container toolkit, so the startup script exited at boot and apply waited for /health until its deadline. The script now installs Docker Engine and nvidia-container-toolkit from their official apt repositories when missing (each key checked against a pinned fingerprint), configures the NVIDIA runtime, and waits for vLLM on the VM. It reports ready or failed:<step> with its log tail as guest attributes, which the readiness wait reads to stop at once.
… report each boot The startup script finishes an install cut short by a reboot or preemption (dpkg --configure -a) and skips it only when a marker, a running Docker and the nvidia runtime say it is done. trust() imports the downloaded key into a scratch keyring and exports only the pinned fingerprint for apt. apt-get update errors from unrelated repositories are tolerated as long as the needed packages have a candidate. Each boot writes amicu/status=booting and its boot_id first, and the on-VM health wait fails only on a stopped or crash-looping container, leaving slow loads to apply's deadline.
…drop the dead serial hint apply now prints the certificate's public key pin and snippets that verify it: curl -k --pinnedpubkey sha256//<pin>, and Python trusting only the VM's certificate through an ssl context passed to httpx. A Spot VM deleted by preemption during the wait is reported as preempted (from the zone's compute.instances.preempted operations, matched by instance id), with the advice to re-run apply or use standard provisioning. The startup failure error no longer suggests reading the serial console of a VM apply then deletes; that command is printed only when the delete failed and the VM may still be billing.
…e real apt error Under set -o pipefail, apt-cache policy piped into grep -q failed with SIGPIPE whenever grep matched early, so every package looked missing and the install aborted with 'apt cannot find docker-ce ...'. Candidates are now read with sed, the fingerprint awk no longer exits early, and the nvidia runtime check reads all of docker info. apt-get update writes to its own log; when a package has no candidate, its E:/Err: lines and the lines for download.docker.com and nvidia.github.io go to the startup log instead of the image's legacy-keyring warnings.
…teral The Python snippet already writes the path through a JSON string literal, which Python reads the same way, so backslashes in a Windows path are escaped. The end-to-end test compared against the raw path and failed on Windows; it now builds the expectation the same way, and a unit test checks a Windows path with quotes.
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.
Builds on #362, which is now merged; main is merged into this branch.
Problem
A live T4 Spot test (n1-standard-4, europe-west4-b) on the default image family
common-cu129-ubuntu-2204-nvidia-580failed at boot withamicu: docker is not installedandScript "startup-script" failed with error: exit status 1. The Deep Learning VM image has the NVIDIA 580 driver but not Docker or the NVIDIA container toolkit.amicu applydid not notice. It kept polling/healthfor 20+ minutes after the script had exited.Approach: install at boot on the Deep Learning VM image
We keep the Deep Learning VM image and install the missing tools from the startup script. Reasons:
python3,curlandgpg, which the Secret Manager fetch and the key check use.cos-extensions, mounting the GPU devices and libraries by hand instead of--gpus all, a read-only/opt, nopython3, and a rewrite of the script.What the script does now:
install Docker and the NVIDIA container toolkit). It adds Docker's apt repository (docker-ce docker-ce-cli containerd.io) and NVIDIA's libnvidia-container repository (nvidia-container-toolkit) for whichever tool is missing./var/lib/amicu/tools-ready(written after the restart) exists,systemctl is-active dockersucceeds, anddocker infolists thenvidiaruntime. Otherwise it first runsdpkg --configure -a, retried for 10 minutes while the lock is held, so an install cut short by a reboot or preemption is finished.trust()downloads each key withcurl --retry 5 --retry-connrefusedand imports it into a scratchGNUPGHOME. It then exports only the pinned fingerprint to/etc/apt/keyrings/<name>.gpg, so apt trusts exactly the checked key:9DC858229FC7DD38854AE2D88D81803C0EBFCD88C95B321B61E88C1809C4F759DDCAE044F796ECB0apt-get updateerrors from unrelated repositories on the image are tolerated. What must hold is thatapt-cache policyshows a candidate for every needed package (3 tries). apt waits up to 10 minutes for the dpkg lock, because unattended-upgrades holds it on first boot.nvidia-ctk runtime configure --runtime=dockerandsystemctl restart docker. The step checks that Docker lists thenvidiaruntime before writing the marker./health. It fails only if the container stops or restarts 3 times, and printsdocker logs --tail 50. A slow model load is left to apply's own deadline, and the script has no deadline of its own.dpkg --print-architecture, NVIDIA's$(ARCH)repository). A4X is still refused, butA4X_UNSUPPORTED, the placement error and the docs no longer say its images lack Docker. They now say amicu is untested on the Grace image and the arm64 vLLM container.Fail fast
enable-guest-attributes=TRUEin instance metadata. At the start of every boot it writesamicu/status=bootingandamicu/boot_id, so areadyfrom an earlier boot does not survive a restart. AnEXITtrap writesamicu/detail, the last 4 KB of the script's own log, and thenamicu/status=failed:<step>. On success it writesamicu/status=ready./healthfails,wait_readyreadsgetGuestAttributes?queryPath=amicu/, at most every 15 s. Compute Engine allows 10 queries per minute per VM.failed:<step>it returnsGcpError::StartupFailed, with the step and the last 25 log lines.gcloud compute instances get-serial-port-output <vm> --zone <zone> --project <project>command is printed only when that delete failed. That note also says the VM may still be running and billing in its zone, and thatamicu destroy --target <dep>retries./healthdeadline. If the VM reportsreadybut the probe never gets through, the timeout names the firewall andallowed_source_cidrs.compute.instances.preemptedoperations are checked, matched by the instance id seen while it ran. The error then says it was preempted and suggests re-runningamicu applyorprovisioning = "standard", instead of "deleted".Client snippets for a VM
Plain
curlfails on the pinned self-signed certificate, and--cacertalso fails (exit 60) because the certificate names no host. apply now prints:curl -k --pinnedpubkey 'sha256//<pin>' ....-kskips only the CA and host name checks, and the pin still refuses any other key.ssl.create_default_context(cafile=<cert>)withcheck_hostname = False, passed ashttpx.Client(verify=tls)toOpenAI(http_client=...). This still verifies the chain against that one certificate.Checked locally against
openssl s_serverwith an amicu-generated certificate:Boot time
The live T4 Spot run on the first commit took 8m53s from apply to ready.
Tests
startup.rs(content checks on the generated script):nvidiaruntime) anddpkg --configure -abefore the installkeyrings/*.gpg, and--retry-connrefusedapt-get updatewith the candidate checkbootingandboot_idwritten before the first step/healthwait with no fixed limitbash -non every varianthealth.rs:tls.rs: the public key pin equals the hash of the key's SubjectPublicKeyInfo.amicu-cli:~/.claude/amicu-cargo.sh +stable clippy --workspace --all-targets -- -D warnings: clean~/.claude/amicu-cargo.sh test -p amicu-gcp -p amicu-cli: amicu-gcp 174 passed; amicu-cli 517 passed, 1 ignoredcargo fmt --check: clean