65 lines
2.5 KiB
Bash
65 lines
2.5 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
NAMESPACE=${KUBE_NAMESPACE:-magistr}
|
|
BACKEND_REF=${1:-}
|
|
FRONTEND_REF=${2:-}
|
|
|
|
log() {
|
|
printf '[CI/CD] %s\n' "$1"
|
|
}
|
|
|
|
fail() {
|
|
printf '[CI/CD] Ошибка: %s\n' "$1" >&2
|
|
exit 1
|
|
}
|
|
|
|
require_digest() {
|
|
local image_ref=$1
|
|
local component=$2
|
|
if [[ ! "$image_ref" =~ ^[^[:space:]@]+@sha256:[0-9a-f]{64}$ ]]; then
|
|
fail "для ${component} требуется полный immutable image digest"
|
|
fi
|
|
}
|
|
|
|
require_digest "$BACKEND_REF" "backend"
|
|
require_digest "$FRONTEND_REF" "frontend"
|
|
|
|
previous_backend=$(kubectl get deployment backend -n "$NAMESPACE" \
|
|
-o 'jsonpath={.spec.template.spec.containers[?(@.name=="backend")].image}')
|
|
previous_frontend=$(kubectl get deployment frontend -n "$NAMESPACE" \
|
|
-o 'jsonpath={.spec.template.spec.containers[?(@.name=="frontend")].image}')
|
|
|
|
[[ -n "$previous_backend" ]] || fail "не удалось определить текущий образ backend"
|
|
[[ -n "$previous_frontend" ]] || fail "не удалось определить текущий образ frontend"
|
|
|
|
rollback() {
|
|
local failed=0
|
|
log "Rollout завершился ошибкой, возвращаем предыдущие образы"
|
|
kubectl set image deployment/backend backend="$previous_backend" -n "$NAMESPACE" || failed=1
|
|
kubectl set image deployment/frontend frontend="$previous_frontend" -n "$NAMESPACE" || failed=1
|
|
kubectl rollout status deployment/frontend -n "$NAMESPACE" --timeout=120s || failed=1
|
|
kubectl rollout status deployment/backend -n "$NAMESPACE" --timeout=300s || failed=1
|
|
if [[ "$failed" -ne 0 ]]; then
|
|
printf '[CI/CD] Ошибка: автоматический rollback требует вмешательства оператора\n' >&2
|
|
return 1
|
|
fi
|
|
log "Предыдущие образы восстановлены"
|
|
}
|
|
|
|
log "Применяем проверенные image digests"
|
|
if ! kubectl set image deployment/backend backend="$BACKEND_REF" -n "$NAMESPACE" \
|
|
|| ! kubectl set image deployment/frontend frontend="$FRONTEND_REF" -n "$NAMESPACE"; then
|
|
rollback || true
|
|
fail "не удалось обновить Deployment"
|
|
fi
|
|
|
|
if ! kubectl rollout status deployment/frontend -n "$NAMESPACE" --timeout=120s \
|
|
|| ! kubectl rollout status deployment/backend -n "$NAMESPACE" --timeout=300s; then
|
|
rollback || true
|
|
fail "новая ревизия не достигла состояния Ready"
|
|
fi
|
|
|
|
log "Immutable rollout успешно завершён"
|