Skip to content

ci: run bare metal maintenance on the right nodes - #2597

Open
sespiros wants to merge 2 commits into
mainfrom
sse/bm-maintenance-runner-host
Open

ci: run bare metal maintenance on the right nodes#2597
sespiros wants to merge 2 commits into
mainfrom
sse/bm-maintenance-runner-host

Conversation

@sespiros

Copy link
Copy Markdown
Collaborator

Two nodes have carried ci.contrast.edgeless.systems/main-runner=true since a second bare-metal machine joined the TDX-GPU cluster on 2026-08-14, so the maintenance jobs pick one at random.

nix-gc collects the runner's nix store and dies on the other machine (timed out 08-18 and 08-20, blocking v1.23.1, hence b0753f7).
It now selects runner-host=<runner name>, which names exactly one node.
cleanup and cleanup-containerd pass but only clean the node they land on, so they now run once per main-runner node.

Before merging, label each runner's node in its own cluster, or nix-gc goes Pending and times out:

kubectl label node <node> ci.contrast.edgeless.systems/runner-host=<runner name>

for dgx-007, palutena, discovery, olimar, hetzner-ax162-snp.
Test-target nodes like the second TDX-GPU machine keep main-runner and get no runner-host.

Revert b0753f7 once the bare metal maintenance run this merge triggers is green on TDX-GPU.
Why nix-gc dies on that node is still unknown: the job deletes its namespace on failure before anything captures the pod state.

@sespiros
sespiros requested a review from charludo August 20, 2026 18:33
@sespiros sespiros added no changelog PRs not listed in the release notes do not merge This shouldn't be merged at this point labels Aug 20, 2026
@sespiros
sespiros force-pushed the sse/bm-maintenance-runner-host branch from 14cd4f1 to 33599a7 Compare August 20, 2026 20:37
The job garbage collects the nix store of the machine hosting the GitHub
runner, but selected ci.contrast.edgeless.systems/main-runner=true, which two
nodes have carried since a second bare-metal machine joined the TDX-GPU
cluster on 2026-08-14. That node needs main-runner so test pods can be
scheduled on it for B300 GPUs (#2566), so pin nix gc to the runner's own
machine instead, and fail with a named error when that label is missing
rather than after a 600s wait. It has timed out three times since, on
2026-08-18 and twice on 2026-08-20.

Signed-off-by: Spyros Seimenis <sse@edgeless.systems>
@sespiros
sespiros force-pushed the sse/bm-maintenance-runner-host branch from 33599a7 to 7108310 Compare August 21, 2026 07:26
cleanup and cleanup-containerd select main-runner=true, which two nodes have
carried since a second bare-metal machine joined the TDX-GPU cluster. They
still pass, but each run cleans one of the two and leaves the other's runtime
class directories, snapshotter state and images behind. Run the same job once
per schedulable matching node, and fail when none is labelled rather than
quietly cleaning nothing.

The job is deleted before each apply because spec.template is immutable, so
applying the next node's variant over one left by an interrupted run would
fail. The job timeout grows with it: the worst case is one 600s wait per node.

Signed-off-by: Spyros Seimenis <sse@edgeless.systems>
@sespiros
sespiros force-pushed the sse/bm-maintenance-runner-host branch from 7108310 to 9daf20c Compare August 21, 2026 08:46
@sespiros sespiros removed the do not merge This shouldn't be merged at this point label Aug 21, 2026
@sespiros
sespiros marked this pull request as ready for review August 21, 2026 09:32
@sespiros sespiros added the do not merge This shouldn't be merged at this point label Aug 21, 2026

@charludo charludo 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.

Thanks! In general, LGTM. I'm not overly familiar with the available labeling strategies (both technically and best-practice) though, maybe Markus should also take a look at this?

echo "::error::no node labeled ci.contrast.edgeless.systems/main-runner=true"
exit 1
fi
while IFS= read -r node; do

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.

(sorry, sanity check: we expect nodes to always have len==1, right? otherwise I'd comment that a failure on one node means we never try the other nodes)

kubectl delete job -n maintenance-cleanup cleanup-maintenance --ignore-not-found
sed -e "s#@@REPLACE_IMAGE@@#${IMAGE}#g" -e "s#@@REPLACE_K3S_VERSION@@#${K3S_VERSION}#g" -e "s#@@REPLACE_NODE@@#${node}#g" \
./tools/bm-maintenance/cleanup.yml | kubectl apply -f -
kubectl wait -n maintenance-cleanup --for=condition=complete --timeout=600s job/cleanup-maintenance

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.

I wonder if we can race a second kubectl wait with --for-condition=failed on all of these and have them cancel the attempt long before the 600s timeout in case of an ctual error

Once the node has joined the cluster, apply the label with:

```bash
kubectl label node <node> ci.contrast.edgeless.systems/runner-host=<runner name>

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.

Can we just use kubernetes.io/hostname=<runner name> and not have to worry about labeling the hosts? Or is there a downside

@sespiros
sespiros requested a review from burgerdev August 24, 2026 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

do not merge This shouldn't be merged at this point no changelog PRs not listed in the release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants