9.4 KiB
9.4 KiB
Runbook — Migration Client Pilote vers Production
Applicable à : Clients A (TechVision ESN) et B (RH Conseil) Durée estimée : 2–4 heures par client (fenêtre de maintenance recommandée) Prérequis : Cluster production opérationnel (EKS eu-west-3), Keycloak prod configuré
Vue d'ensemble
Staging (api-staging.veylant.ai) Production (api.veylant.ai)
│ │
├── PostgreSQL staging DB →→→→→→→→ ├── PostgreSQL production DB
├── Keycloak staging realm →→→→→→→→ ├── Keycloak production realm
├── Redis staging ├── Redis production
└── Utilisateurs staging └── Utilisateurs production
Phase 1 — Pré-migration (J-1)
1.1 Backup complet du staging
# Backup PostgreSQL staging
kubectl exec -n veylant deploy/postgres -- \
pg_dump -U veylant veylant_db | gzip > backup_staging_$(date +%Y%m%d).sql.gz
# Vérifier le backup
gunzip -t backup_staging_$(date +%Y%m%d).sql.gz && echo "Backup OK"
# Uploader vers S3 (conservation pendant la migration)
aws s3 cp backup_staging_$(date +%Y%m%d).sql.gz \
s3://veylant-backups-production/migration/
1.2 Inventaire des utilisateurs à migrer
# Exporter la liste des utilisateurs Keycloak staging
kubectl exec -n keycloak deploy/keycloak -- \
/opt/keycloak/bin/kcadm.sh get users \
-r veylant-staging \
--server http://localhost:8080 \
--realm master \
--user admin --password admin \
> users_staging.json
# Compter les utilisateurs actifs (30 derniers jours)
psql "$STAGING_DB_URL" -c \
"SELECT COUNT(*) FROM users WHERE last_login > NOW() - INTERVAL '30 days';"
1.3 Validation de l'environnement production
# Vérifier que le cluster production est opérationnel
kubectl get nodes -n veylant --context=production
kubectl get pods -n veylant --context=production
# Vérifier la connectivité API production
curl -sf https://api.veylant.ai/healthz | jq .
# Vérifier Keycloak production
curl -sf https://auth.veylant.ai/realms/veylant/.well-known/openid-configuration | jq .issuer
# Confirmer le backup automatique actif
kubectl get cronjob veylant-postgres-backup -n veylant --context=production
1.4 Communication client
- Envoyer email de notification J-1 (fenêtre de maintenance, impact estimé)
- Confirmer contact technique côté client disponible pendant la migration
- Partager le runbook rollback avec le client
Phase 2 — Migration des données PostgreSQL
2.1 Export depuis staging
# Export complet avec données clients seulement (pas les configs système)
pg_dump \
--host="$STAGING_DB_HOST" \
--username="$STAGING_DB_USER" \
--dbname="$STAGING_DB_NAME" \
--table=users \
--table=api_keys \
--table=routing_rules \
--table=gdpr_processing_registry \
--table=ai_act_classifications \
--format=custom \
--no-privileges \
--no-owner \
-f migration_data.dump
echo "Export size: $(du -sh migration_data.dump)"
2.2 Import vers production
# Appliquer les migrations DDL d'abord (production doit être à jour)
kubectl exec -n veylant deploy/veylant-proxy --context=production -- \
/app/proxy migrate up
# Import des données
pg_restore \
--host="$PROD_DB_HOST" \
--username="$PROD_DB_USER" \
--dbname="$PROD_DB_NAME" \
--no-privileges \
--no-owner \
--clean \
--if-exists \
-v \
migration_data.dump
# Vérifier l'intégrité
psql "$PROD_DB_URL" -c "SELECT COUNT(*) FROM users;"
psql "$PROD_DB_URL" -c "SELECT COUNT(*) FROM routing_rules;"
2.3 Vérification post-import
# Comparer les compteurs staging vs production
STAGING_USERS=$(psql "$STAGING_DB_URL" -t -c "SELECT COUNT(*) FROM users;")
PROD_USERS=$(psql "$PROD_DB_URL" -t -c "SELECT COUNT(*) FROM users;")
echo "Staging users: $STAGING_USERS | Production users: $PROD_USERS"
if [ "$STAGING_USERS" != "$PROD_USERS" ]; then
echo "ERROR: User count mismatch — abort migration"
exit 1
fi
Phase 3 — Reconfiguration Keycloak Production
3.1 Création du realm production
# Se connecter à Keycloak production
KEYCLOAK_URL="https://auth.veylant.ai"
KEYCLOAK_ADMIN_TOKEN=$(curl -s \
-d "client_id=admin-cli" \
-d "username=admin" \
-d "password=$KEYCLOAK_ADMIN_PASSWORD" \
-d "grant_type=password" \
"$KEYCLOAK_URL/realms/master/protocol/openid-connect/token" | jq -r .access_token)
# Importer la configuration du realm depuis staging
# (exportée au format JSON lors de la phase 1.2)
curl -sf -X POST \
-H "Authorization: Bearer $KEYCLOAK_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d @realm-export.json \
"$KEYCLOAK_URL/admin/realms"
3.2 Import des utilisateurs
# Importer les utilisateurs avec leurs rôles
# Note: les mots de passe ne peuvent pas être migrés — les utilisateurs recevront un email de reset
for user in $(jq -r '.[].id' users_staging.json); do
USER_DATA=$(jq --arg id "$user" '.[] | select(.id == $id)' users_staging.json)
curl -sf -X POST \
-H "Authorization: Bearer $KEYCLOAK_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "$USER_DATA" \
"$KEYCLOAK_URL/admin/realms/veylant/users"
done
echo "Imported $(jq length users_staging.json) users"
3.3 Réinitialisation des mots de passe
# Envoyer un email de reset de mot de passe à tous les utilisateurs migrés
USER_IDS=$(curl -sf \
-H "Authorization: Bearer $KEYCLOAK_ADMIN_TOKEN" \
"$KEYCLOAK_URL/admin/realms/veylant/users?max=1000" | jq -r '.[].id')
for USER_ID in $USER_IDS; do
curl -sf -X PUT \
-H "Authorization: Bearer $KEYCLOAK_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '["UPDATE_PASSWORD"]' \
"$KEYCLOAK_URL/admin/realms/veylant/users/$USER_ID/execute-actions-email"
sleep 0.1 # Rate limit emails
done
Phase 4 — Validation
4.1 Smoke tests API
# Obtenir un token de test (compte admin pré-créé)
TOKEN=$(curl -sf \
-d "client_id=veylant-api" \
-d "username=admin-test@veylant.ai" \
-d "password=$TEST_ADMIN_PASSWORD" \
-d "grant_type=password" \
"https://auth.veylant.ai/realms/veylant/protocol/openid-connect/token" | jq -r .access_token)
# Test endpoints principaux
curl -sf -H "Authorization: Bearer $TOKEN" https://api.veylant.ai/v1/admin/users | jq length
curl -sf -H "Authorization: Bearer $TOKEN" https://api.veylant.ai/v1/admin/routing-rules | jq length
# Test proxy (avec model user-role)
curl -sf -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Hello"}]}' \
https://api.veylant.ai/v1/chat/completions | jq .choices[0].message.content
echo "Smoke tests passed"
4.2 Validation des audit logs
# Vérifier que les logs sont bien envoyés à ClickHouse
curl -sf -H "Authorization: Bearer $TOKEN" \
"https://api.veylant.ai/v1/admin/logs?limit=5" | jq '.[].request_id'
4.3 Validation du dashboard
# Ouvrir le dashboard client et vérifier les métriques
open "https://dashboard.veylant.ai"
# Vérifier manuellement : graphiques RPS, latence, erreurs, PII
Phase 5 — Cutover SSO (Go-Live)
5.1 Mise à jour des URLs côté client
Informer le contact technique du client de mettre à jour :
| Paramètre | Staging | Production |
|---|---|---|
base_url OpenAI SDK |
https://api-staging.veylant.ai/v1 |
https://api.veylant.ai/v1 |
| OIDC Issuer (si SAML) | https://auth-staging.veylant.ai/realms/veylant |
https://auth.veylant.ai/realms/veylant |
| Dashboard | https://dashboard-staging.veylant.ai |
https://dashboard.veylant.ai |
5.2 Mise à jour CORS production
# Ajouter le domaine dashboard client dans config.yaml production
# Exemple Client B (RH Conseil) : dashboard sur dashboard.rh-conseil.fr
kubectl edit configmap veylant-proxy-config -n veylant --context=production
# Ajouter sous server.allowed_origins:
# - "https://dashboard.rh-conseil.fr"
# Redémarrer le proxy pour prendre en compte la nouvelle config
kubectl rollout restart deployment/veylant-proxy-blue -n veylant --context=production
kubectl rollout status deployment/veylant-proxy-blue -n veylant --context=production
5.3 Confirmation Go-Live
- Envoyer email de confirmation au client : migration réussie
- Planifier NPS de suivi J+7
- Archiver le dump staging utilisé pour la migration
Rollback
Rollback Phase 2 (avant cutover)
# Restaurer la base production depuis le backup staging
pg_restore \
--host="$PROD_DB_HOST" \
--username="$PROD_DB_USER" \
--dbname="$PROD_DB_NAME" \
--clean \
migration_data.dump
echo "Rollback Phase 2 terminé — base production restaurée"
Rollback Phase 5 (après cutover)
# Rediriger le trafic vers staging (intervention DNS)
# Contact ops@veylant.ai immédiatement
# Informer le client : retour en staging, investigation en cours
# ETA rollback DNS : < 5 minutes (TTL court configuré en préparation)
Checklist finale
- Backup staging conservé 30 jours
- Tous les utilisateurs ont reçu l'email de reset mot de passe
- Smoke tests API passés
- Dashboard client accessible
- CORS mis à jour avec domaine client
- NPS suivi planifié J+7
- Staging désactivé après 2 semaines (coûts)