#!/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 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"