From c97b45eb7053c5487ff19b4c2cd7d554ffdf5235 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 3 Nov 2026 09:27:13 +0000 Subject: [PATCH 1/2] fix(test): pull the node recovery stand-in image on each kind node A host Docker on the containerd image store pulls a multi-platform index that holds only the host platform's blobs, so kind's import of it with all platforms fails on a missing digest. Each node now pulls the image through its own runtime and only the locally built watcher image is loaded from the host. --- tests/node_recovery/run.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/node_recovery/run.sh b/tests/node_recovery/run.sh index 366a935b..a2155fda 100755 --- a/tests/node_recovery/run.sh +++ b/tests/node_recovery/run.sh @@ -155,8 +155,11 @@ doomed_uid="$(kubectl get node "$doomed_node" -o jsonpath='{.metadata.uid}')" log "Building and loading the watcher image and the stand-in's image" docker build -q -f "$repo_root/node-recovery/Dockerfile" -t "$image" "$repo_root" >/dev/null -docker pull -q "$pod_image" >/dev/null -kind load docker-image "$image" "$pod_image" --name "$cluster" >/dev/null +kind load docker-image "$image" --name "$cluster" >/dev/null +# The stand-in's image is pulled by each node's own runtime: a host Docker on the containerd image store pulls a multi-platform index holding only the host platform's blobs, and kind's import of it with all platforms fails on the missing ones. +for node in $(kind get nodes --name "$cluster"); do + docker exec "$node" crictl pull "$pod_image" >/dev/null +done # Renders the role's manifests into $work/recovery.yaml; extra arguments are further -e settings, such as the prune threshold. render_manifests() { From 06ab4890e8a634e9b4e97732ed160cc8bc3f9f51 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Tue, 3 Nov 2026 09:35:19 +0000 Subject: [PATCH 2/2] fix(test): quote the etcd role label so shellcheck reads it as a string --- tests/node_recovery/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/node_recovery/run.sh b/tests/node_recovery/run.sh index a2155fda..cd8af528 100755 --- a/tests/node_recovery/run.sh +++ b/tests/node_recovery/run.sh @@ -27,7 +27,7 @@ recovery_bound=$((grace_seconds + after_seconds + poll_seconds + margin_seconds) stuck_watch_seconds=60 # Voting etcd members the prune pass needs to remain, the quorum floor for tolerating one failure. kind runs no etcd member beyond its control plane's, so phase 4 gives three Ready nodes the etcd role label. min_voters=3 -etcd_role_label=node-role.kubernetes.io/etcd +etcd_role_label="node-role.kubernetes.io/etcd" # Longer than after_seconds, as the watcher requires. Counted from when the worker went Unknown, which phase 3 reached long before phase 4 turns pruning on. prune_after_seconds=60 removable_label=github-runner.exadev.io/removable