#!/usr/bin/env bash # Pre-pull images to all cluster nodes. # # Reads image references from stdin, one per line. Empty lines and lines # starting with '#' are ignored. # # Some workloads (OVN raft, LINSTOR) are sensitive to peer-readiness at # startup: if nodes pull the image at different speeds, one replica boots # before its peers are reachable, exhausts its raft connection retries, and # the HelmRelease install times out. Pre-pulling eliminates the pull stagger # so all replicas start within milliseconds of each other. # # Implementation: a DaemonSet with one regular container per image (parallel # pulls — total time = max of any one image rather than sum). kubectl rollout # status blocks until all pods are Ready (= all containers running = all # images cached on every node), then we delete the DaemonSet. set -euo pipefail cleanup() { kubectl delete daemonset e2e-image-prepuller -n kube-system --ignore-not-found } trap cleanup EXIT mapfile -t images < <(grep -Ev '^[[:space:]]*(#|$)' | sort -u) if [[ ${#images[@]} -eq 0 ]]; then echo "e2e-prepull-images: no images on stdin, nothing to do" >&2 exit 0 fi echo "Pre-pulling ${#images[@]} image(s):" printf ' %s\n' "${images[@]}" containers="" i=0 for image in "${images[@]}"; do containers+=" - name: pull-${i} image: ${image} command: [\"sleep\", \"infinity\"] imagePullPolicy: IfNotPresent resources: requests: cpu: 1m memory: 1Mi" i=$((i + 1)) done kubectl apply -f - <