#!/bin/bash # Бенчмарк: upload, deploy, cold/hot start для простой функции # Все результаты пишутся в test-results/bench-func set -e RESULTS_DIR="$(dirname "$0")/../test-results/bench-func" FUNC_DIR="$(dirname "$0")" FUNC_NAME="bench-hello" ENV_NAME="bench-python-env" NS="bench-func-$(date +%s)" # Donor namespace с готовым RBAC DONOR_NS=$(kubectl get ns --no-headers | awk '{print $1}' | grep -E '^fission-[a-f0-9]{16}$' | head -1) LOGFILE="$RESULTS_DIR/bench_func_$(date +%Y-%m-%d_%H-%M-%S).log" mkdir -p "$RESULTS_DIR" { echo "# Bench: $(date)" echo "Namespace: $NS" echo "Donor NS: $DONOR_NS" } | tee "$LOGFILE" # 1. Create namespace + copy RBAC from donor echo -n "[1] Create namespace + RBAC... " | tee -a "$LOGFILE" START_NS=$(date +%s%3N) kubectl create ns "$NS" >/dev/null # Копируем ServiceAccount-ы for sa in fission-builder fission-fetcher; do kubectl get sa "$sa" -n "$DONOR_NS" -o json 2>/dev/null \ | jq 'del(.metadata.resourceVersion,.metadata.uid,.metadata.creationTimestamp,.metadata.annotations,.metadata.ownerReferences) | .metadata.namespace = $ns' --arg ns "$NS" \ | kubectl apply -f - >/dev/null 2>&1 || true done # Копируем RoleBindings из donor kubectl get rolebinding -n "$DONOR_NS" -o json 2>/dev/null \ | jq -r '.items[] | select(.roleRef.kind=="ClusterRole") | del(.metadata.resourceVersion,.metadata.uid,.metadata.creationTimestamp,.metadata.annotations,.metadata.ownerReferences) | .metadata.namespace = $ns' --arg ns "$NS" \ | kubectl apply -f - >/dev/null 2>&1 || true END_NS=$(date +%s%3N) echo "$((END_NS-START_NS)) ms" | tee -a "$LOGFILE" # 2. Create environment echo -n "[2] Create environment... " | tee -a "$LOGFILE" START_ENV=$(date +%s%3N) fission env create --name "$ENV_NAME" --image naeel/fission-python-env:v1.1 --namespace "$NS" >/dev/null 2>&1 END_ENV=$(date +%s%3N) echo "$((END_ENV-START_ENV)) ms" | tee -a "$LOGFILE" # 3. Upload function echo -n "[3] Upload function... " | tee -a "$LOGFILE" START_UP=$(date +%s%3N) fission fn create --name "$FUNC_NAME" --env "$ENV_NAME" --code "$FUNC_DIR/hello.py" --namespace "$NS" >/dev/null 2>&1 END_UP=$(date +%s%3N) echo "$((END_UP-START_UP)) ms" | tee -a "$LOGFILE" # 4. Cold start invoke (retry до 60 раз по 2 сек = 2 мин максимум) echo -n "[4] Cold start invoke... " | tee -a "$LOGFILE" START_COLD=$(date +%s%3N) COLD_OK=0 for i in {1..60}; do RESULT=$(fission fn test --name "$FUNC_NAME" --namespace "$NS" 2>&1 || true) if echo "$RESULT" | grep -qE "hello|200|statusCode"; then COLD_OK=1 break fi sleep 2 done END_COLD=$(date +%s%3N) if [[ $COLD_OK -eq 1 ]]; then echo "$((END_COLD-START_COLD)) ms" | tee -a "$LOGFILE" else echo "FAILED" | tee -a "$LOGFILE" { echo "[DEBUG] pods in $NS:" kubectl get pods -n "$NS" 2>&1 echo "[DEBUG] events in $NS:" kubectl get events -n "$NS" --sort-by=.metadata.creationTimestamp 2>&1 | tail -20 } >> "$LOGFILE" exit 1 fi # 5. Hot start invoke (pod уже прогрет, retry до 5 раз) echo -n "[5] Hot start invoke... " | tee -a "$LOGFILE" START_HOT=$(date +%s%3N) HOT_OK=0 for i in {1..5}; do RESULT=$(fission fn test --name "$FUNC_NAME" --namespace "$NS" 2>&1 || true) if echo "$RESULT" | grep -qE "hello|200|statusCode"; then HOT_OK=1; break fi sleep 2 done END_HOT=$(date +%s%3N) if [[ $HOT_OK -eq 1 ]]; then echo "$((END_HOT-START_HOT)) ms" | tee -a "$LOGFILE" else echo "FAILED (pod не ответил)" | tee -a "$LOGFILE" fi # 6. Hot x5 echo "[6] Hot start x5:" | tee -a "$LOGFILE" for i in {1..5}; do START_H=$(date +%s%3N) RESULT=$(fission fn test --name "$FUNC_NAME" --namespace "$NS" 2>&1 || true) END_H=$(date +%s%3N) if echo "$RESULT" | grep -qE "hello|200|statusCode"; then echo " invoke #$i: $((END_H-START_H)) ms" | tee -a "$LOGFILE" else echo " invoke #$i: FAILED" | tee -a "$LOGFILE" fi done echo "---" | tee -a "$LOGFILE" echo "DONE. Log: $LOGFILE"