mirror of
https://github.com/hanzo-ml/kserve.git
synced 2026-10-30 20:53:49 +00:00
Signed-off-by: Vivek Karunai Kiri Ragavan <[email protected]>
199 lines
7.0 KiB
Bash
Executable File
199 lines
7.0 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright 2025 The KServe Authors.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
# Fail-fast health check for the autoscaling metrics pipeline.
|
|
# Validates that Prometheus, WVA, and the external metrics API are wired
|
|
# correctly BEFORE running e2e tests. Exits non-zero on first failure.
|
|
#
|
|
# Usage: verify-autoscaling-health.sh <hpa|keda>
|
|
|
|
set -euo pipefail
|
|
|
|
AUTOSCALER="${1:?Usage: verify-autoscaling-health.sh <hpa|keda>}"
|
|
|
|
PROMETHEUS_NAMESPACE="${PROMETHEUS_NAMESPACE:-monitoring}"
|
|
WVA_NAMESPACE="${WVA_NAMESPACE:-wva-system}"
|
|
KEDA_NAMESPACE="${KEDA_NAMESPACE:-keda}"
|
|
|
|
retry() {
|
|
local description="$1"
|
|
local timeout="$2"
|
|
local interval="${3:-5}"
|
|
shift 3
|
|
local cmd=("$@")
|
|
|
|
local deadline=$((SECONDS + timeout))
|
|
local attempt=0
|
|
while true; do
|
|
attempt=$((attempt + 1))
|
|
if "${cmd[@]}" 2>/dev/null; then
|
|
echo " [PASS] ${description}"
|
|
return 0
|
|
fi
|
|
if [ $SECONDS -ge $deadline ]; then
|
|
echo " [FAIL] ${description} (timed out after ${timeout}s, ${attempt} attempts)"
|
|
return 1
|
|
fi
|
|
sleep "$interval"
|
|
done
|
|
}
|
|
|
|
echo "======================================================================"
|
|
echo "Autoscaling Pipeline Health Check (mode: ${AUTOSCALER})"
|
|
echo "======================================================================"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Pod readiness
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "--- Step 1: Verifying pod readiness ---"
|
|
|
|
echo " Waiting for Prometheus pods..."
|
|
kubectl wait --for=condition=Ready pod \
|
|
-l app.kubernetes.io/name=prometheus \
|
|
-n "${PROMETHEUS_NAMESPACE}" \
|
|
--timeout=120s
|
|
|
|
echo " Waiting for WVA pods..."
|
|
kubectl wait --for=condition=Ready pod \
|
|
-l control-plane=controller-manager \
|
|
-n "${WVA_NAMESPACE}" \
|
|
--timeout=120s
|
|
|
|
if [[ "${AUTOSCALER}" == "hpa" ]]; then
|
|
echo " Waiting for Prometheus Adapter pods..."
|
|
kubectl wait --for=condition=Ready pod \
|
|
-l app.kubernetes.io/name=prometheus-adapter \
|
|
-n "${PROMETHEUS_NAMESPACE}" \
|
|
--timeout=120s
|
|
elif [[ "${AUTOSCALER}" == "keda" ]]; then
|
|
echo " Waiting for KEDA operator pods..."
|
|
kubectl wait --for=condition=Ready pod \
|
|
-l app.kubernetes.io/name=keda-operator \
|
|
-n "${KEDA_NAMESPACE}" \
|
|
--timeout=120s
|
|
fi
|
|
|
|
echo " [PASS] All pods are Ready"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. Prometheus API reachable
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "--- Step 2: Verifying Prometheus API is reachable ---"
|
|
|
|
PROM_POD=$(kubectl get pods -n "${PROMETHEUS_NAMESPACE}" \
|
|
-l app.kubernetes.io/name=prometheus \
|
|
-l app.kubernetes.io/managed-by=prometheus-operator \
|
|
-o jsonpath='{.items[0].metadata.name}')
|
|
|
|
check_prometheus_api() {
|
|
kubectl exec -n "${PROMETHEUS_NAMESPACE}" "${PROM_POD}" -c prometheus -- \
|
|
wget -qO- --no-check-certificate \
|
|
"https://localhost:9090/api/v1/status/config" | grep -q '"status":"success"'
|
|
}
|
|
|
|
retry "Prometheus API responds" 30 5 check_prometheus_api
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. WVA ServiceMonitor target is UP in Prometheus
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "--- Step 3: Verifying WVA ServiceMonitor target is scraped ---"
|
|
|
|
check_wva_target_up() {
|
|
kubectl exec -n "${PROMETHEUS_NAMESPACE}" "${PROM_POD}" -c prometheus -- \
|
|
wget -qO- --no-check-certificate \
|
|
"https://localhost:9090/api/v1/targets" | grep -q "${WVA_NAMESPACE}"
|
|
}
|
|
|
|
retry "WVA target discovered by Prometheus" 60 5 check_wva_target_up
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. WVA controller can reach Prometheus (log smoke-check)
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "--- Step 4: Verifying WVA controller health (log check) ---"
|
|
|
|
WVA_POD=$(kubectl get pods -n "${WVA_NAMESPACE}" \
|
|
-l control-plane=controller-manager \
|
|
-o jsonpath='{.items[0].metadata.name}')
|
|
|
|
check_wva_no_prometheus_errors() {
|
|
local logs
|
|
logs=$(kubectl logs -n "${WVA_NAMESPACE}" "${WVA_POD}" --tail=50 2>/dev/null || echo "")
|
|
if echo "${logs}" | grep -qi "error.*prometheus\|connection refused\|no such host\|dial tcp.*refused"; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
if ! check_wva_no_prometheus_errors; then
|
|
echo " [FAIL] WVA controller has Prometheus connectivity errors in logs:"
|
|
kubectl logs -n "${WVA_NAMESPACE}" "${WVA_POD}" --tail=20
|
|
exit 1
|
|
fi
|
|
echo " [PASS] WVA controller logs show no Prometheus errors"
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5. External Metrics API is healthy
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "--- Step 5: Verifying External Metrics API ---"
|
|
|
|
check_external_metrics_api() {
|
|
kubectl get --raw /apis/external.metrics.k8s.io/v1beta1 >/dev/null 2>&1
|
|
}
|
|
|
|
retry "External Metrics API discovery endpoint" 60 5 check_external_metrics_api
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 5b. Autoscaler-specific checks
|
|
# ---------------------------------------------------------------------------
|
|
if [[ "${AUTOSCALER}" == "hpa" ]]; then
|
|
echo ""
|
|
echo "--- Step 5b: Verifying Prometheus Adapter APIService ---"
|
|
|
|
check_apiservice_available() {
|
|
local status
|
|
status=$(kubectl get apiservice v1beta1.external.metrics.k8s.io \
|
|
-o jsonpath='{.status.conditions[?(@.type=="Available")].status}')
|
|
[[ "${status}" == "True" ]]
|
|
}
|
|
|
|
retry "APIService v1beta1.external.metrics.k8s.io Available" 60 5 check_apiservice_available
|
|
|
|
elif [[ "${AUTOSCALER}" == "keda" ]]; then
|
|
echo ""
|
|
echo "--- Step 5b: Verifying KEDA metrics server ---"
|
|
|
|
check_keda_metrics_server() {
|
|
kubectl get pods -n "${KEDA_NAMESPACE}" \
|
|
-l app=keda-operator-metrics-apiserver \
|
|
-o jsonpath='{.items[0].status.phase}' | grep -q "Running"
|
|
}
|
|
|
|
retry "KEDA metrics server Running" 60 5 check_keda_metrics_server
|
|
fi
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Summary
|
|
# ---------------------------------------------------------------------------
|
|
echo ""
|
|
echo "======================================================================"
|
|
echo "All autoscaling pipeline health checks PASSED (mode: ${AUTOSCALER})"
|
|
echo "======================================================================"
|