Skip to content

[CI]: Reclaim agent disk in premerge pipeline to fix ENOSPC - #264

Closed
wuhang2014 wants to merge 2 commits into
vllm-project:mainfrom
wuhang2014:ci/premerge-disk-hygiene
Closed

wuhang2014 wants to merge 2 commits into
vllm-project:mainfrom
wuhang2014:ci/premerge-disk-hygiene

Conversation

@wuhang2014

Copy link
Copy Markdown
Collaborator

Purpose

Premerge builds on the shared agents have started failing with No space left on device (e.g. build 799). The pipeline leaks disk on every build:

  • Build Docker Image runs a multi-stage docker build whose RUN cargo build --release layer is multi-GB, tags it vllm-router:<commit>, and never pushes or deletes it. Nothing consumes the local tags downstream (release images are built and pushed by release-pipeline.yml), so each build permanently strands multi-GB of tagged images + build cache on cpu_queue_premerge agents. After ~800 builds the disks fill up.
  • Cargo jobs (clippy, build, tests, wheel, python tests) each leave multi-GB target/ dirs in the host-mounted checkout (.:/workdir). Intermediates are never reused across jobs (separate checkouts).
  • The P/D GPU e2e job leaves a ~20GB .venv (vllm + torch cu130) plus target/ in the /workdir checkout on gpu_4_queue, even when the job fails.

For reference, vllm-project/vllm CI avoids this class of problem by building images with buildx/bake into a registry with ECR layer cache, scheduling registry cleanup (cleanup-nightly-builds.sh), and running on ephemeral agents — none of which the router pipeline can assume from within the repo, so this PR makes the pipeline self-cleaning instead.

Changes (all in .buildkite/pipeline.yml)

  • Docker Build: prune stale vllm-router:* tags (except latest), dangling layers, and builder cache (--keep-storage 10GB) before building — this also reclaims disk on agents that are already full; after building, smoke-test the image with vllm-router --version inside docker run and docker rmi it. Local tags are unused downstream.
  • Cargo jobs (clippy, unit/integration tests, wheel build, python tests): rm -rf target after the job.
  • Build Rust (Release): keep only target/release/vllm-router for the artifact upload; delete deps/build/.fingerprint intermediates.
  • P/D GPU job: pre-clean .venv/target at start and trap ... EXIT so ~25GB is freed even when the job fails.

Test Plan

  • python3 YAML parse of .buildkite/pipeline.yml — OK
  • bash -n syntax check of every modified command block — OK
  • pre-commit hooks (incl. check-yaml) — pass

Test Result

Pipeline-level change only; behavior verified by YAML/bash syntax checks and the pre-commit hook. Effect will be observable on the next premerge runs: the Docker Build step now logs df -h / before/after pruning.

Shared cpu_queue_premerge agents ran out of disk (e.g. build 799):
the Docker Build step stranded a multi-GB vllm-router:<commit> image
plus build cache on every build, cargo jobs left multi-GB target/
dirs in the mounted checkout, and the P/D GPU job left a ~20GB .venv
(vllm + torch cu130) and target/ in its checkout.

- Docker Build: prune stale vllm-router:* tags, dangling layers and
  builder cache before building; smoke-test the image and rmi it after
  (local tags are unused downstream; release images are pushed by
  release-pipeline.yml)
- cargo jobs (clippy, tests, wheel, python): rm -rf target afterwards
- Build Rust: keep only the release binary for the artifact upload
- P/D GPU job: pre-clean and trap-rm .venv and target/ so failures
  still free ~25GB

Signed-off-by: WU Hang <whlbx@hotmail.com>
Copilot AI lite review requested due to automatic review settings September 9, 2026 14:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 44c77cf37b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread .buildkite/pipeline.yml
cargo clippy --all-targets --all-features -- -D warnings
# Free agent disk: target/ holds multi-GB of build artifacts
# that are never reused across jobs (separate checkouts).
rm -rf target || true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve command failures while removing target

These Docker plugin commands explicitly invoke bash -c without -e, so if Clippy fails, execution continues and this successful rm -rf ... || true becomes the shell's exit status, making the check pass. The same failure masking occurs in the newly appended cleanup commands for the release build, wheel build, unit tests, integration tests, and Python tests; use an EXIT trap that preserves the original status (or otherwise capture and return it) so cleanup cannot turn failed CI checks green.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new Docker cleanup command uses {{...}} in docker images --format, which can be consumed by Buildkite templating and break the cleanup, undermining the ENOSPC fix.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Updates the Buildkite premerge pipeline to proactively reclaim disk space on long-lived shared agents (CPU and GPU queues), addressing ENOSPC failures caused by accumulated Docker images/build cache and Rust/Python build artifacts.

Changes:

  • Add target/ cleanup after cargo-based CI steps and prune intermediate release artifacts while keeping the uploaded binary.
  • Add GPU e2e workspace hygiene (.venv/target pre-clean + trap ... EXIT) to reclaim space even on failures.
  • Add Docker daemon hygiene (prune stale vllm-router images/cache pre-build, smoke-test the built image, then remove it).
File summaries
File Description
.buildkite/pipeline.yml Adds per-step cleanup of Cargo artifacts, GPU venv cleanup with traps, and Docker image/cache pruning + post-build image removal to prevent disk exhaustion.
Review details

Suppressed comments (1)

.buildkite/pipeline.yml:486

  • If the smoke test (docker run ... --version) fails, the script may exit before reaching the docker rmi ... line, leaving the per-commit image on disk (the exact leak this PR is addressing). Add an EXIT trap before the smoke test so cleanup runs even on failure.
      # Smoke test the image, then drop it: keeping one multi-GB image per
      # commit fills the agent disk.
      docker run --rm --entrypoint /bin/sh vllm-router:latest -c 'vllm-router --version'
      docker rmi vllm-router:${BUILDKITE_COMMIT} vllm-router:latest || true
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .buildkite/pipeline.yml Outdated
Comment on lines +473 to +475
docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' \
| awk '$1 ~ /^vllm-router:/ && $1 != "vllm-router:latest" {print $2}' \
| xargs -r docker rmi -f || true
The pipeline uploader's env interpolation (buildkite-agent 3.73.1)
rejects dollar-identifiers that start with a digit, so the awk
positional args in the pre-build docker cleanup aborted pipeline
upload entirely (build 801: 'Expected identifier to start with a
letter, got 1'). It scans the whole command string, comments
included.

Replace the awk/--format pipeline with 'docker images -q vllm-router
| xargs -r docker rmi -f': all vllm-router images can go since
latest is re-tagged in the same step anyway. Verified with
buildkite-agent 3.73.1 locally.

Signed-off-by: WU Hang <whlbx@hotmail.com>

@hsliuustc0106 hsliuustc0106 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Cleanup turns failed CI checks green (.buildkite/pipeline.yml:58; also lines 98, 124, 158, 179, and 205).

The six affected Docker plugin steps explicitly use bash -c without -e. Appending rm -rf ... || true replaces the build/test exit status with success, so failed Clippy checks, Rust builds, wheel builds, Rust unit/integration tests, and Python tests can pass CI. Please use an EXIT trap that preserves the original status, or explicitly capture and return the build/test status after cleanup.

I verified this against base 0519da5 and PR head 0a19209 using the actual command blocks with stubbed build/test commands returning 42: all six base scripts returned 42, while all six PR scripts returned 0. This confirms the existing inline finding remains unresolved at the current head.

Validation: YAML parsing and bash syntax checks passed for all nine plugin scripts. Full Docker/GPU CI was not run.

@wuhang2014 wuhang2014 closed this Sep 9, 2026
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.

3 participants