Skip to content

Commit 58721c5

Browse files
authored
fix(uat): wait for nodewright tuning before validate readiness gate (#1429)
1 parent 6663eb5 commit 58721c5

2 files changed

Lines changed: 62 additions & 12 deletions

File tree

tests/uat/aws/run

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,13 @@ TRAINJOB_NAME="${TRAINJOB_NAME:-pytorch-mnist}"
6363
TRAINJOB_IMAGE="${TRAINJOB_IMAGE:-kubeflow/pytorch-dist-mnist:v1-9e12c68}"
6464
TRAINJOB_TIMEOUT_SECONDS="${TRAINJOB_TIMEOUT_SECONDS:-1200}" # 20 min
6565
HELMFILE_TIMEOUT_SECONDS="${HELMFILE_TIMEOUT_SECONDS:-1200}" # 20 min
66-
# Convergence budget for the post-install readiness gate. Cold-boot p5.48xlarge
66+
# Convergence budget for the post-install readiness gate. Spans nodewright
67+
# (skyhook) node tuning -- which REBOOTS the GPU node and re-inits the operator
68+
# stack after gpu-operator first reports ready -- plus cold-boot p5.48xlarge
6769
# GPU-operator convergence (driver build/load -> toolkit -> device-plugin ->
68-
# DCGM exporter) plus prometheus-adapter APIService aggregation can take many
69-
# minutes, so this is generous; the gate fails closed if exceeded.
70-
READINESS_TIMEOUT_SECONDS="${READINESS_TIMEOUT_SECONDS:-900}" # 15 min
70+
# DCGM exporter) and prometheus-adapter APIService aggregation. Generous; the
71+
# gate fails closed if exceeded.
72+
READINESS_TIMEOUT_SECONDS="${READINESS_TIMEOUT_SECONDS:-1200}" # 20 min
7173

7274
# wait_for polls <check-cmd...> every 10s until it succeeds (exit 0) or
7375
# <timeout-seconds> elapses. Fail-closed: returns non-zero with diagnostics on
@@ -106,6 +108,21 @@ _apiservice_available() {
106108
[[ "$(kubectl get apiservice "$1" \
107109
-o jsonpath='{.status.conditions[?(@.type=="Available")].status}' 2>/dev/null)" == "True" ]]
108110
}
111+
# _skyhook_complete is true when every nodewright (Skyhook) CR reports
112+
# status.status=complete. Skyhook node tuning REBOOTS the GPU node, which
113+
# re-initializes the gpu-operator operands AFTER ClusterPolicy first reports
114+
# ready — so this must clear before the GPU/metrics checks, else the gate passes
115+
# on a transient pre-reboot ready state and validate races the re-convergence.
116+
# Empty list (CR not created yet) => not complete => keep waiting. If the Skyhook
117+
# CRD is absent the recipe has no nodewright, so skip rather than block. Skyhook
118+
# CRs are cluster-scoped (see validators/deployment/expected_resources.go).
119+
_skyhook_complete() {
120+
kubectl get crd skyhooks.skyhook.nvidia.com >/dev/null 2>&1 || return 0
121+
local states
122+
states="$(kubectl get skyhooks.skyhook.nvidia.com \
123+
-o jsonpath='{range .items[*]}{.status.status}{"\n"}{end}' 2>/dev/null)"
124+
[[ -n "$states" ]] && ! grep -qxv 'complete' <<<"$states"
125+
}
109126

110127
# Per-run unique OCI repo suffix. The committed config carries the stable
111128
# prefix only; we append `-${RUN_ID}` once, idempotently, so re-running a
@@ -223,10 +240,18 @@ phase_install() {
223240
# conformance-phase checks evaluate a ready cluster. ClusterPolicy=ready implies
224241
# the DCGM exporter operand is rolled out; the two aggregated APIServices imply
225242
# prometheus-adapter is serving custom/external metrics.
226-
# All three checks share a SINGLE READINESS_TIMEOUT_SECONDS budget: compute one
227-
# deadline up front and pass each call the time remaining until it, so the
243+
# All readiness checks share a SINGLE READINESS_TIMEOUT_SECONDS budget: compute
244+
# one deadline up front and pass each call the time remaining until it, so the
228245
# combined barrier cannot run N x the per-check timeout.
246+
#
247+
# nodewright (skyhook) tuning is waited on FIRST: it reboots the GPU node to
248+
# apply kernel tuning, re-initializing the gpu-operator operands after the
249+
# operator first reports ClusterPolicy=ready. Checking ClusterPolicy/operands
250+
# before that reboot lets the gate pass on a transient pre-reboot ready state,
251+
# so wait for tuning to complete before the GPU/metrics checks.
229252
local ready_deadline=$(( SECONDS + READINESS_TIMEOUT_SECONDS ))
253+
wait_for "nodewright (skyhook) tuning complete" "$(( ready_deadline - SECONDS ))" \
254+
_skyhook_complete
230255
wait_for "gpu-operator ClusterPolicy state=ready" "$(( ready_deadline - SECONDS ))" \
231256
_clusterpolicy_ready
232257
wait_for "custom.metrics.k8s.io APIService Available" "$(( ready_deadline - SECONDS ))" \

tests/uat/gcp/run

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,13 @@ TRAINJOB_NAME="${TRAINJOB_NAME:-pytorch-mnist}"
6363
TRAINJOB_IMAGE="${TRAINJOB_IMAGE:-kubeflow/pytorch-dist-mnist:v1-9e12c68}"
6464
TRAINJOB_TIMEOUT_SECONDS="${TRAINJOB_TIMEOUT_SECONDS:-1200}" # 20 min
6565
HELMFILE_TIMEOUT_SECONDS="${HELMFILE_TIMEOUT_SECONDS:-1200}" # 20 min
66-
# Convergence budget for the post-install readiness gate. Cold-boot GPU-operator
66+
# Convergence budget for the post-install readiness gate. Spans nodewright
67+
# (skyhook) node tuning -- which REBOOTS the GPU node and re-inits the operator
68+
# stack after gpu-operator first reports ready -- plus cold-boot GPU-operator
6769
# convergence (driver build/load -> toolkit -> device-plugin -> DCGM exporter)
68-
# plus prometheus-adapter APIService aggregation can take many minutes, so this
69-
# is generous; the gate fails closed if exceeded.
70-
READINESS_TIMEOUT_SECONDS="${READINESS_TIMEOUT_SECONDS:-900}" # 15 min
70+
# and prometheus-adapter APIService aggregation. Generous; the gate fails closed
71+
# if exceeded.
72+
READINESS_TIMEOUT_SECONDS="${READINESS_TIMEOUT_SECONDS:-1200}" # 20 min
7173

7274
# wait_for polls <check-cmd...> every 10s until it succeeds (exit 0) or
7375
# <timeout-seconds> elapses. Fail-closed: returns non-zero with diagnostics on
@@ -106,6 +108,21 @@ _apiservice_available() {
106108
[[ "$(kubectl get apiservice "$1" \
107109
-o jsonpath='{.status.conditions[?(@.type=="Available")].status}' 2>/dev/null)" == "True" ]]
108110
}
111+
# _skyhook_complete is true when every nodewright (Skyhook) CR reports
112+
# status.status=complete. Skyhook node tuning REBOOTS the GPU node, which
113+
# re-initializes the gpu-operator operands AFTER ClusterPolicy first reports
114+
# ready — so this must clear before the GPU/metrics checks, else the gate passes
115+
# on a transient pre-reboot ready state and validate races the re-convergence.
116+
# Empty list (CR not created yet) => not complete => keep waiting. If the Skyhook
117+
# CRD is absent the recipe has no nodewright, so skip rather than block. Skyhook
118+
# CRs are cluster-scoped (see validators/deployment/expected_resources.go).
119+
_skyhook_complete() {
120+
kubectl get crd skyhooks.skyhook.nvidia.com >/dev/null 2>&1 || return 0
121+
local states
122+
states="$(kubectl get skyhooks.skyhook.nvidia.com \
123+
-o jsonpath='{range .items[*]}{.status.status}{"\n"}{end}' 2>/dev/null)"
124+
[[ -n "$states" ]] && ! grep -qxv 'complete' <<<"$states"
125+
}
109126

110127
# Per-run unique OCI repo suffix. The committed config carries the stable
111128
# prefix only; we append `-${RUN_ID}` once, idempotently, so re-running a
@@ -223,10 +240,18 @@ phase_install() {
223240
# conformance-phase checks evaluate a ready cluster. ClusterPolicy=ready implies
224241
# the DCGM exporter operand is rolled out; the two aggregated APIServices imply
225242
# prometheus-adapter is serving custom/external metrics.
226-
# All three checks share a SINGLE READINESS_TIMEOUT_SECONDS budget: compute one
227-
# deadline up front and pass each call the time remaining until it, so the
243+
# All readiness checks share a SINGLE READINESS_TIMEOUT_SECONDS budget: compute
244+
# one deadline up front and pass each call the time remaining until it, so the
228245
# combined barrier cannot run N x the per-check timeout.
246+
#
247+
# nodewright (skyhook) tuning is waited on FIRST: it reboots the GPU node to
248+
# apply kernel tuning, re-initializing the gpu-operator operands after the
249+
# operator first reports ClusterPolicy=ready. Checking ClusterPolicy/operands
250+
# before that reboot lets the gate pass on a transient pre-reboot ready state,
251+
# so wait for tuning to complete before the GPU/metrics checks.
229252
local ready_deadline=$(( SECONDS + READINESS_TIMEOUT_SECONDS ))
253+
wait_for "nodewright (skyhook) tuning complete" "$(( ready_deadline - SECONDS ))" \
254+
_skyhook_complete
230255
wait_for "gpu-operator ClusterPolicy state=ready" "$(( ready_deadline - SECONDS ))" \
231256
_clusterpolicy_ready
232257
wait_for "custom.metrics.k8s.io APIService Available" "$(( ready_deadline - SECONDS ))" \

0 commit comments

Comments
 (0)