xpeditis2.0/infra/prod/scripts/deploy.sh
2026-09-07 21:40:50 +02:00

127 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Deploiement d'une version en production
# =============================================================================
# export KUBECONFIG=~/.kube/xpeditis-prod.yaml
# bash scripts/deploy.sh prod-a1b2c3d
#
# Sequence :
# 1. verification que les images existent dans le registre
# 2. Job de migration (parallelisme 1) -- bloquant
# 3. mise a jour des images backend et frontend
# 4. attente du deploiement complet
# 5. tests de fumee sur les URLs publiques
# 6. retour arriere automatique si l'une des etapes echoue
#
# C'est la meme sequence que cd-main.yml : ce script est le chemin manuel de
# secours quand GitHub Actions est indisponible.
set -euo pipefail
TAG="${1:?usage: $0 <tag-image> ex: prod-a1b2c3d}"
NAMESPACE="${NAMESPACE:-xpeditis-prod}"
REGISTRY="${REGISTRY:-rg.fr-par.scw.cloud/weworkstudio}"
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
K8S_DIR="${HERE}/../k8s"
log() { printf '\n>>> %s\n' "$*"; }
fail() { printf '\nECHEC: %s\n' "$*" >&2; exit 1; }
rollback() {
log "RETOUR ARRIERE"
kubectl -n "$NAMESPACE" rollout undo deploy/xpeditis-backend || true
kubectl -n "$NAMESPACE" rollout undo deploy/xpeditis-frontend || true
kubectl -n "$NAMESPACE" rollout status deploy/xpeditis-backend --timeout=180s || true
kubectl -n "$NAMESPACE" rollout status deploy/xpeditis-frontend --timeout=180s || true
cat >&2 <<'MSG'
Les deploiements sont revenus a la version precedente.
ATTENTION : les MIGRATIONS DE BASE, elles, ne sont pas annulees. Si la version
retiree contenait une migration destructrice (colonne supprimee, type change),
l'ancienne version applicative peut ne plus fonctionner contre le schema
courant. Voir docs/mise-en-prod/15-exploitation-incidents.md, "Retour arriere
avec migration".
MSG
exit 1
}
# --- 0. Preconditions --------------------------------------------------------
kubectl get ns "$NAMESPACE" >/dev/null || fail "namespace $NAMESPACE introuvable"
kubectl -n "$NAMESPACE" get secret regcred >/dev/null \
|| fail "secret 'regcred' absent : les images ne pourront pas etre telechargees"
kubectl -n "$NAMESPACE" get secret xpeditis-backend-secrets >/dev/null \
|| fail "secrets applicatifs absents : lancez scripts/secrets-apply.sh"
BACKEND_IMAGE="${REGISTRY}/xpeditis-backend:${TAG}"
FRONTEND_IMAGE="${REGISTRY}/xpeditis-frontend:${TAG}"
EXPORTER_IMAGE="${REGISTRY}/xpeditis-log-exporter:${TAG}"
log "Version deployee : ${TAG}"
kubectl -n "$NAMESPACE" get deploy -o wide
# --- 1. Configuration --------------------------------------------------------
log "Application de la configuration (ConfigMap, Ingress, politiques)"
kubectl apply -f "${K8S_DIR}/base/00-namespaces.yaml"
kubectl apply -f "${K8S_DIR}/base/01-limits.yaml"
kubectl apply -f "${K8S_DIR}/base/02-configmap-backend.yaml"
kubectl apply -f "${K8S_DIR}/base/08-traefik-middlewares.yaml"
kubectl apply -f "${K8S_DIR}/base/10-network-policies.yaml"
kubectl apply -f "${K8S_DIR}/base/11-certificate.yaml"
kubectl apply -f "${K8S_DIR}/base/09-ingress.yaml"
# Empreinte de la configuration : sans elle, un changement de ConfigMap ne
# provoque aucun redemarrage et reste sans effet jusqu'au deploiement suivant.
CONFIG_SUM="$(kubectl -n "$NAMESPACE" get cm xpeditis-backend-config -o yaml \
| sha256sum | cut -c1-16)"
# --- 2. Migrations -----------------------------------------------------------
JOB_NAME="xpeditis-migrate-${TAG//[^a-z0-9-]/-}"
log "Migrations de base (Job ${JOB_NAME})"
kubectl -n "$NAMESPACE" delete job "$JOB_NAME" --ignore-not-found >/dev/null
sed -e "s|__IMAGE_TAG__|${TAG}|g" "${K8S_DIR}/base/07-migration-job.yaml" \
| kubectl apply -f -
if ! kubectl -n "$NAMESPACE" wait --for=condition=complete "job/${JOB_NAME}" --timeout=900s; then
echo "--- journaux du Job de migration ---" >&2
kubectl -n "$NAMESPACE" logs "job/${JOB_NAME}" --tail=200 >&2 || true
fail "les migrations ont echoue : AUCUNE image n'a ete deployee, la production tourne toujours sur la version precedente"
fi
kubectl -n "$NAMESPACE" logs "job/${JOB_NAME}" --tail=50
# --- 3. Deploiement ----------------------------------------------------------
log "Mise a jour du backend"
kubectl -n "$NAMESPACE" patch deploy xpeditis-backend --type=strategic -p \
"{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"xpeditis.com/config-checksum\":\"${CONFIG_SUM}\"}}}}}"
kubectl -n "$NAMESPACE" set image deploy/xpeditis-backend "backend=${BACKEND_IMAGE}"
kubectl -n "$NAMESPACE" rollout status deploy/xpeditis-backend --timeout=300s || rollback
log "Mise a jour du frontend"
kubectl -n "$NAMESPACE" set image deploy/xpeditis-frontend "frontend=${FRONTEND_IMAGE}"
kubectl -n "$NAMESPACE" rollout status deploy/xpeditis-frontend --timeout=300s || rollback
# Le collecteur de logs n'est pas critique : son echec ne doit pas declencher
# un retour arriere de l'application.
log "Mise a jour du log-exporter"
kubectl -n "$NAMESPACE" set image deploy/xpeditis-log-exporter "log-exporter=${EXPORTER_IMAGE}" || true
kubectl -n "$NAMESPACE" rollout status deploy/xpeditis-log-exporter --timeout=180s \
|| log "AVERTISSEMENT: le log-exporter n'a pas demarre (non bloquant)"
# --- 4. Tests de fumee -------------------------------------------------------
log "Tests de fumee"
if ! bash "${HERE}/smoke-test.sh"; then
rollback
fi
# --- 5. Compte rendu ---------------------------------------------------------
log "Deploiement termine"
kubectl -n "$NAMESPACE" get pods -o wide
echo
echo "Backend : ${BACKEND_IMAGE}"
echo "Frontend : ${FRONTEND_IMAGE}"
echo
echo "Retour arriere manuel si necessaire :"
echo " kubectl -n ${NAMESPACE} rollout undo deploy/xpeditis-backend"
echo " kubectl -n ${NAMESPACE} rollout undo deploy/xpeditis-frontend"