From fc013b174fbbf6c5d67e327cf140d583dcd94735 Mon Sep 17 00:00:00 2001 From: ZhenYi <434836402@qq.com> Date: Mon, 11 May 2026 00:17:43 +0800 Subject: [PATCH] fix(ops): preserve resources on deploy failure and protect ConfigMap/PVC from deletion - deploy.sh: keep failed release for debugging instead of auto-uninstall, add helm.sh/resource-policy=keep annotation on ConfigMap and PVC - uninstall.sh: interactive confirmation with protected resource list, post-uninstall verification that namespace/ConfigMap/PVC still exist --- deploy.sh | 27 +++++++++++++++++-------- uninstall.sh | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 uninstall.sh diff --git a/deploy.sh b/deploy.sh index 211214e..1371f9d 100644 --- a/deploy.sh +++ b/deploy.sh @@ -30,24 +30,25 @@ log "Ensuring namespace $NAMESPACE exists..." kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - # ── 2. Ensure prerequisites ───────────────────────────────────────── -# Namespace must exist (not managed by Helm) if ! kubectl get namespace "$NAMESPACE" &>/dev/null; then err "Namespace '$NAMESPACE' not found — create it first: kubectl create namespace $NAMESPACE" fi -# ConfigMap (must exist before Helm install) if ! kubectl get configmap "$CONFIG_MAP" -n "$NAMESPACE" &>/dev/null; then err "ConfigMap '$CONFIG_MAP' not found in namespace '$NAMESPACE' — create it first" fi -# PVC (must exist before Helm install) if ! kubectl get pvc "$PVC_NAME" -n "$NAMESPACE" &>/dev/null; then err "PVC '$PVC_NAME' not found in namespace '$NAMESPACE' — create it first" fi +# Protect ConfigMap and PVC from accidental Helm deletion +kubectl annotate configmap "$CONFIG_MAP" -n "$NAMESPACE" helm.sh/resource-policy=keep --overwrite +kubectl annotate pvc "$PVC_NAME" -n "$NAMESPACE" helm.sh/resource-policy=keep --overwrite + # cert-manager ClusterIssuer -if ! kubectl get clusterissuer letsencrypt-prod &>/dev/null; then - warn "ClusterIssuer 'letsencrypt-prod' not found — TLS certificate issuance will fail" +if ! kubectl get clusterissuer cloudflare-acme-cluster-issuer &>/dev/null; then + warn "ClusterIssuer 'cloudflare-acme-cluster-issuer' not found — TLS certificate issuance will fail" fi log "Prerequisites verified" @@ -59,14 +60,24 @@ helm lint "$CHART_DIR" || err "Helm lint failed" # ── 4. Deploy ──────────────────────────────────────────────────────── log "Deploying release $RELEASE with tag $TAG..." -helm upgrade --install "$RELEASE" "$CHART_DIR" \ +if ! helm upgrade --install "$RELEASE" "$CHART_DIR" \ --namespace "$NAMESPACE" \ --set imageRegistry="$REGISTRY" \ --set imageTag="$TAG" \ --set configMapName="$CONFIG_MAP" \ --set pvcName="$PVC_NAME" \ - --wait \ - --timeout 5m + --timeout 5m; then + echo "" + err "Deployment FAILED — release preserved for debugging. + +Debug commands: + helm status $RELEASE -n $NAMESPACE + kubectl get pods -n $NAMESPACE + kubectl logs -n app --previous + helm rollback $RELEASE -n $NAMESPACE (rollback to previous release) + helm uninstall $RELEASE -n $NAMESPACE (remove failed release)" + +fi log "Release $RELEASE deployed successfully" diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 0000000..a709216 --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ── helpers ────────────────────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' +log() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } + +# ── defaults ───────────────────────────────────────────────────────── +NAMESPACE="${NAMESPACE:-app}" +RELEASE="${RELEASE:-deploy}" +CONFIG_MAP="${CONFIG_MAP:-app-env}" +PVC_NAME="${PVC_NAME:-shared-data}" + +# ── safety check ───────────────────────────────────────────────────── +echo "" +warn "This will remove Helm release '$RELEASE' from namespace '$NAMESPACE'." +warn "The following resources are PROTECTED and will NOT be deleted:" +warn " - Namespace: $NAMESPACE" +warn " - ConfigMap: $CONFIG_MAP" +warn " - PVC: $PVC_NAME" +echo "" +read -rp "Continue? [y/N] " confirm +if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then + log "Cancelled" + exit 0 +fi + +# ── uninstall ──────────────────────────────────────────────────────── +log "Uninstalling Helm release $RELEASE..." +helm uninstall "$RELEASE" --namespace "$NAMESPACE" + +log "Helm release uninstalled" + +# ── verify protected resources ─────────────────────────────────────── +log "Verifying protected resources still exist..." + +if kubectl get namespace "$NAMESPACE" &>/dev/null; then + log "Namespace '$NAMESPACE' preserved" +else + echo -e "${RED}[ERR]${NC} Namespace '$NAMESPACE' was deleted!" +fi + +if kubectl get configmap "$CONFIG_MAP" -n "$NAMESPACE" &>/dev/null; then + log "ConfigMap '$CONFIG_MAP' preserved" +else + echo -e "${RED}[ERR]${NC} ConfigMap '$CONFIG_MAP' was deleted!" +fi + +if kubectl get pvc "$PVC_NAME" -n "$NAMESPACE" &>/dev/null; then + log "PVC '$PVC_NAME' preserved" +else + echo -e "${RED}[ERR]${NC} PVC '$PVC_NAME' was deleted!" +fi + +log "Uninstall complete — remaining resources in namespace $NAMESPACE:" +kubectl get all,pvc,configmap,ingress -n "$NAMESPACE" \ No newline at end of file