Repository navigation
kind: build the seed early and run the console step in parallel - #1020
Merged
Merged
Conversation
|
Thanks for opening this pull request! A SPACE maintainer will take a look. CONTRIBUTING.md explains how we review outside contributions. |
ac-pplx
marked this pull request as ready for review
October 29, 2026 10:55
This was referenced Oct 31, 2026
zibi-pplx
previously approved these changes
Nov 1, 2026
zibi-pplx
left a comment
Collaborator
There was a problem hiding this comment.
The scheduling change looks right. It needs a rebase, and some of its evidence predates two merges.
- [low] The rebase onto #1017 and #1168 should refresh the claims and timings
Tiltfile(seed-publishcustom_build,space-internal-apideps);scripts/tests/lib/bootstrap-kind-stack.sh
The PR conflicts with main. The merge-order note covers #1017, but #1168 also changed theTiltfile,bootstrap-kind-stack.sh,wait-node-publication.shandtest-kind-stale-tilt-recovery.sh. After #1168, the description's statement that "the only password logins during a bring-up are the node-publication wait … and the smokes" no longer holds. On the Direct lane,register-direct-nodessigns in asroot@local. It stays safe because that resource listsprovision-local-consolein its ownresource_deps(Tiltfile:929on main). Dropping the console step fromspace-internal-api's deps therefore doesn't affect it. The bring-up timings and "the 4 Kind smoke shards" were measured before #1017 changed image loading and before CI moved to six shards.
Suggestion: after the rebase, keepregister-direct-nodes' explicit dependency and update that sentence. Then re-runkind-bringup-timeline.pyon both substrates so the before/after table reflects current main.
zibi-pplx
dismissed
their stale review
November 1, 2026 22:29
Withdrawing this approval for now. Any feedback above still stands.
The seed-publish image build is a custom_build, which Tilt holds until its resource's resource_deps are ready, and the seed resource waits for space-internal-api. So the privileged seed rootfs build, which needs only the Rust artifact image's guest binaries, started only once internal-api was up. A seed-artifacts local_resource now runs build-seed.sh as soon as rust-artifacts is done, beside the space-api deploy chain. The custom_build still runs build-seed.sh before its docker build, from the same SEED_BUILD command and output directory, so it finds the seed up to date or rebuilds it; the publish Job keeps its gate on space-internal-api and the bucket init. build-seed.sh takes a file lock in its output directory, so the two callers never write it at once. provision-local-console only waits for the API rollout and execs into its pod, so it is now allow_parallel instead of waiting for Tilt to have nothing else in progress. space-internal-api no longer waits for it: nothing it runs or serves signs in as root@local. space-ui keeps the dependency.
build-seed.sh read the recipe's source settings before taking its lock, so a build that waited for another one could build with the settings it read before the wait and stamp the result with the hash of the recipe saved during it; later runs then took the old seed as current. The lock is now taken before any input is read; the cache-only build writes nothing to the output directory and stays unlocked. The seed-publish image build read the directory after build-seed.sh had exited and released the lock, so a seed build starting in between could delete the outputs under it. `build-seed.sh --read-lock -- <command>` runs a command holding the lock shared, and the Tiltfile runs the image build under it. With two Tilt resources running the script, it now requires flock rather than running unguarded. scripts/tests/test-kind-build-seed-lock.sh runs the script against a scratch checkout with docker stubbed and covers all three.
space-internal-api no longer waits for provision-local-console, so a failed console step no longer holds anything the bring-up waits for until the node-publication wait, which signs in as root@local and took a rejected login for an unpublished node until BOOTSTRAP_TIMEOUT. The bring-up now waits for the console step to succeed before that wait, and fails with its log like any failed Tilt resource. wait-node-publication.sh also says when it timed out on rejected logins.
The whole-bring-up cases model a settled Tilt, which now has to report provision-local-console ok before the node-publication wait; their fake resource lists say so. Case 14c pins the console wait: a failed provision-local-console ends the bring-up with its log before the node-publication wait runs.
The image build's shared lock is a new lock, taken after build-seed.sh has released its exclusive one, so a seed build already waiting can finish in between and the image is built from its output. The Tiltfile now says what holds on every path: no seed build rewrites the directory while the image build reads it. The wait message no longer assumes the holder is a seed build.
ac-pplx
force-pushed
the
ac/tilt-critical-path
branch
from
November 2, 2026 04:42
4d2579f to
6700606
Compare
nikhilbirmiwal-pplx
approved these changes
Nov 3, 2026
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.
Summary
This shortens a cold Kind bring-up by moving two Tilt steps off the critical path. Each step was held back for reasons unrelated to its own work. The charts and the seed-publish Job's gates do not change. space-internal-api stops waiting for the console step, and the bring-up gains one wait for it (below).
build-seed.shnow requiresflock.custom_builduntil its resource'sresource_depsare ready, andspace-seed-publishwaits forspace-internal-api. So the privileged rootfs build inbuild-seed.shcould start only once internal-api was Ready, even though it needs only the Rust artifact image's guest binaries. A newseed-artifactslocal_resource(allow_parallel = True, afterrust-artifacts) now runs it beside the space-api deploy chain. This mirrors howrust-artifactswas already pulled forward.space-seed-publishcustom_buildstill runsbuild-seed.shbefore itsdocker build. Both steps use oneSEED_BUILDcommand, which resolvesSPACE_SEED_OUTPUT_DIRthe same way. The image build finds the seed up to date or rebuilds it. The publish Job keeps its gate onspace-internal-apiandspace-object-store-bucket-init.build-seed.shtakes an exclusive file lock in its output directory before it reads any input, the recipe included, and holds it until the outputs and stamp are written. A build that waited therefore reads its inputs as they are once it runs, and the later caller finds the seed up to date. The image build reads the directory throughbuild-seed.sh --read-lock -- <command>, which holds the lock shared, so no seed build rewrites the directory while the docker build reads it. A seed build that takes the lock after the check and before the read finishes first, and the image is built from its output. The script now refuses to run withoutflock, rather than running two privileged builds unguarded. The cache-only build writes nothing there and takes no lock.provision-local-consoleonly waits for the API rollout and execsspace-db-migrator set-user-passwordin the API pod, so it is nowallow_parallel. As a serial resource it waited for Tilt to go idle and blocked every other update while it ran. That is why admin-api, internal-api and the credential authority were all applied the instant it finished.provision-local-consoleto succeed before the node-publication wait, which signs in asroot@local. A failed console step ends the bring-up with its log, like any failed Tilt resource; before, it surfaced as a "nodes not published" timeout.wait-node-publication.shalso says when it timed out on rejected logins.space-internal-apino longer lists the console step inresource_deps. Nothing it runs signs in asroot@local, and its build does not link the session-login code. Its callers present ServiceAccount tokens or the internal token; the seed publish Job uses a projected token. The only password logins during a bring-up are the node-publication wait, which now runs after the console step succeeds, and the smokes, which run after the bring-up returns.space-uikeeps the dependency; see "Not covered".Validation
Measured at
0afac29d(the scheduling change; later commits change only the locking and the failure path) on one 48-CPU box withscripts/benchmarks/kind-bringup-timeline.py, usingSPACE_KIND_TELEMETRY_MODE=otelas the Kind CI shards do. Each run used a fresh cluster and an emptySPACE_SEED_OUTPUT_DIR, with Rust and image caches warm. Times are seconds from the start ofsmoke-kind-e2e.sh. "Applied" is the time Tilt applied admin-api, internal-api and the authority. "Ready" lists the time each was Ready, in that order.Pair 1 is not a fair comparison. Main 1's rootfs spent 155 s fetching apt indexes. Branch 1 also rebuilt the UI image for its new commit. In pairs 2 and 3 the branch is 50 s and 41 s faster. On the branch the rootfs finishes before internal-api is Ready, so the seed-publish image build starts as soon as internal-api is Ready.
Seed freshness: on the live branch stack, I changed a string compiled into
spaced-svcand ranup.shagain.seed-artifactsand the seed-publish image build started together. The image build logged that the lock was held, waited, and then found the seed up to date. These all matchsha256:e0460394…:build-seed.sh'smanifest.jsoncontent_hash;manifest.jsonand the sha256 of the rootfs inside the Job's image;The image's rootfs contains the new string, and the staged
spaced-svcmatches the artifact image's binary. Reverting the change and runningup.shagain also passedsmoke-kind-e2e.sh.At this head, a fresh-cluster branch run with an empty seed directory passed
smoke-kind-e2e.shat 198.3 s. The seed rootfs ran at 108–135 s, and the image build ran under--read-lock. The freshness check above passed again through the new path: on each guest change, the image build logged that it was waiting on the lock.Regression tests, each failing on the commit before its fix:
scripts/tests/test-kind-build-seed-lock.shruns the real script against a scratch checkout withdockerstubbed. It shows that a build that waited on the lock builds with the recipe saved during the wait, that a build waits while a--read-lockcommand reads the directory, and that the script exits nonzero withoutflock.test-kind-stale-tilt-recovery.sh: a failed console step ends the bring-up with its log before the node-publication wait.Live check of the console failure, using a scratch edit that is not committed:
provision-local-consolesleeps 90 s, then sets the password of a user that does not exist.0afac29d, withSPACE_BOOTSTRAP_TIMEOUT=300, the bring-up failed after 466 s with "nodes not published as ready within 300s".Against the live stack,
wait-node-publication.shwith a wrong password now fails with "root@local login still rejected (HTTP 401)".Earlier, at
0afac29d, on the branch stack:up.shrerun reused the running Tilt (same pid, 11 s);smoke-kind-e2e.shpassed;SKIP_BOOTSTRAP=1 bash scripts/tests/smoke-kind-typed.sh all 1/4passed 17 of 17 (ECW 10, native 7), with the shard step's admin token and cold-receipt settings. The GHCR image mirror was not used locally.At this head, a warm
up.shrerun reused Tilt (11 s) andsmoke-kind-e2e.shpassed.test_kind_prune_superseded_images.py,test-kind-localhost-ports.sh,test-kind-rust-input-key.sh,test-kind-up-restart.shandtest-kind-stale-tilt-recovery.sh(all cases) pass. The 4 Kind smoke shards run in CI on this head.Severity and risk
Severity: does not apply. This is a local and CI bring-up speedup.
Risk: the main new behavior is two concurrent callers of
build-seed.sh, plus the image build reading what they write. The lock serializes every writer and keeps them out while the image build reads. The custom_build still rebuilds the seed if it is stale. Ifseed-artifactsfails, the bring-up fails the same way a failing seed-publish build does today. Kind hosts now needflock, which util-linux provides on the apt-based Linux hosts Kind already requires. Revert this PR to roll back.Merge order: #1017 rewrites the same seed-publish block. Whichever lands second keeps
SEED_BUILD,deps = SEED_DEPS + [...]and #1017's image call, with--read-lockwrapping only the image build, not the node load.Not covered
space-uistill depends onprovision-local-console. The UI pod does not sign in at start, so the dependency looks removable. It also gates the UI image build, but that build is off the critical path here.scripts/tests/lib/bootstrap-kind-stack.sh, assignments such asstatus="$(… | awk …)"run underset -euo pipefail. They end the bring-up silently whentilt get uiresourcesfails. This affects the console wait added here and two older lines onmain, in__die_on_failed_buildsand the quiet wait.AI assistance: Claude Code drafted the code changes, the measurements and this description.